Merge "Revert "Remove telephony support for car builds.""
diff --git a/EncryptionRunner/Android.bp b/EncryptionRunner/Android.bp
index 7910b73..c82d769 100644
--- a/EncryptionRunner/Android.bp
+++ b/EncryptionRunner/Android.bp
@@ -29,25 +29,3 @@
installable: true,
}
-android_test {
- name: "EncryptionRunnerTest",
- min_sdk_version: "23",
- srcs: [
- "test/**/*.java",
- ],
- product_variables: {
- pdk: {
- enabled: false,
- },
- },
- libs: [
- "android.test.base",
- "android.test.runner",
- ],
- static_libs: [
- "androidx.test.rules",
- "EncryptionRunner",
- "junit",
- "truth-prebuilt",
- ],
-}
diff --git a/EncryptionRunner/AndroidManifest.xml b/EncryptionRunner/AndroidManifest.xml
index 9b76d15..3ebdf42 100644
--- a/EncryptionRunner/AndroidManifest.xml
+++ b/EncryptionRunner/AndroidManifest.xml
@@ -18,5 +18,4 @@
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="android.car.encryptionrunner" >
<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="23" />
- <application />
</manifest>
diff --git a/EncryptionRunner/src/android/car/encryptionrunner/DummyEncryptionRunner.java b/EncryptionRunner/src/android/car/encryptionrunner/DummyEncryptionRunner.java
index f38bf65..5b63dbc 100644
--- a/EncryptionRunner/src/android/car/encryptionrunner/DummyEncryptionRunner.java
+++ b/EncryptionRunner/src/android/car/encryptionrunner/DummyEncryptionRunner.java
@@ -31,6 +31,7 @@
public class DummyEncryptionRunner implements EncryptionRunner {
private static final String KEY = "key";
+ private static final byte[] DUMMY_MESSAGE = "Dummy Message".getBytes();
@VisibleForTesting
public static final String INIT = "init";
@VisibleForTesting
@@ -48,6 +49,9 @@
int SERVER = 2;
}
+ private boolean mIsReconnect;
+ private boolean mInitReconnectVerification;
+ private Key mCurrentDummyKey;
@Mode
private int mMode;
@HandshakeMessage.HandshakeState
@@ -90,12 +94,16 @@
if (mState != HandshakeMessage.HandshakeState.IN_PROGRESS) {
throw new HandshakeException("not waiting for response but got one");
}
- switch(mMode) {
+ switch (mMode) {
case Mode.SERVER:
if (!CLIENT_RESPONSE.equals(new String(response))) {
throw new HandshakeException("unexpected response: " + new String(response));
}
mState = HandshakeMessage.HandshakeState.VERIFICATION_NEEDED;
+ if (mIsReconnect) {
+ verifyPin();
+ mState = HandshakeMessage.HandshakeState.RESUMING_SESSION;
+ }
return HandshakeMessage.newBuilder()
.setVerificationCode(VERIFICATION_CODE)
.setHandshakeState(mState)
@@ -105,17 +113,44 @@
throw new HandshakeException("unexpected response: " + new String(response));
}
mState = HandshakeMessage.HandshakeState.VERIFICATION_NEEDED;
+ if (mIsReconnect) {
+ verifyPin();
+ mState = HandshakeMessage.HandshakeState.RESUMING_SESSION;
+ }
return HandshakeMessage.newBuilder()
.setHandshakeState(mState)
.setNextMessage(CLIENT_RESPONSE.getBytes())
.setVerificationCode(VERIFICATION_CODE)
.build();
default:
- throw new IllegalStateException("unexpected state: " + mState);
+ throw new IllegalStateException("unexpected role: " + mMode);
}
}
@Override
+ public HandshakeMessage authenticateReconnection(byte[] message, byte[] previousKey)
+ throws HandshakeException {
+ mCurrentDummyKey = new DummyKey();
+ // Blindly verify the reconnection because this is a dummy encryption runner.
+ return HandshakeMessage.newBuilder()
+ .setHandshakeState(HandshakeMessage.HandshakeState.FINISHED)
+ .setKey(mCurrentDummyKey)
+ .setNextMessage(mInitReconnectVerification ? null : DUMMY_MESSAGE)
+ .build();
+ }
+
+ @Override
+ public HandshakeMessage initReconnectAuthentication(byte[] previousKey)
+ throws HandshakeException {
+ mInitReconnectVerification = true;
+ mState = HandshakeMessage.HandshakeState.RESUMING_SESSION;
+ return HandshakeMessage.newBuilder()
+ .setHandshakeState(mState)
+ .setNextMessage(DUMMY_MESSAGE)
+ .build();
+ }
+
+ @Override
public Key keyOf(byte[] serialized) {
return new DummyKey();
}
@@ -126,10 +161,8 @@
throw new IllegalStateException("asking to verify pin, state = " + mState);
}
mState = HandshakeMessage.HandshakeState.FINISHED;
- return HandshakeMessage.newBuilder()
- .setHandshakeState(mState)
- .setKey(new DummyKey())
- .build();
+ return HandshakeMessage.newBuilder().setKey(new DummyKey()).setHandshakeState(
+ mState).build();
}
@Override
@@ -137,8 +170,12 @@
mState = HandshakeMessage.HandshakeState.INVALID;
}
- private class DummyKey implements Key {
+ @Override
+ public void setIsReconnect(boolean isReconnect) {
+ mIsReconnect = isReconnect;
+ }
+ private class DummyKey implements Key {
@Override
public byte[] asBytes() {
return KEY.getBytes();
@@ -153,5 +190,10 @@
public byte[] decryptData(byte[] encryptedData) {
return encryptedData;
}
+
+ @Override
+ public byte[] getUniqueSession() {
+ return KEY.getBytes();
+ }
}
}
diff --git a/EncryptionRunner/src/android/car/encryptionrunner/EncryptionRunner.java b/EncryptionRunner/src/android/car/encryptionrunner/EncryptionRunner.java
index ad444bc..f0a34b2 100644
--- a/EncryptionRunner/src/android/car/encryptionrunner/EncryptionRunner.java
+++ b/EncryptionRunner/src/android/car/encryptionrunner/EncryptionRunner.java
@@ -23,39 +23,63 @@
* messages.
*
* To use this interface:
- * 1. As a client.
*
- * HandshakeMessage initialClientMessage = clientRunner.initHandshake();
- * sendToServer(initialClientMessage.getNextMessage());
- * byte message = getServerResponse();
+ * <p>1. As a client.
*
- * HandshakeMessage message = clientRunner.continueHandshake(message);
- * message.getHandshakeState() should be VERIFICATION_NEEDED,
- * otherwise if IN_PROGRESS just send the result of getNextMessage();
+ * {@code
+ * HandshakeMessage initialClientMessage = clientRunner.initHandshake();
+ * sendToServer(initialClientMessage.getNextMessage());
+ * byte message = getServerResponse();
+ * HandshakeMessage message = clientRunner.continueHandshake(message);
+ * }
*
- * Show user the verification code and ask to verify.
- * message.getVerificationCode()
+ * <p>If it is a first-time connection,
*
- * if user agrees
- * HandshakeMessage lastMessage = clientRunner.verifyPin();
- * otherwise
- * clientRunner.invalidPin();
+ * {@code message.getHandshakeState()} should be VERIFICATION_NEEDED, show user the verification
+ * code and ask to verify.
+ * After user confirmed, {@code HandshakeMessage lastMessage = clientRunner.verifyPin();} otherwise
+ * {@code clientRunner.invalidPin(); }
*
- * Use lastMessage.getKey() for encryption.
+ * Use {@code lastMessage.getKey()} to get the key for encryption.
*
- * 2. As a server.
+ * <p>If it is a reconnection,
*
- * byte[] initialMessage = getClientMessageBytes();
- * HandshakeMesssage message = serverRunner.respondToInitRequest(initialMessage);
+ * {@code message.getHandshakeState()} should be RESUMING_SESSION, PIN has been verified blindly,
+ * send the authentication message over to server, then authenticate the message from server.
*
- * sendToClient(message.getNextMessage());
+ * {@code
+ * clientMessage = clientRunner.initReconnectAuthentication(previousKey)
+ * sendToServer(clientMessage.getNextMessage());
+ * HandshakeMessage lastMessage = clientRunner.authenticateReconnection(previousKey, message)
+ * }
*
- * message.getHandshakeState() should be VERIFICATION_NEEDED,
- * if so show user code and ask to verify
- * message.getVerificationCode();
+ * {@code lastMessage.getHandshakeState()} should be FINISHED if reconnection handshake is done.
*
- * serverRunner.verifyPin or invalidPin and continue same as client above.
+ * <p>2. As a server.
*
+ * {@code
+ * byte[] initialMessage = getClientMessageBytes();
+ * HandshakeMessage message = serverRunner.respondToInitRequest(initialMessage);
+ * sendToClient(message.getNextMessage());
+ * byte[] clientMessage = getClientResponse();
+ * HandshakeMessage message = serverRunner.continueHandshake(clientMessage);}
+ *
+ * <p>if it is a first-time connection,
+ *
+ * {@code message.getHandshakeState()} should be VERIFICATION_NEEDED, show user the verification
+ * code and ask to verify.
+ * After PIN is confirmed, {@code HandshakeMessage lastMessage = serverRunner.verifyPin}, otherwise
+ * {@code clientRunner.invalidPin(); }
+ * Use {@code lastMessage.getKey()} to get the key for encryption.
+ *
+ * <p>If it is a reconnection,
+ *
+ * {@code message.getHandshakeState()} should be RESUMING_SESSION,PIN has been verified blindly,
+ * waiting for client message.
+ * After client message been received,
+ * {@code serverMessage = serverRunner.authenticateReconnection(previousKey, message);
+ * sendToClient(serverMessage.getNextMessage());}
+ * {@code serverMessage.getHandshakeState()} should be FINISHED if reconnection handshake is done.
*
* Also see {@link EncryptionRunnerTest} for examples.
*/
@@ -68,6 +92,7 @@
*
* @return A handshake message with information about the handshake that is started.
*/
+ @NonNull
HandshakeMessage initHandshake();
/**
@@ -76,9 +101,9 @@
*
* @param initializationRequest the bytes that the other device sent over.
* @return a handshake message with information about the handshake.
- *
* @throws HandshakeException if initialization request is invalid.
*/
+ @NonNull
HandshakeMessage respondToInitRequest(@NonNull byte[] initializationRequest)
throws HandshakeException;
@@ -87,9 +112,9 @@
*
* @param response the response from the other device.
* @return a message that can be used to continue the handshake.
- *
* @throws HandshakeException if unexpected bytes in response.
*/
+ @NonNull
HandshakeMessage continueHandshake(@NonNull byte[] response) throws HandshakeException;
/**
@@ -98,6 +123,7 @@
*
* @throws HandshakeException if not in state to verify pin.
*/
+ @NonNull
HandshakeMessage verifyPin() throws HandshakeException;
/**
@@ -107,11 +133,49 @@
void invalidPin();
/**
+ * Verifies the reconnection message.
+ *
+ * <p>The message passed to this method should have been generated by
+ * {@link #initReconnectAuthentication(byte[] previousKey)}.
+ *
+ * <p>If the message is valid, then a {@link HandshakeMessage} will be returned that contains
+ * the encryption key and a handshake message which can be used to verify the other side of the
+ * connection.
+ *
+ * @param previousKey previously stored key.
+ * @param message message from the client
+ * @return a handshake message with an encryption key if verification succeed.
+ * @throws HandshakeException if the message does not match.
+ */
+ @NonNull
+ HandshakeMessage authenticateReconnection(@NonNull byte[] message, @NonNull byte[] previousKey)
+ throws HandshakeException;
+
+ /**
+ * Initiates the reconnection verification by generating a message that should be sent to the
+ * device that is being reconnected to.
+ *
+ * @param previousKey previously stored key.
+ * @return a handshake message with client's message which will be sent to server.
+ * @throws HandshakeException when get encryption key's unique session fail.
+ */
+ @NonNull
+ HandshakeMessage initReconnectAuthentication(@NonNull byte[] previousKey)
+ throws HandshakeException;
+
+ /**
* De-serializes a previously serialized key generated by an instance of this encryption runner.
*
* @param serialized the serialized bytes of the key.
* @return the Key object used for encryption.
*/
+ @NonNull
Key keyOf(@NonNull byte[] serialized);
+ /**
+ * Set the signal if it is a reconnection process.
+ *
+ * @param isReconnect {@code true} if it is a reconnect.
+ */
+ void setIsReconnect(boolean isReconnect);
}
diff --git a/EncryptionRunner/src/android/car/encryptionrunner/HandshakeMessage.java b/EncryptionRunner/src/android/car/encryptionrunner/HandshakeMessage.java
index 347c9fa..fa6705d 100644
--- a/EncryptionRunner/src/android/car/encryptionrunner/HandshakeMessage.java
+++ b/EncryptionRunner/src/android/car/encryptionrunner/HandshakeMessage.java
@@ -33,12 +33,8 @@
* States for handshake progress.
*/
@Retention(RetentionPolicy.SOURCE)
- @IntDef({
- HandshakeState.UNKNOWN,
- HandshakeState.IN_PROGRESS,
- HandshakeState.VERIFICATION_NEEDED,
- HandshakeState.FINISHED,
- HandshakeState.INVALID})
+ @IntDef({HandshakeState.UNKNOWN, HandshakeState.IN_PROGRESS, HandshakeState.VERIFICATION_NEEDED,
+ HandshakeState.FINISHED, HandshakeState.INVALID, HandshakeState.RESUMING_SESSION,})
public @interface HandshakeState {
/**
* The initial state, this value is not expected to be returned.
@@ -60,9 +56,14 @@
* The handshake is complete and not successful.
*/
int INVALID = 4;
+ /**
+ * The handshake is complete, but extra verification is needed.
+ */
+ int RESUMING_SESSION = 5;
}
- @HandshakeState private final int mHandshakeState;
+ @HandshakeState
+ private final int mHandshakeState;
private final Key mKey;
private final byte[] mNextMessage;
private final String mVerificationCode;
@@ -121,7 +122,8 @@
}
static class Builder {
- @HandshakeState int mHandshakeState;
+ @HandshakeState
+ int mHandshakeState;
Key mKey;
byte[] mNextMessage;
String mVerificationCode;
diff --git a/EncryptionRunner/src/android/car/encryptionrunner/Key.java b/EncryptionRunner/src/android/car/encryptionrunner/Key.java
index ce35e98..2e32858 100644
--- a/EncryptionRunner/src/android/car/encryptionrunner/Key.java
+++ b/EncryptionRunner/src/android/car/encryptionrunner/Key.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
+import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
/**
@@ -27,7 +28,8 @@
/**
* Returns a serialized encryption key.
*/
- @NonNull byte[] asBytes();
+ @NonNull
+ byte[] asBytes();
/**
* Encrypts data using this key.
@@ -35,6 +37,7 @@
* @param data the data to be encrypted
* @return the encrypted data.
*/
+ @NonNull
byte[] encryptData(@NonNull byte[] data);
/**
@@ -42,8 +45,16 @@
*
* @param encryptedData The encrypted data.
* @return decrypted data.
- *
* @throws SignatureException if encrypted data is not properly signed.
*/
+ @NonNull
byte[] decryptData(@NonNull byte[] encryptedData) throws SignatureException;
+
+ /**
+ * Returns a cryptographic digest of the key.
+ *
+ * @throws NoSuchAlgorithmException when a unique session can not be created.
+ */
+ @NonNull
+ byte[] getUniqueSession() throws NoSuchAlgorithmException;
}
diff --git a/EncryptionRunner/src/android/car/encryptionrunner/Ukey2EncryptionRunner.java b/EncryptionRunner/src/android/car/encryptionrunner/Ukey2EncryptionRunner.java
index eed7852..904d5c2 100644
--- a/EncryptionRunner/src/android/car/encryptionrunner/Ukey2EncryptionRunner.java
+++ b/EncryptionRunner/src/android/car/encryptionrunner/Ukey2EncryptionRunner.java
@@ -16,16 +16,26 @@
package android.car.encryptionrunner;
+import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.google.security.cryptauth.lib.securegcm.D2DConnectionContext;
import com.google.security.cryptauth.lib.securegcm.Ukey2Handshake;
+import com.google.security.cryptauth.lib.securemessage.CryptoOps;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
+import javax.crypto.spec.SecretKeySpec;
+
/**
* An {@link EncryptionRunner} that uses Ukey2 as the underlying implementation.
*/
@@ -33,15 +43,33 @@
private static final Ukey2Handshake.HandshakeCipher CIPHER =
Ukey2Handshake.HandshakeCipher.P256_SHA512;
-
+ private static final int RESUME_HMAC_LENGTH = 32;
+ private static final byte[] RESUME = "RESUME".getBytes();
+ private static final byte[] SERVER = "SERVER".getBytes();
+ private static final byte[] CLIENT = "CLIENT".getBytes();
private static final int AUTH_STRING_LENGTH = 6;
+ @IntDef({Mode.UNKNOWN, Mode.CLIENT, Mode.SERVER})
+ private @interface Mode {
+ int UNKNOWN = 0;
+ int CLIENT = 1;
+ int SERVER = 2;
+ }
+
private Ukey2Handshake mUkey2client;
private boolean mRunnerIsInvalid;
+ private Key mCurrentKey;
+ private byte[] mCurrentUniqueSesion;
+ private byte[] mPrevUniqueSesion;
+ private boolean mIsReconnect;
+ private boolean mInitReconnectionVerification;
+ @Mode
+ private int mMode = Mode.UNKNOWN;
@Override
public HandshakeMessage initHandshake() {
checkRunnerIsNew();
+ mMode = Mode.CLIENT;
try {
mUkey2client = Ukey2Handshake.forInitiator(CIPHER);
return HandshakeMessage.newBuilder()
@@ -56,9 +84,15 @@
}
@Override
+ public void setIsReconnect(boolean isReconnect) {
+ mIsReconnect = isReconnect;
+ }
+
+ @Override
public HandshakeMessage respondToInitRequest(byte[] initializationRequest)
throws HandshakeException {
checkRunnerIsNew();
+ mMode = Mode.SERVER;
try {
if (mUkey2client != null) {
throw new IllegalStateException("Cannot reuse encryption runners, "
@@ -101,11 +135,18 @@
if (mUkey2client.getHandshakeState() == Ukey2Handshake.State.IN_PROGRESS) {
nextMessage = mUkey2client.getNextHandshakeMessage();
}
-
String verificationCode = null;
if (mUkey2client.getHandshakeState() == Ukey2Handshake.State.VERIFICATION_NEEDED) {
+ // getVerificationString() needs to be called before verifyPin().
verificationCode = generateReadablePairingCode(
mUkey2client.getVerificationString(AUTH_STRING_LENGTH));
+ if (mIsReconnect) {
+ HandshakeMessage handshakeMessage = verifyPin();
+ return HandshakeMessage.newBuilder()
+ .setHandshakeState(handshakeMessage.getHandshakeState())
+ .setNextMessage(nextMessage)
+ .build();
+ }
}
return HandshakeMessage.newBuilder()
.setHandshakeState(getHandshakeState())
@@ -158,20 +199,128 @@
public byte[] decryptData(byte[] encryptedData) throws SignatureException {
return mConnectionContext.decodeMessageFromPeer(encryptedData);
}
+
+ @Override
+ public byte[] getUniqueSession() throws NoSuchAlgorithmException {
+ return mConnectionContext.getSessionUnique();
+ }
}
@Override
public HandshakeMessage verifyPin() throws HandshakeException {
checkInitialized();
mUkey2client.verifyHandshake();
+ int state = getHandshakeState();
try {
- return HandshakeMessage.newBuilder()
- .setHandshakeState(getHandshakeState())
- .setKey(new UKey2Key(mUkey2client.toConnectionContext()))
- .build();
+ mCurrentKey = new UKey2Key(mUkey2client.toConnectionContext());
} catch (com.google.security.cryptauth.lib.securegcm.HandshakeException e) {
throw new HandshakeException(e);
}
+ return HandshakeMessage.newBuilder()
+ .setHandshakeState(state)
+ .setKey(mCurrentKey)
+ .build();
+ }
+
+ /**
+ * <p>After getting message from the other device, authenticate the message with the previous
+ * stored key.
+ *
+ * If current device inits the reconnection authentication by calling {@code
+ * initReconnectAuthentication} and sends the message to the other device, the other device
+ * will call {@code authenticateReconnection()} with the received message and send its own
+ * message back to the init device. The init device will call {@code
+ * authenticateReconnection()} on the received message, but do not need to set the next
+ * message.
+ */
+ @Override
+ public HandshakeMessage authenticateReconnection(byte[] message, byte[] previousKey)
+ throws HandshakeException {
+ if (!mIsReconnect) {
+ throw new HandshakeException(
+ "Reconnection authentication requires setIsReconnect(true)");
+ }
+ if (mCurrentKey == null) {
+ throw new HandshakeException("Current key is null, make sure verifyPin() is called.");
+ }
+ if (message.length != RESUME_HMAC_LENGTH) {
+ mRunnerIsInvalid = true;
+ throw new HandshakeException("Failing because (message.length =" + message.length
+ + ") is not equal to " + RESUME_HMAC_LENGTH);
+ }
+ try {
+ mCurrentUniqueSesion = mCurrentKey.getUniqueSession();
+ mPrevUniqueSesion = keyOf(previousKey).getUniqueSession();
+ } catch (NoSuchAlgorithmException e) {
+ throw new HandshakeException(e);
+ }
+ switch (mMode) {
+ case Mode.SERVER:
+ if (!MessageDigest.isEqual(
+ message, computeMAC(mPrevUniqueSesion, mCurrentUniqueSesion, CLIENT))) {
+ mRunnerIsInvalid = true;
+ throw new HandshakeException("Reconnection authentication failed.");
+ }
+ return HandshakeMessage.newBuilder()
+ .setHandshakeState(HandshakeMessage.HandshakeState.FINISHED)
+ .setKey(mCurrentKey)
+ .setNextMessage(mInitReconnectionVerification ? null
+ : computeMAC(mPrevUniqueSesion, mCurrentUniqueSesion, SERVER))
+ .build();
+ case Mode.CLIENT:
+ if (!MessageDigest.isEqual(
+ message, computeMAC(mPrevUniqueSesion, mCurrentUniqueSesion, SERVER))) {
+ mRunnerIsInvalid = true;
+ throw new HandshakeException("Reconnection authentication failed.");
+ }
+ return HandshakeMessage.newBuilder()
+ .setHandshakeState(HandshakeMessage.HandshakeState.FINISHED)
+ .setKey(mCurrentKey)
+ .setNextMessage(mInitReconnectionVerification ? null
+ : computeMAC(mPrevUniqueSesion, mCurrentUniqueSesion, CLIENT))
+ .build();
+ default:
+ throw new IllegalStateException(
+ "Encountered unexpected role during authenticateReconnection: " + mMode);
+ }
+ }
+
+ /**
+ * Both client and server can call this method to send authentication message to the other
+ * device.
+ */
+ @Override
+ public HandshakeMessage initReconnectAuthentication(byte[] previousKey)
+ throws HandshakeException {
+ if (!mIsReconnect) {
+ throw new HandshakeException(
+ "Reconnection authentication requires setIsReconnect(true).");
+ }
+ if (mCurrentKey == null) {
+ throw new HandshakeException("Current key is null, make sure verifyPin() is called.");
+ }
+ mInitReconnectionVerification = true;
+ try {
+ mCurrentUniqueSesion = mCurrentKey.getUniqueSession();
+ mPrevUniqueSesion = keyOf(previousKey).getUniqueSession();
+ } catch (NoSuchAlgorithmException e) {
+ throw new HandshakeException(e);
+ }
+ switch (mMode) {
+ case Mode.SERVER:
+ return HandshakeMessage.newBuilder()
+ .setHandshakeState(HandshakeMessage.HandshakeState.RESUMING_SESSION)
+ .setNextMessage(computeMAC(mPrevUniqueSesion, mCurrentUniqueSesion, SERVER))
+ .build();
+ case Mode.CLIENT:
+ return HandshakeMessage.newBuilder()
+ .setHandshakeState(HandshakeMessage.HandshakeState.RESUMING_SESSION)
+ .setNextMessage(computeMAC(mPrevUniqueSesion, mCurrentUniqueSesion, CLIENT))
+ .build();
+ default:
+ throw new IllegalStateException(
+ "Encountered unexpected role during authenticateReconnection: " + mMode);
+ }
}
@HandshakeMessage.HandshakeState
@@ -182,6 +331,9 @@
case ERROR:
throw new IllegalStateException("unexpected error state");
case FINISHED:
+ if (mIsReconnect) {
+ return HandshakeMessage.HandshakeState.RESUMING_SESSION;
+ }
return HandshakeMessage.HandshakeState.FINISHED;
case IN_PROGRESS:
return HandshakeMessage.HandshakeState.IN_PROGRESS;
@@ -218,4 +370,28 @@
throw new IllegalStateException("runner has been invalidated");
}
}
+
+ @Nullable
+ private byte[] computeMAC(byte[] previous, byte[] next, byte[] info) {
+ try {
+ SecretKeySpec inputKeyMaterial = new SecretKeySpec(
+ concatByteArrays(previous, next), "" /* key type is just plain raw bytes */);
+ return CryptoOps.hkdf(inputKeyMaterial, RESUME, info);
+ } catch (NoSuchAlgorithmException | InvalidKeyException e) {
+ // Does not happen in practice
+ Log.e(TAG, "Compute MAC failed");
+ return null;
+ }
+ }
+
+ private static byte[] concatByteArrays(@NonNull byte[] a, @NonNull byte[] b) {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ try {
+ outputStream.write(a);
+ outputStream.write(b);
+ } catch (IOException e) {
+ return new byte[0];
+ }
+ return outputStream.toByteArray();
+ }
}
diff --git a/EncryptionRunner/test/android/car/encryptionrunner/EncryptionRunnerTest.java b/EncryptionRunner/test/android/car/encryptionrunner/EncryptionRunnerTest.java
deleted file mode 100644
index c7893ad..0000000
--- a/EncryptionRunner/test/android/car/encryptionrunner/EncryptionRunnerTest.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.car.encryptionrunner;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.util.Log;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import junit.framework.Assert;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class EncryptionRunnerTest {
-
- private static final byte[] sTestData = "test data".getBytes();
- private interface RunnerFactory {
- EncryptionRunner newRunner();
- }
-
- @Test
- public void happyFlow_dummyRunner() throws Exception {
- verifyRunners(EncryptionRunnerFactory::newDummyRunner);
- }
-
- @Test
- public void happyFlow_ukey2Runner() throws Exception {
- verifyRunners(EncryptionRunnerFactory::newRunner);
- }
-
- /**
- * Runs through a happy flow of encryption runners and verifies that they behave as expected.
- * Some * of the test is implementation specific because the interface doesn't specify how many
- * round * trips may be needed but this test makes assumptions( i.e. white box testing).
- */
- private void verifyRunners(RunnerFactory runnerFactory) throws Exception {
- EncryptionRunner clientRunner = runnerFactory.newRunner();
- EncryptionRunner serverRunner = runnerFactory.newRunner();
-
- verifyHandshake(clientRunner, serverRunner);
-
- HandshakeMessage finalServerMessage = serverRunner.verifyPin();
- assertThat(finalServerMessage.getHandshakeState())
- .isEqualTo(HandshakeMessage.HandshakeState.FINISHED);
- assertThat(finalServerMessage.getKey()).isNotNull();
- assertThat(finalServerMessage.getNextMessage()).isNull();
-
- HandshakeMessage finalClientMessage = clientRunner.verifyPin();
- assertThat(finalClientMessage.getHandshakeState())
- .isEqualTo(HandshakeMessage.HandshakeState.FINISHED);
- assertThat(finalClientMessage.getKey()).isNotNull();
- assertThat(finalClientMessage.getNextMessage()).isNull();
-
- assertThat(finalServerMessage.getKey()
- .decryptData(finalClientMessage.getKey().encryptData(sTestData)))
- .isEqualTo(sTestData);
- assertThat(finalClientMessage.getKey()
- .decryptData(finalServerMessage.getKey().encryptData(sTestData)))
- .isEqualTo(sTestData);
- }
-
- private void verifyHandshake(EncryptionRunner clientRunner, EncryptionRunner serverRunner)
- throws Exception {
- HandshakeMessage initialClientMessage = clientRunner.initHandshake();
-
- assertThat(initialClientMessage.getHandshakeState())
- .isEqualTo(HandshakeMessage.HandshakeState.IN_PROGRESS);
- assertThat(initialClientMessage.getKey()).isNull();
- assertThat(initialClientMessage.getNextMessage()).isNotNull();
-
- // This and the following similar log statements are useful when running this test to
- // find the payload sizes.
- Log.i(EncryptionRunner.TAG,
- "initial client size:" + initialClientMessage.getNextMessage().length);
-
- HandshakeMessage initialServerMessage =
- serverRunner.respondToInitRequest(initialClientMessage.getNextMessage());
-
- assertThat(initialServerMessage.getHandshakeState())
- .isEqualTo(HandshakeMessage.HandshakeState.IN_PROGRESS);
- assertThat(initialServerMessage.getKey()).isNull();
- assertThat(initialServerMessage.getNextMessage()).isNotNull();
-
- Log.i(EncryptionRunner.TAG,
- "initial server message size:" + initialServerMessage.getNextMessage().length);
-
- HandshakeMessage clientMessage =
- clientRunner.continueHandshake(initialServerMessage.getNextMessage());
-
- assertThat(clientMessage.getHandshakeState())
- .isEqualTo(HandshakeMessage.HandshakeState.VERIFICATION_NEEDED);
- assertThat(clientMessage.getKey()).isNull();
- assertThat(clientMessage.getVerificationCode()).isNotEmpty();
- assertThat(clientMessage.getNextMessage()).isNotNull();
-
- Log.i(EncryptionRunner.TAG,
- "second client message size:" + clientMessage.getNextMessage().length);
-
- HandshakeMessage serverMessage =
- serverRunner.continueHandshake(clientMessage.getNextMessage());
- assertThat(serverMessage.getHandshakeState())
- .isEqualTo(HandshakeMessage.HandshakeState.VERIFICATION_NEEDED);
- assertThat(serverMessage.getKey()).isNull();
- assertThat(serverMessage.getNextMessage()).isNull();
-
- Log.i(EncryptionRunner.TAG,
- "last server message size:" + clientMessage.getNextMessage().length);
- }
-
- @Test
- public void invalidPin_ukey2() throws Exception {
- invalidPinTest(EncryptionRunnerFactory::newRunner);
- }
-
- @Test
- public void invalidPin_dummy() throws Exception {
- invalidPinTest(EncryptionRunnerFactory::newDummyRunner);
- }
-
- private void invalidPinTest(RunnerFactory runnerFactory) throws Exception {
- EncryptionRunner clientRunner = runnerFactory.newRunner();
- EncryptionRunner serverRunner = runnerFactory.newRunner();
-
- verifyHandshake(clientRunner, serverRunner);
- clientRunner.invalidPin();
- serverRunner.invalidPin();
-
- try {
- clientRunner.verifyPin();
- Assert.fail();
- } catch (Exception ignored) {
- // pass
- }
-
- try {
- serverRunner.verifyPin();
- Assert.fail();
- } catch (Exception ignored) {
- // pass
- }
- }
-}
diff --git a/car-lib/src/android/car/Car.java b/car-lib/src/android/car/Car.java
index e6e0d35..668b78a 100644
--- a/car-lib/src/android/car/Car.java
+++ b/car-lib/src/android/car/Car.java
@@ -56,6 +56,7 @@
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -67,6 +68,13 @@
* Calling this API on a device with no such feature will lead to an exception.
*/
public final class Car {
+
+ /**
+ * Binder service name of car service registered to service manager.
+ *
+ * @hide
+ */
+ public static final String CAR_SERVICE_BINDER_SERVICE_NAME = "car_service";
/**
* Service name for {@link CarSensorManager}, to be used in {@link #getCarManager(String)}.
*
@@ -613,6 +621,9 @@
private static final long CAR_SERVICE_BIND_RETRY_INTERVAL_MS = 500;
private static final long CAR_SERVICE_BIND_MAX_RETRY = 20;
+ private static final long CAR_SERVICE_BINDER_POLLING_INTERVAL_MS = 50;
+ private static final long CAR_SERVICE_BINDER_POLLING_MAX_RETRY = 100;
+
private final Context mContext;
@GuardedBy("this")
private ICar mService;
@@ -647,7 +658,9 @@
mService = ICar.Stub.asInterface(service);
mConnectionState = STATE_CONNECTED;
}
- mServiceConnectionListenerClient.onServiceConnected(name, service);
+ if (mServiceConnectionListenerClient != null) {
+ mServiceConnectionListenerClient.onServiceConnected(name, service);
+ }
}
public void onServiceDisconnected(ComponentName name) {
@@ -658,7 +671,9 @@
}
// unbind explicitly and set connectionState to STATE_DISCONNECTED here.
disconnect();
- mServiceConnectionListenerClient.onServiceDisconnected(name);
+ if (mServiceConnectionListenerClient != null) {
+ mServiceConnectionListenerClient.onServiceDisconnected(name);
+ }
}
};
@@ -734,11 +749,54 @@
*/
@Nullable
public static Car createCar(Context context, @Nullable Handler handler) {
- IBinder service = ServiceManager.getService("car_service");
- if (service == null) {
- return null;
+ Car car = null;
+ IBinder service = null;
+ boolean started = false;
+ int retryCount = 0;
+ while (true) {
+ service = ServiceManager.getService(CAR_SERVICE_BINDER_SERVICE_NAME);
+ if (car == null) {
+ // service can be still null. The constructor is safe for null service.
+ car = new Car(context, ICar.Stub.asInterface(service), handler);
+ }
+ if (service != null) {
+ if (!started) { // specialization for most common case.
+ return car;
+ }
+ break;
+ }
+ if (!started) {
+ car.startCarService();
+ started = true;
+ }
+ retryCount++;
+ if (retryCount > CAR_SERVICE_BINDER_POLLING_MAX_RETRY) {
+ Log.e(CarLibLog.TAG_CAR, "cannot get car_service, waited for car service (ms):"
+ + CAR_SERVICE_BINDER_POLLING_INTERVAL_MS
+ * CAR_SERVICE_BINDER_POLLING_MAX_RETRY,
+ new RuntimeException());
+ return null;
+ }
+ try {
+ Thread.sleep(CAR_SERVICE_BINDER_POLLING_INTERVAL_MS);
+ } catch (InterruptedException e) {
+ Log.e(CarLibLog.TAG_CAR, "interrupted while waiting for car_service",
+ new RuntimeException());
+ return null;
+ }
}
- return new Car(context, ICar.Stub.asInterface(service), handler);
+ // Can be accessed from mServiceConnectionListener in main thread.
+ synchronized (car) {
+ if (car.mService == null) {
+ car.mService = ICar.Stub.asInterface(service);
+ Log.w(CarLibLog.TAG_CAR,
+ "waited for car_service (ms):"
+ + CAR_SERVICE_BINDER_POLLING_INTERVAL_MS * retryCount,
+ new RuntimeException());
+ }
+ car.mConnectionState = STATE_CONNECTED;
+ }
+ return car;
}
private Car(Context context, ServiceConnection serviceConnectionListener,
@@ -748,6 +806,7 @@
mMainThreadEventHandler = determineMainThreadEventHandler(mEventHandler);
mService = null;
+ mConnectionState = STATE_DISCONNECTED;
mOwnsService = true;
mServiceConnectionListenerClient = serviceConnectionListener;
}
@@ -757,14 +816,19 @@
* Car constructor when ICar binder is already available.
* @hide
*/
- public Car(Context context, ICar service, @Nullable Handler handler) {
+ public Car(Context context, @Nullable ICar service, @Nullable Handler handler) {
mContext = context;
mEventHandler = determineEventHandler(handler);
mMainThreadEventHandler = determineMainThreadEventHandler(mEventHandler);
mService = service;
- mOwnsService = false;
- mConnectionState = STATE_CONNECTED;
+ if (service != null) {
+ mConnectionState = STATE_CONNECTED;
+ mOwnsService = false;
+ } else {
+ mConnectionState = STATE_DISCONNECTED;
+ mOwnsService = true;
+ }
mServiceConnectionListenerClient = null;
}
@@ -844,6 +908,12 @@
}
}
+ /** @hide */
+ @VisibleForTesting
+ public ServiceConnection getServiceConnectionListener() {
+ return mServiceConnectionListener;
+ }
+
/**
* Get car specific service as in {@link Context#getSystemService(String)}. Returned
* {@link Object} should be type-casted to the desired service.
diff --git a/car-usb-handler/AndroidManifest.xml b/car-usb-handler/AndroidManifest.xml
index 848548f..caa93bd 100644
--- a/car-usb-handler/AndroidManifest.xml
+++ b/car-usb-handler/AndroidManifest.xml
@@ -26,7 +26,7 @@
android:directBootAware="true">
<activity android:name=".UsbHostManagementActivity"
android:theme="@android:style/Theme.DeviceDefault.Dialog"
- android:launchMode="singleTop">
+ android:launchMode="standard">
<meta-data
android:name="distractionOptimized"
android:value="true" />
diff --git a/car_product/sepolicy/test/kitchensink_app.te b/car_product/sepolicy/test/kitchensink_app.te
index 8093490..26b8255 100644
--- a/car_product/sepolicy/test/kitchensink_app.te
+++ b/car_product/sepolicy/test/kitchensink_app.te
@@ -13,6 +13,7 @@
audio_service
audioserver_service
autofill_service
+ bluetooth_manager_service
connectivity_service
content_service
deviceidle_service
@@ -27,6 +28,7 @@
sensorservice_service
surfaceflinger_service
uimode_service
+ wifi_service
}:service_manager find;
# Read and write /data/data subdirectory.
diff --git a/service/res/values-af/strings.xml b/service/res/values-af/strings.xml
index 8da32cf..3805c17 100644
--- a/service/res/values-af/strings.xml
+++ b/service/res/values-af/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Toegang tot motor se kamera(s)."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"toegang tot motor se dryfkraginligting"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Toegang tot jou motor se energie-inligting."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"verstel motor se oorblywende ritafstand"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Verstel waarde van motor se oorblywende ritafstand."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"toegang tot motor se HVAC- (verhitting, ventilasie, lugversorging) stelsel"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Toegang tot jou motor se HVAC (verhitting, venitalise en lugversorging)."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"toegang tot motor se ryafstandinligting"</string>
diff --git a/service/res/values-am/strings.xml b/service/res/values-am/strings.xml
index 41b7622..a987e68 100644
--- a/service/res/values-am/strings.xml
+++ b/service/res/values-am/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"የእርስዎን ካሜራ(ዎች) ይደርሱበት(ባቸው)።"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"የመኪናውን የኃይል መረጃ ድረስበት"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"የእርስዎን መኪና ኃይል መረጃ ይድረሱበት።"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"የመኪና ክልልን ቀሪ አስተካክል"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"የመኪና ክልልን ቀሪ ዋጋ አስተካክል።"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"የመኪናውን hvac ድረስበት"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"የእርስዎን መኪና hvac ይድረሱበት።"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"የመኪናውን የሄደበት ርቀት ብዛት መረጃ ድረስበት"</string>
diff --git a/service/res/values-ar/strings.xml b/service/res/values-ar/strings.xml
index d9b7040..19a0775 100644
--- a/service/res/values-ar/strings.xml
+++ b/service/res/values-ar/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"الوصول إلى الكاميرات في السيارة"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"الحصول على معلومات عن طاقة السيارة"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"الحصول على معلومات الطاقة في السيارة"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"ضبط القيمة المتبقية لنطاق السيارة"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"يمكنك ضبط القيمة المتبقية لنطاق السيارة."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"الحصول على معلومات التدفئة والتهوية وتكييف الهواء في السيارة"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"الحصول على معلومات التدفئة والتهوية وتكييف الهواء في السيارة"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"الحصول على معلومات المسافة المقطوعة بالأميال في سيارتك"</string>
diff --git a/service/res/values-as/strings.xml b/service/res/values-as/strings.xml
index 0cac303..cabe098 100644
--- a/service/res/values-as/strings.xml
+++ b/service/res/values-as/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"আপোনাৰ গাড়ীৰ কেমেৰা এক্সেছ কৰিব।"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"গাড়ীৰ শক্তিৰ তথ্য এক্সেছ কৰিব"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"আপোনাৰ গাড়ীৰ শক্তি সম্পৰ্কীয় তথ্য এক্সেছ কৰিব।"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"গাড়ীখন আৰু কিমান সময়লৈ চলিব সেয়া মিলাওক"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"গাড়ীখন আৰু কিমান সময়লৈ চলিব তাৰ মানটো মিলাওক।"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"গাড়ীৰ এইছভিএচি এক্সেছ কৰিব"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"আপোনাৰ গাড়ীৰ hvac এক্সেছ কৰিব।"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"গাড়ীৰ মাইলেজৰ তথ্য এক্সেছ কৰিব"</string>
diff --git a/service/res/values-az/strings.xml b/service/res/values-az/strings.xml
index 5cdfa3d..f34dfd2 100644
--- a/service/res/values-az/strings.xml
+++ b/service/res/values-az/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Avtomobilin kameralarına giriş."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"avtomobilin enerji məlumatlarına giriş"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Avtomobilin enerji məlumatlarına giriş."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"avtomobilin yürüş məsafəsi qalığını nizamlamaq"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Avtomobilin yürüş məsafəsi qalıq dəyərini nizamlamaq."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"avtomobilin HVAC məlumatlarına giriş"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Avtomobilin HVAC mexanizminə giriş."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"avtomobilin kilometraj məlumatlarına giriş"</string>
diff --git a/service/res/values-b+sr+Latn/strings.xml b/service/res/values-b+sr+Latn/strings.xml
index e0da81d..1f9d908 100644
--- a/service/res/values-b+sr+Latn/strings.xml
+++ b/service/res/values-b+sr+Latn/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Pristupi kamerama automobila."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"pristup podacima o energiji automobila"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Pristupi informacijama o energiji automobila."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"prilagođavanje preostalog dometa automobila"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Prilagođavanje vrednosti preostalog dometa automobila."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"pristup grejanju, ventilaciji i klimatizaciji automobila"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Pristupi grejanju, ventilaciji i klimatizaciji automobila"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"pristup podacima o kilometraži automobila"</string>
diff --git a/service/res/values-be/strings.xml b/service/res/values-be/strings.xml
index b5d46ae..56bd6d2 100644
--- a/service/res/values-be/strings.xml
+++ b/service/res/values-be/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Доступ да камер аўтамабіля."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"дазволіць доступ да інфармацыі пра энергарэсурсы аўтамабіля"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Доступ да інфармацыі пра энергарэсурсы аўтамабіля."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"карэктаваць аўтамабільны прабег без дазапраўкі, які застаўся"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Карэктаваць значэнне аўтамабільнага прабегу без дазапраўкі, які застаўся."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"дазволіць доступ да сістэмы АВіК аўтамабіля"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Доступ да сістэмы АВіК аўтамабіля."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"дазволіць доступ да інфармацыі пра прабег аўтамабіля"</string>
diff --git a/service/res/values-bg/strings.xml b/service/res/values-bg/strings.xml
index d5c1fa4..0144a9e 100644
--- a/service/res/values-bg/strings.xml
+++ b/service/res/values-bg/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Достъп до камерата или съответно камерите на автомобила ви."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"достъп до информацията за енергията на автомобила"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Достъп до информацията за енергията на автомобила."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"корекция на отсечката, която трябва да измине автомобилът"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Коригирайте стойността за отсечката, която трябва да измине автомобилът."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"достъп до ОВК системата на автомобила"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Достъп до ОВК системата на автомобила."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"достъп до информацията за километража на автомобила"</string>
diff --git a/service/res/values-bn/strings.xml b/service/res/values-bn/strings.xml
index 3b5957b..1663f7e 100644
--- a/service/res/values-bn/strings.xml
+++ b/service/res/values-bn/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"আপনার গাড়ির ক্যামেরা(গুলি) অ্যাক্সেস করা।"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"আপনার গাড়ির এনার্জির তথ্য অ্যাক্সেস করা"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"আপনার গাড়ির এনার্জি তথ্য অ্যাক্সেস করা।"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"গাড়ি আর কত সময় চলবে তা অ্যাডজাস্ট করতে পারবে"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"গাড়ি আর কত সময় চলবে তার মান অ্যাডজাস্ট করতে পারবে।"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"গাড়ির HVAC অ্যাক্সেস করা"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"আপনার গাড়ির HVAC অ্যাক্সেস করা।"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"গাড়ির মাইলেজ সংক্রান্ত তথ্য অ্যাক্সেস করা"</string>
diff --git a/service/res/values-bs/strings.xml b/service/res/values-bs/strings.xml
index 5770adf..ea31b1b 100644
--- a/service/res/values-bs/strings.xml
+++ b/service/res/values-bs/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Pristupiti kameri(ama) automobila."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"pristupiti informacijama o energiji automobila"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Pristupiti informacijama o energiji automobila."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"podesi preostali domet automobila"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Podesi vrijednost preostalog dometa automobila."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"pristupiti grijanju, ventilaciji i klimatizaciji automobila"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Pristupiti grijanju, ventilaciji i klimatizaciji automobila."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"pristupiti informacijama o pređenim kilometrima automobila"</string>
diff --git a/service/res/values-ca/strings.xml b/service/res/values-ca/strings.xml
index 535b403..eefd5ef 100644
--- a/service/res/values-ca/strings.xml
+++ b/service/res/values-ca/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Accedir a la càmera del cotxe"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"accedeix a la informació sobre l\'energia del cotxe"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Accedir a la informació sobre l\'energia del cotxe"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"ajustar l\'autonomia restant del cotxe"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Ajustar el valor de l\'autonomia restant del cotxe."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"accedeix al sistema HVAC del cotxe"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Accedir al sistema HVAC del cotxe"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"accedeix a la informació sobre el quilometratge del cotxe"</string>
diff --git a/service/res/values-cs/strings.xml b/service/res/values-cs/strings.xml
index 369cdbc..c4ffdd8 100644
--- a/service/res/values-cs/strings.xml
+++ b/service/res/values-cs/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Přístup ke kamerám auta."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"přístup k údajům o energii auta"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Přístup k údajům o energii auta."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"úprava dojezdu auta – zbytek"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Úprava zbývající hodnoty dojezdu auta."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"přístup k topení, větrání a klimatizaci auta"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Přístup k systému HVAC auta."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"přístup k ujetým kilometrům auta"</string>
diff --git a/service/res/values-da/strings.xml b/service/res/values-da/strings.xml
index 5513137..9f80191 100644
--- a/service/res/values-da/strings.xml
+++ b/service/res/values-da/strings.xml
@@ -22,8 +22,10 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Få adgang til bilens kameraer."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"få adgang til oplysninger om bilens energiforbrug"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Få adgang til oplysninger om bilens energiforbrug"</string>
- <string name="car_permission_label_hvac" msgid="1499454192558727843">"få adgang til bilens vvac"</string>
- <string name="car_permission_desc_hvac" msgid="3754229695589774195">"Få adgang til bilens VVAC-system."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"juster bilens resterende afstand."</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Juster værdien for bilens resterende afstand."</string>
+ <string name="car_permission_label_hvac" msgid="1499454192558727843">"få adgang til bilens ventilation"</string>
+ <string name="car_permission_desc_hvac" msgid="3754229695589774195">"Få adgang til bilens ventilationssystem."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"få adgang til oplysninger om bilens kilometertal"</string>
<string name="car_permission_desc_mileage" msgid="7179735693278681090">"Få adgang til oplysninger om bilens kilometertal."</string>
<string name="car_permission_label_speed" msgid="1149027717860529745">"tjekke bilens hastighed"</string>
diff --git a/service/res/values-de/strings.xml b/service/res/values-de/strings.xml
index ff4c461..c7e1590 100644
--- a/service/res/values-de/strings.xml
+++ b/service/res/values-de/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Auf Autokamera(s) zugreifen."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"auf Energieinformationen des Autos zuzugreifen"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Auf Energieinformationen des Autos zugreifen."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"Strecke anpassen, die das Auto noch fahren kann"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Wert für die Strecke anpassen, die das Auto noch fahren kann."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"auf die Klimaanlage zuzugreifen"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Auf Klimaanlage des Autos zugreifen."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"auf den Kilometerstand zuzugreifen"</string>
diff --git a/service/res/values-el/strings.xml b/service/res/values-el/strings.xml
index 8935d6d..583e938 100644
--- a/service/res/values-el/strings.xml
+++ b/service/res/values-el/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Πρόσβαση στις κάμερες του αυτοκινήτου σας."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"πρόσβαση στις πληροφορίες ενέργειας του αυτοκινήτου"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Πρόσβαση σε πληροφορίες ενέργειας του αυτοκινήτου σας."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"προσαρμόστε το εύρος αυτοκινήτου που απομένει"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Προσαρμόστε την τιμή του εύρους αυτοκινήτου που απομένει."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"πρόσβαση στο σύστημα θέρμανσης-αερισμού-κλιματισμού του αυτοκινήτου"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Πρόσβαση στο σύστημα θέρμανσης, αερισμού, και κλιματισμού του αυτοκινήτου σας."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"πρόσβαση στις πληροφορίες διανυθείσας απόστασης του αυτοκινήτου"</string>
diff --git a/service/res/values-en-rAU/strings.xml b/service/res/values-en-rAU/strings.xml
index 49741f1..f89611f 100644
--- a/service/res/values-en-rAU/strings.xml
+++ b/service/res/values-en-rAU/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Access your car’s camera(s)."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"access car’s energy information"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Access your car’s energy information."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"adjust car’s range remaining"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Adjust car’s range remaining value."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"access car’s hvac"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Access your car’s HVAC."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"access car’s mileage information"</string>
diff --git a/service/res/values-en-rCA/strings.xml b/service/res/values-en-rCA/strings.xml
index 49741f1..f89611f 100644
--- a/service/res/values-en-rCA/strings.xml
+++ b/service/res/values-en-rCA/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Access your car’s camera(s)."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"access car’s energy information"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Access your car’s energy information."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"adjust car’s range remaining"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Adjust car’s range remaining value."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"access car’s hvac"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Access your car’s HVAC."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"access car’s mileage information"</string>
diff --git a/service/res/values-en-rGB/strings.xml b/service/res/values-en-rGB/strings.xml
index 49741f1..f89611f 100644
--- a/service/res/values-en-rGB/strings.xml
+++ b/service/res/values-en-rGB/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Access your car’s camera(s)."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"access car’s energy information"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Access your car’s energy information."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"adjust car’s range remaining"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Adjust car’s range remaining value."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"access car’s hvac"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Access your car’s HVAC."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"access car’s mileage information"</string>
diff --git a/service/res/values-en-rIN/strings.xml b/service/res/values-en-rIN/strings.xml
index 49741f1..f89611f 100644
--- a/service/res/values-en-rIN/strings.xml
+++ b/service/res/values-en-rIN/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Access your car’s camera(s)."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"access car’s energy information"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Access your car’s energy information."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"adjust car’s range remaining"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Adjust car’s range remaining value."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"access car’s hvac"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Access your car’s HVAC."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"access car’s mileage information"</string>
diff --git a/service/res/values-en-rXC/strings.xml b/service/res/values-en-rXC/strings.xml
index 5bbe05b..785d012 100644
--- a/service/res/values-en-rXC/strings.xml
+++ b/service/res/values-en-rXC/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Access your car’s camera(s)."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"access car’s energy information"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Access your car’s energy information."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"adjust car’s range remaining"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Adjust car’s range remaining value."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"access car’s hvac"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Access your car’s hvac."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"access car’s mileage information"</string>
diff --git a/service/res/values-es-rUS/strings.xml b/service/res/values-es-rUS/strings.xml
index ebcc08c..d18ffbb 100644
--- a/service/res/values-es-rUS/strings.xml
+++ b/service/res/values-es-rUS/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Acceder a las cámaras del auto"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"acceder a información de la potencia del vehículo"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Acceder a la información de energía del auto"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"ajustar el valor restante de alcance del vehículo"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Ajustar el valor restante de alcance del vehículo"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"acceder al sistema HVAC del vehículo"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Acceder al sistema HVAC del auto."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"acceder a información sobre el kilometraje del vehículo"</string>
diff --git a/service/res/values-es/strings.xml b/service/res/values-es/strings.xml
index e2a9e88..6b1c9b1 100644
--- a/service/res/values-es/strings.xml
+++ b/service/res/values-es/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Acceder a las cámaras del coche."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"acceder a la información sobre el nivel de energía del coche"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Acceder a la información sobre el nivel de energía del coche."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"Ajuste de la distancia que se puede recorrer con el combustible actual"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Valor del ajuste de la distancia que se puede recorrer con el combustible actual."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"acceder al sistema de CVAA del coche"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Acceder al sistema de CVAA del coche."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"acceder a la información del kilometraje del coche"</string>
diff --git a/service/res/values-et/strings.xml b/service/res/values-et/strings.xml
index cfaf748..0162b2e 100644
--- a/service/res/values-et/strings.xml
+++ b/service/res/values-et/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Juurdepääs auto kaameratele."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"juurdepääs auto energiateabele"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Juurdepääs auto energiateabele."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"kohandage auto järelejäänud kütusega kaetavat vahemaad"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Kohandage auto järelejäänud kütusega kaetava vahemaa väärtust."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"juurdepääs auto kliimaseadmele"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Juurdepääs auto kliimatehnikale."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"juurdepääs auto läbisõiduteabele"</string>
diff --git a/service/res/values-eu/strings.xml b/service/res/values-eu/strings.xml
index eed4c05..66faacd 100644
--- a/service/res/values-eu/strings.xml
+++ b/service/res/values-eu/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Atzitu autoaren kamerak."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"atzitu autoaren energiari buruzko informazioa"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Atzitu autoaren energiari buruzko informazioa"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"doitu autoari gelditzen zaion gaitasuna"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Doitu autoari gelditzen zaion gaitasunaren balioa."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"atzitu autoaren berogailua, haizagailua eta aire-girogailua"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Atzitu autoaren berogailua, haizagailua eta aire-girogailua."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"atzitu autoaren kilometro kopuruari buruzko informazioa"</string>
diff --git a/service/res/values-fa/strings.xml b/service/res/values-fa/strings.xml
index 2e29029..d95a3b1 100644
--- a/service/res/values-fa/strings.xml
+++ b/service/res/values-fa/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"دسترسی به دوربین(های) خودرو."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"دسترسی به اطلاعات انرژی خودرو"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"دسترسی اطلاعات انرژی خودرو."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"تنظیم مقدار مسافت باقیمانده که میتوان با خودرو سفر کرد"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"تنظیم مقدار مسافت باقیمانده که میتوان با خودرو سفر کرد."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"دسترسی به اچویایسی خودرو"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"دسترسی به اچویایسی خودرو."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"دسترسی به اطلاعات مسافت طیشده خودرو"</string>
diff --git a/service/res/values-fi/strings.xml b/service/res/values-fi/strings.xml
index 256cdfa..0b23324 100644
--- a/service/res/values-fi/strings.xml
+++ b/service/res/values-fi/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"käyttää auton kameroita"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"käyttää auton energiatietoja"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"nähdä auton energiatiedot"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"säädä auton jäljellä olevaa toimintamatkaa"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Säädä auton jäljellä olevan toimintamatkan arvoa."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"käyttää auton ilmastointia ja lämmitystä"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"käyttää auton lämmitys-,ilmanvaihto- ja ilmastointijärjestelmää"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"käyttää tietoja ajetuista kilometreistä"</string>
diff --git a/service/res/values-fr-rCA/strings.xml b/service/res/values-fr-rCA/strings.xml
index 470879d..c18eaee 100644
--- a/service/res/values-fr-rCA/strings.xml
+++ b/service/res/values-fr-rCA/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Accéder aux caméras de la voiture."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"accéder aux renseignements énergétiques de la voiture"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Accéder aux renseignements énergétiques de la voiture."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"réglez l\'autonomie restante du véhicule"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Réglez la valeur de l\'autonomie restante du véhicule."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"accéder à l\'élément CVC de la voiture"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Accéder à l\'élément CVC de la voiture."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"accéder au kilométrage de la voiture"</string>
diff --git a/service/res/values-fr/strings.xml b/service/res/values-fr/strings.xml
index 6d562be..5eb7007 100644
--- a/service/res/values-fr/strings.xml
+++ b/service/res/values-fr/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Accéder aux caméras de la voiture."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"Accéder aux informations relatives à l\'énergie de la voiture"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Accéder aux informations énergétiques de la voiture."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"ajuster l\'autonomie restante de la voiture"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Ajustez la valeur de l\'autonomie restante de la voiture."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"Accéder aux éléments CVC de la voiture"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Accéder aux éléments CVC de la voiture"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"Accéder aux informations sur le kilométrage de la voiture"</string>
diff --git a/service/res/values-gl/strings.xml b/service/res/values-gl/strings.xml
index efcf7b2..b141dd7 100644
--- a/service/res/values-gl/strings.xml
+++ b/service/res/values-gl/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Acceder ás cámaras do coche."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"acceder a información sobre o nivel de enerxía do coche"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Acceder a información de enerxía do coche."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"axustar alcance restante do coche"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Axusta o valor de alcance restante do coche."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"acceder ao sistema de climatización do coche"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Acceder ao sistema de HVAC coche."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"acceder a información da quilometraxe do coche"</string>
diff --git a/service/res/values-gu/strings.xml b/service/res/values-gu/strings.xml
index 7c00a7d..f5aff77 100644
--- a/service/res/values-gu/strings.xml
+++ b/service/res/values-gu/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"તમારી કારના કૅમેરાને ઍક્સેસ કરવાની મંજૂરી આપો."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"કારની ઊર્જાની માહિતીને ઍક્સેસ કરો"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"તમારી કારની ઊર્જાની માહિતી ઍક્સેસ કરવાની મંજૂરી આપો."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"કારની રેંજનું બાકીનું મૂલ્ય ગોઠવો"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"કારની રેંજનું બાકીનું મૂલ્ય ગોઠવો."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"કારના HVACને ઍક્સેસ કરો"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"તમારી કારની hvac ઍક્સેસ કરો."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"કારના માઇલેજની માહિતીને ઍક્સેસ કરો"</string>
diff --git a/service/res/values-hi/strings.xml b/service/res/values-hi/strings.xml
index ff8429a..799c001 100644
--- a/service/res/values-hi/strings.xml
+++ b/service/res/values-hi/strings.xml
@@ -16,27 +16,29 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="car_permission_label" msgid="741004755205554376">"कार की जानकारी एक्सेस कर सकता है"</string>
- <string name="car_permission_desc" msgid="162499818870052725">"आपकी कार की जानकारी एक्सेस कर सकता है"</string>
- <string name="car_permission_label_camera" msgid="3725702064841827180">"कार का कैमरा एक्सेस कर सकता है"</string>
- <string name="car_permission_desc_camera" msgid="917024932164501426">"आपकी कार के कैमरे एक्सेस कर सकता है."</string>
- <string name="car_permission_label_energy" msgid="7409144323527821558">"कार की ऊर्जा की जानकारी एक्सेस कर सकता है"</string>
- <string name="car_permission_desc_energy" msgid="3392963810053235407">"आपकी कार की ऊर्जा से जुड़ी जानकारी एक्सेस कर सकता है."</string>
- <string name="car_permission_label_hvac" msgid="1499454192558727843">"कार का एचवीएसी एक्सेस कर सकता है"</string>
- <string name="car_permission_desc_hvac" msgid="3754229695589774195">"आपकी कार का एचवीएसी एक्सेस कर सकता है."</string>
- <string name="car_permission_label_mileage" msgid="4661317074631150551">"कार के माइलेज की जानकारी एक्सेस कर सकता है"</string>
- <string name="car_permission_desc_mileage" msgid="7179735693278681090">"आपकी कार की माइलेज से जुड़ी जानकारी एक्सेस कर सकता है."</string>
+ <string name="car_permission_label" msgid="741004755205554376">"कार की जानकारी ऐक्सेस कर सकता है"</string>
+ <string name="car_permission_desc" msgid="162499818870052725">"आपकी कार की जानकारी ऐक्सेस कर सकता है"</string>
+ <string name="car_permission_label_camera" msgid="3725702064841827180">"कार का कैमरा ऐक्सेस कर सकता है"</string>
+ <string name="car_permission_desc_camera" msgid="917024932164501426">"आपकी कार के कैमरे ऐक्सेस कर सकता है."</string>
+ <string name="car_permission_label_energy" msgid="7409144323527821558">"कार की ऊर्जा की जानकारी ऐक्सेस कर सकता है"</string>
+ <string name="car_permission_desc_energy" msgid="3392963810053235407">"आपकी कार की ऊर्जा से जुड़ी जानकारी ऐक्सेस कर सकता है."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"मौजूदा बैटरी या फ़्यूल में कार कितनी दूरी तय कर सकती है, इस मान में बदलाव करें."</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"मौजूदा बैटरी या फ़्यूल में कार कितनी दूरी तय कर सकती है, इस मान में बदलाव करें."</string>
+ <string name="car_permission_label_hvac" msgid="1499454192558727843">"कार का एचवीएसी ऐक्सेस कर सकता है"</string>
+ <string name="car_permission_desc_hvac" msgid="3754229695589774195">"आपकी कार का एचवीएसी ऐक्सेस कर सकता है."</string>
+ <string name="car_permission_label_mileage" msgid="4661317074631150551">"कार के माइलेज की जानकारी ऐक्सेस कर सकता है"</string>
+ <string name="car_permission_desc_mileage" msgid="7179735693278681090">"आपकी कार की माइलेज से जुड़ी जानकारी ऐक्सेस कर सकता है."</string>
<string name="car_permission_label_speed" msgid="1149027717860529745">"कार की रफ़्तार की जानकारी देख सकता है"</string>
- <string name="car_permission_desc_speed" msgid="2047965198165448241">"आपकी कार की रफ़्तार की जानकारी एक्सेस कर सकता है."</string>
- <string name="car_permission_label_vehicle_dynamics_state" msgid="313779267420048367">"कार के चलने की स्थिति एक्सेस कर सकता है"</string>
- <string name="car_permission_desc_vehicle_dynamics_state" msgid="8891506193446375660">"आपकी कार के चलने से जुड़ी जानकारी एक्सेस कर सकता है."</string>
- <string name="car_permission_label_vendor_extension" msgid="7141601811734127361">"कार बनाने वाली कंपनी से जुड़ी जानकारी एक्सेस कर सकता है"</string>
- <string name="car_permission_desc_vendor_extension" msgid="2970718502334714035">"कार की खास जानकारी लेने-देने के लिए आपकी कार का विक्रेता, चैनल एक्सेस कर सकता है."</string>
+ <string name="car_permission_desc_speed" msgid="2047965198165448241">"आपकी कार की रफ़्तार की जानकारी ऐक्सेस कर सकता है."</string>
+ <string name="car_permission_label_vehicle_dynamics_state" msgid="313779267420048367">"कार के चलने की स्थिति ऐक्सेस कर सकता है"</string>
+ <string name="car_permission_desc_vehicle_dynamics_state" msgid="8891506193446375660">"आपकी कार के चलने से जुड़ी जानकारी ऐक्सेस कर सकता है."</string>
+ <string name="car_permission_label_vendor_extension" msgid="7141601811734127361">"कार बनाने वाली कंपनी से जुड़ी जानकारी ऐक्सेस कर सकता है"</string>
+ <string name="car_permission_desc_vendor_extension" msgid="2970718502334714035">"कार की खास जानकारी लेने-देने के लिए आपकी कार का विक्रेता, चैनल ऐक्सेस कर सकता है."</string>
<string name="car_permission_label_radio" msgid="6009465291685935112">"कार का रेडियो मैनेज कर सकता है"</string>
- <string name="car_permission_desc_radio" msgid="3385999027478186964">"आपकी कार का रेडियो एक्सेस कर सकता है."</string>
+ <string name="car_permission_desc_radio" msgid="3385999027478186964">"आपकी कार का रेडियो ऐक्सेस कर सकता है."</string>
<string name="car_permission_label_projection" msgid="9107156380287576787">"फ़ोन से कार की डिसप्ले पर किसी इंटरफ़ेस को प्रोजेक्ट कर सकता है"</string>
<string name="car_permission_desc_projection" msgid="2352178999656292944">"ऐप्लिकेशन कार की डिसप्ले पर, फ़ोन से किसी इंटरफ़ेस को प्रोजेक्ट कर सकता है."</string>
- <string name="car_permission_label_access_projection_status" msgid="4231618890836627402">"प्रोजेक्ट करने की स्थिति को एक्सेस कर सकता है"</string>
+ <string name="car_permission_label_access_projection_status" msgid="4231618890836627402">"प्रोजेक्ट करने की स्थिति को ऐक्सेस कर सकता है"</string>
<string name="car_permission_desc_access_projection_status" msgid="8497351979100616278">"ऐप्लिकेशन, कार की डिसप्ले पर प्रोजेक्ट किए जा रहे दूसरे ऐप्लिकेशन की स्थिति देख सकता है."</string>
<string name="car_permission_label_bind_projection_service" msgid="5362076216606651526">"प्रोजेक्ट करने की सुविधा इस्तेमाल कर सकता है"</string>
<string name="car_permission_desc_bind_projection_service" msgid="2282657787853408639">"उपोयगकर्ता को किसी प्रोजेक्ट करने की सुविधा के टॉप-लेवल इंटरफ़ेस से जोड़ता है. सामान्य ऐप्लिकेशन के लिए इसकी कभी ज़रूरत नहीं होती."</string>
@@ -83,12 +85,12 @@
<string name="car_permission_desc_storage_monitoring" msgid="2075712271139671318">"फ़्लैश डिवाइस की मेमोरी के इस्तेमाल की निगरानी कर सकता है"</string>
<string name="car_permission_label_driving_state" msgid="7754624599537393650">"गाड़ी चलाते समय होने वाले बदलावों की स्थिति को सुन सकता है"</string>
<string name="car_permission_desc_driving_state" msgid="2684025262811635737">"गाड़ी चलाते समय होने वाले बदलावों को सुन सकता है."</string>
- <string name="car_permission_label_car_engine_detailed" msgid="8911992719173587337">"कार के इंजन की जानकारी एक्सेस कर सकता है"</string>
- <string name="car_permission_desc_car_engine_detailed" msgid="1746863362811347700">"आपकी कार के इंजन की पूरी जानकारी एक्सेस कर सकता है."</string>
- <string name="car_permission_label_car_energy_ports" msgid="8548990315169219454">"कार की ईंधन टंकी का ढक्कन और चार्जिंग पोर्ट एक्सेस कर सकता है"</string>
- <string name="car_permission_desc_car_energy_ports" msgid="7771185999828794949">"कार की ईंधन टंकी का ढक्कन और चार्जिंग पोर्ट एक्सेस कर सकता है."</string>
+ <string name="car_permission_label_car_engine_detailed" msgid="8911992719173587337">"कार के इंजन की जानकारी ऐक्सेस कर सकता है"</string>
+ <string name="car_permission_desc_car_engine_detailed" msgid="1746863362811347700">"आपकी कार के इंजन की पूरी जानकारी ऐक्सेस कर सकता है."</string>
+ <string name="car_permission_label_car_energy_ports" msgid="8548990315169219454">"कार की ईंधन टंकी का ढक्कन और चार्जिंग पोर्ट ऐक्सेस कर सकता है"</string>
+ <string name="car_permission_desc_car_energy_ports" msgid="7771185999828794949">"कार की ईंधन टंकी का ढक्कन और चार्जिंग पोर्ट ऐक्सेस कर सकता है."</string>
<string name="car_permission_label_car_identification" msgid="5896712510164020478">"कार की पहचान देख सकता है"</string>
- <string name="car_permission_desc_car_identification" msgid="4132040867171275059">"कार की पहचान एक्सेस कर सकता है."</string>
+ <string name="car_permission_desc_car_identification" msgid="4132040867171275059">"कार की पहचान ऐक्सेस कर सकता है."</string>
<string name="car_permission_label_control_car_doors" msgid="3032058819250195700">"कार के दरवाज़े नियंत्रित कर सकता है"</string>
<string name="car_permission_desc_control_car_doors" msgid="6287353311980590092">"कार के दरवाज़े नियंत्रित कर सकता है."</string>
<string name="car_permission_label_control_car_windows" msgid="2452854429996653029">"कार की खिड़कियां नियंत्रित कर सकता है"</string>
@@ -97,30 +99,30 @@
<string name="car_permission_desc_control_car_mirrors" msgid="1224135684068855032">"कार के शीशे नियंत्रित कर सकता है."</string>
<string name="car_permission_label_control_car_seats" msgid="1826934820585497135">"कार की सीटें नियंत्रित कर सकता है"</string>
<string name="car_permission_desc_control_car_seats" msgid="2407536601226470563">"कार की सीटें नियंत्रित कर सकता है."</string>
- <string name="car_permission_label_car_info" msgid="4707513570676492315">"कार की बुनियादी जानकारी एक्सेस कर सकता है"</string>
- <string name="car_permission_desc_car_info" msgid="2118081474543537653">"कार की बुनियादी जानकारी एक्सेस कर सकता है."</string>
+ <string name="car_permission_label_car_info" msgid="4707513570676492315">"कार की बुनियादी जानकारी ऐक्सेस कर सकता है"</string>
+ <string name="car_permission_desc_car_info" msgid="2118081474543537653">"कार की बुनियादी जानकारी ऐक्सेस कर सकता है."</string>
<string name="car_permission_label_car_exterior_lights" msgid="541304469604902110">"कार के बाहरी हिस्से में लगी लाइटों की स्थिति देख सकता है"</string>
- <string name="car_permission_desc_car_exterior_lights" msgid="4038037584100849318">"कार के बाहरी हिस्से में लगी लाइटों की स्थिति एक्सेस कर सकता है."</string>
+ <string name="car_permission_desc_car_exterior_lights" msgid="4038037584100849318">"कार के बाहरी हिस्से में लगी लाइटों की स्थिति ऐक्सेस कर सकता है."</string>
<string name="car_permission_label_control_car_exterior_lights" msgid="101357531386232141">"कार के बाहरी हिस्से में लगी लाइटें नियंत्रित कर सकता है"</string>
<string name="car_permission_desc_control_car_exterior_lights" msgid="6332252612685264180">"कार के बाहरी हिस्से में लगी लाइटें नियंत्रित कर सकता है."</string>
<string name="car_permission_label_car_interior_lights" msgid="8506302199784427680">"कार के अंदर लगी लाइटों की स्थिति देख सकता है"</string>
- <string name="car_permission_desc_car_interior_lights" msgid="6204775354692372506">"कार के अंदर लगी लाइटों की स्थिति एक्सेस कर सकता है."</string>
+ <string name="car_permission_desc_car_interior_lights" msgid="6204775354692372506">"कार के अंदर लगी लाइटों की स्थिति ऐक्सेस कर सकता है."</string>
<string name="car_permission_label_control_car_interior_lights" msgid="6685386372012664281">"कार के अंदर लगी लाइटें नियंत्रित कर सकता है"</string>
<string name="car_permission_desc_control_car_interior_lights" msgid="797201814109701538">"कार के अंदर लगी लाइटें नियंत्रित कर सकता है."</string>
<string name="car_permission_label_car_exterior_environment" msgid="3385924985991299436">"कार के बाहर के तापमान की जानकारी देख सकता है"</string>
- <string name="car_permission_desc_car_exterior_environment" msgid="1716656004731603379">"कार के बाहर के तापमान की जानकारी एक्सेस कर सकता है."</string>
- <string name="car_permission_label_car_tires" msgid="4379255261197836840">"कार के टायरों की जानकारी एक्सेस कर सकता है"</string>
- <string name="car_permission_desc_car_tires" msgid="8134496466769810134">"कार के टायर की जानकारी एक्सेस कर सकता है."</string>
+ <string name="car_permission_desc_car_exterior_environment" msgid="1716656004731603379">"कार के बाहर के तापमान की जानकारी ऐक्सेस कर सकता है."</string>
+ <string name="car_permission_label_car_tires" msgid="4379255261197836840">"कार के टायरों की जानकारी ऐक्सेस कर सकता है"</string>
+ <string name="car_permission_desc_car_tires" msgid="8134496466769810134">"कार के टायर की जानकारी ऐक्सेस कर सकता है."</string>
<string name="car_permission_label_car_steering" msgid="7779530447441232479">"कार के स्टीयरिंग एंगल की जानकारी देख सकता है"</string>
- <string name="car_permission_desc_car_steering" msgid="1357331844530708138">"कार के स्टीयरिंग एंगल की जानकारी एक्सेस कर सकता है."</string>
+ <string name="car_permission_desc_car_steering" msgid="1357331844530708138">"कार के स्टीयरिंग एंगल की जानकारी ऐक्सेस कर सकता है."</string>
<string name="car_permission_label_read_car_display_units" msgid="7617008314862097183">"कार के डिसप्ले यूनिट की जानकारी देख सकता है"</string>
<string name="car_permission_desc_read_car_display_units" msgid="6891898275208542385">"डिसप्ले यूनिट देख सकता है."</string>
<string name="car_permission_label_control_car_display_units" msgid="4975303668183173076">"कार के डिसप्ले यूनिट नियंत्रित कर सकता है"</string>
<string name="car_permission_desc_control_car_display_units" msgid="8744397195158556945">"डिसप्ले यूनिट नियंत्रित कर सकता है."</string>
<string name="car_permission_label_car_powertrain" msgid="4586122326622134886">"कार के पावरट्रेन की जानकारी देख सकता है"</string>
- <string name="car_permission_desc_car_powertrain" msgid="1116007372551797796">"कार के पावरट्रेन की जानकारी एक्सेस कर सकता है."</string>
+ <string name="car_permission_desc_car_powertrain" msgid="1116007372551797796">"कार के पावरट्रेन की जानकारी ऐक्सेस कर सकता है."</string>
<string name="car_permission_label_car_power" msgid="8111448088314368268">"कार के पावर की स्थिति देख सकता है"</string>
- <string name="car_permission_desc_car_power" msgid="9202079903668652864">"कार के पावर की स्थिति एक्सेस कर सकता है."</string>
+ <string name="car_permission_desc_car_power" msgid="9202079903668652864">"कार के पावर की स्थिति ऐक्सेस कर सकता है."</string>
<string name="car_permission_label_enroll_trust" msgid="3512907900486690218">"भरोसेमंद डिवाइस का नाम दर्ज करें"</string>
<string name="car_permission_desc_enroll_trust" msgid="4148649994602185130">"भरोसेमंद डिवाइस का नाम दर्ज करने की अनुमति दें"</string>
<string name="trust_device_default_name" msgid="4213625926070261253">"मेरा डिवाइस"</string>
diff --git a/service/res/values-hr/strings.xml b/service/res/values-hr/strings.xml
index 2d2060b..9de3a7d 100644
--- a/service/res/values-hr/strings.xml
+++ b/service/res/values-hr/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"pristupiti kamerama automobila"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"pristupiti podacima o energiji automobila"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"pristupiti informacijama o energiji automobila"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"korekcija preostalog dometa automobila"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Korekcija vrijednosti preostalog dometa automobila."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"pristupiti grijanju, ventilaciji i klimatizaciji automobila"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"pristupiti grijanju, ventilaciji i klimatizaciji vašeg automobila"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"pristupiti podacima o kilometraži automobila"</string>
diff --git a/service/res/values-hu/strings.xml b/service/res/values-hu/strings.xml
index f427b07..b969a17 100644
--- a/service/res/values-hu/strings.xml
+++ b/service/res/values-hu/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Hozzáférhet az autó kameráihoz."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"hozzáférhet az autó energiafelhasználására vonatkozó adatokhoz"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Hozzáférhet az autó energiafelhasználására vonatkozó adatokhoz."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"az autó fennmaradó hatótávolságának módosítása"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Az autó fennmaradó hatótávolságának módosítása."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"hozzáférhet az autó HVAC-adataihoz"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Hozzáférhet az autó HVAC-adataihoz."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"hozzáférhet az autó kilométeradataihoz"</string>
diff --git a/service/res/values-hy/strings.xml b/service/res/values-hy/strings.xml
index a706dc4..0dc84da 100644
--- a/service/res/values-hy/strings.xml
+++ b/service/res/values-hy/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Կառավարել մեքենայի տեսախցիկ(ներ)ը"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"օգտագործել մեքենայի լիցքի մասին տվյալները"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Ընթերցել մեքենայի էներգառեսուրսների մասին տվյալները"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"փոխել տարածությունը, որը մեքենան կանցնի մինչև հաջորդ լցակայանը"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Փոխել տարածությունը, որը մեքենան կանցնի մինչև հաջորդ լցակայանը"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"օգտագործել մեքենայի HVAC համակարգի տվյալները"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Կառավարել HVAC համակարգը"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"օգտագործել մեքենայի վազքի տվյալները"</string>
diff --git a/service/res/values-in/strings.xml b/service/res/values-in/strings.xml
index 3651eaa..e6040eb 100644
--- a/service/res/values-in/strings.xml
+++ b/service/res/values-in/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Mengakses kamera mobil Anda."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"mengakses informasi energi mobil"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Mengakses informasi energi mobil Anda."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"sesuaikan jangkauan mobil yang tersisa"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Sesuaikan nilai jangkauan mobil yang tersisa."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"mengakses hvac mobil"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Mengakses hvac mobil Anda."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"mengakses informasi jarak tempuh mobil"</string>
diff --git a/service/res/values-is/strings.xml b/service/res/values-is/strings.xml
index 64f68f5..0beda8e 100644
--- a/service/res/values-is/strings.xml
+++ b/service/res/values-is/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Fá aðgang að myndavél(um) bílsins."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"fá aðgang að upplýsingum um orkunotkun bílsins"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Aðgangur að upplýsingum um orkunotkun bílsins."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"stilla gildi fyrir eftirstandandi drægi bílsins"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Stilla gildi fyrir eftirstandandi drægi bílsins."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"fá aðgang að hitun og loftræstingu bílsins"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Fá aðgang að hitun og loftræstingu bílsins."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"fá aðgang að upplýsingum um ekna vegalengd bílsins"</string>
diff --git a/service/res/values-it/strings.xml b/service/res/values-it/strings.xml
index 07aad4e..6b70707 100644
--- a/service/res/values-it/strings.xml
+++ b/service/res/values-it/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Consente di accedere alle videocamere dell\'automobile."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"Accesso alle informazioni sulla carica dell\'automobile"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Consente di accedere alle informazioni sulla carica dell\'automobile."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"regolazione dell\'autonomia rimanente dell\'auto"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Consente di regolare il valore dell\'autonomia rimanente dell\'auto."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"Accesso al sistema HVAC dell\'automobile"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Consente di accedere al sistema HVAC dell\'automobile."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"Accesso alle informazioni sul consumo di carburante dell\'automobile"</string>
diff --git a/service/res/values-iw/strings.xml b/service/res/values-iw/strings.xml
index 1770cf9..0c64299 100644
--- a/service/res/values-iw/strings.xml
+++ b/service/res/values-iw/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"גישה למצלמות הרכב."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"גישה למידע על נתוני צריכת האנרגיה של הרכב"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"גישה למידע על אנרגיית הרכב"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"התאמה של הטווח הנותר של הרכב"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"התאמת הערך של הטווח הנותר של הרכב."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"גישה למערכת החימום, הקירור והאוורור של הרכב"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"גישה למערכת החימום, האוורור ומיזוג האוויר (HVAC) של הרכב."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"גישה לנתוני הקילומטראז\' של הרכב"</string>
diff --git a/service/res/values-ja/strings.xml b/service/res/values-ja/strings.xml
index 9c8ad93..efcb9a1 100644
--- a/service/res/values-ja/strings.xml
+++ b/service/res/values-ja/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"車載カメラにアクセスします。"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"車のエネルギー情報へのアクセス"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"車のエネルギー情報にアクセスします。"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"車の航続可能距離の調整"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"車の航続可能距離の値を調整します。"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"車のエアコン ユニットへのアクセス"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"車のエアコン ユニットにアクセスします。"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"車の走行距離情報へのアクセス"</string>
diff --git a/service/res/values-ka/strings.xml b/service/res/values-ka/strings.xml
index d8343a8..ae72f8f 100644
--- a/service/res/values-ka/strings.xml
+++ b/service/res/values-ka/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"თქვენი მანქანის კამერებზე წვდომა."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"მანქანის ენერგორესურსების ინფორმაციაზე წვდომა"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"თქვენი მანქანის ენერგორესურსების ინფორმაციაზე წვდომა."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"მანქანის დიაპაზონის ნარჩენის კორექტირება"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"მანქანის დიაპაზონის დარჩენილი მნიშვნელობის კორექტირება."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"მანქანის HVAC (გათბობა, ვენტილაცია და ჰაერის კონდიცირება) სისტემაზე წვდომა"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"თქვენი მანქანის HVAC (გათბობა, ვენტილაცია და ჰაერის კონდიცირება) სისტემაზე წვდომა."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"მანქანის გარბენის შესახებ ინფორმაციაზე წვდომა"</string>
diff --git a/service/res/values-kk/strings.xml b/service/res/values-kk/strings.xml
index b031e9d..44f1fa9 100644
--- a/service/res/values-kk/strings.xml
+++ b/service/res/values-kk/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Көліктің камераларын пайдалануға болады."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"көлік қуаты туралы ақпаратты пайдалану"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Көліктің қуаты туралы ақпаратты көруге болады."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"көліктің қалған жүріп өтетін жолын өзгерту"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Көліктің қалған жүріп өтетін жолының мәнін өзгерту"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"көліктің климат басқару жүйесін пайдалану"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Көліктің кондиционерін пайдалануға болады."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"көліктің километражы туралы ақпаратты пайдалану"</string>
diff --git a/service/res/values-km/strings.xml b/service/res/values-km/strings.xml
index 3039b03..b8f6064 100644
--- a/service/res/values-km/strings.xml
+++ b/service/res/values-km/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"ចូលប្រើកាមេរ៉ារបស់រថយន្តអ្នក។"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"ចូលប្រើព័ត៌មានអំពីថាមពលរបស់រថយន្ត"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"ចូលប្រើព័ត៌មានថាមពលរបស់រថយន្តអ្នក។"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"កែតម្រូវរយៈចម្ងាយដែលរថយន្តអាចបន្តដំណើរការបាន"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"កែតម្រូវតម្លៃនៃរយៈចម្ងាយដែលរថយន្តអាចបន្តដំណើរការបាន។"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"ចូលប្រើប្រព័ន្ធកម្តៅ ខ្យល់ និងម៉ាស៊ីនត្រជាក់របស់រថយន្ត"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"ចូលប្រើប្រព័ន្ធកម្តៅ ខ្យល់ និងម៉ាស៊ីនត្រជាក់របស់រថយន្តអ្នក។"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"ចូលប្រើព័ត៌មានអំពីរយៈចម្ងាយរត់របស់រថយន្ត"</string>
diff --git a/service/res/values-kn/strings.xml b/service/res/values-kn/strings.xml
index 0473b2d..762aa2c 100644
--- a/service/res/values-kn/strings.xml
+++ b/service/res/values-kn/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"ನಿಮ್ಮ ಕಾರಿನ ಕ್ಯಾಮರವನ್ನು(ಗಳನ್ನು) ಪ್ರವೇಶಿಸಿ."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"ಕಾರಿನ ಶಕ್ತಿಯ ಬಳಕೆಯ ಮಾಹಿತಿ ಕುರಿತು ಪ್ರವೇಶಿಸಿ"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"ನಿಮ್ಮ ಕಾರಿನ ಶಕ್ತಿ ಮಾಹಿತಿಯನ್ನು ಪಡೆಯಿರಿ."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"ಬಾಕಿ ಉಳಿದ ಕಾರ್ನ ಶ್ರೇಣಿಯನ್ನು ಸರಿಹೊಂದಿಸಿ"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"ಕಾರ್ನ ಶ್ರೇಣಿಯ ಬಾಕಿ ಉಳಿದ ಮೌಲ್ಯವನ್ನು ಸರಿಹೊಂದಿಸಿ."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"ಕಾರಿನ ಹವಾನಿಯಂತ್ರಕದ ಮಾಹಿತಿ ಪಡೆಯಿರಿ"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"ಕಾರಿನ ಎಚ್ವಿಎಸಿಯ ಮಾಹಿತಿನ್ನು ಪಡೆಯಿರಿ."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"ಕಾರಿನ ಮೈಲೇಜ್ ಮಾಹಿತಿಯನ್ನು ಪಡೆಯಿರಿ"</string>
diff --git a/service/res/values-ko/strings.xml b/service/res/values-ko/strings.xml
index 4853d47..c3ac6c7 100644
--- a/service/res/values-ko/strings.xml
+++ b/service/res/values-ko/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"차량 카메라에 액세스"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"차량 에너지 정보 액세스"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"차량 에너지 정보에 액세스"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"차량의 잔여 주행거리 조정"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"차량의 잔여 주행거리를 조정하세요."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"차량 공조기에 액세스"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"차량 공조기에 액세스합니다."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"차량 주행 거리 정보에 액세스"</string>
diff --git a/service/res/values-ky/strings.xml b/service/res/values-ky/strings.xml
index f2a21df..eb4ba14 100644
--- a/service/res/values-ky/strings.xml
+++ b/service/res/values-ky/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Унааңыздын камераларын колдонуу."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"унаанын кубаты тууралуу маалыматты көрүү"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Унааңыздын кубаты тууралуу маалыматты көрүү."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"унаа дагы канча аралыкты басып өтөрүн тууралоо"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Унаа дагы канча аралыкты басып өтөрүн тууралоо."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"унаанын жылыткыч жана вентилиция тутумдарын көрүү"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Унааңыздын жылыткыч жана вентилиция тутумдарын көрүү."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"унаанын километраж маалыматын көрүү"</string>
diff --git a/service/res/values-lo/strings.xml b/service/res/values-lo/strings.xml
index 2fe6c4f..de7e03b 100644
--- a/service/res/values-lo/strings.xml
+++ b/service/res/values-lo/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"ເຂົ້າເຖິງກ້ອງຂອງລົດທ່ານ."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"ເຂົ້າເຖິງຂໍ້ມູນພະລັງງານຂອງລົດ"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"ເຂົ້າເຖິງຂໍ້ມູນພະລັງງານຂອງລົດທ່ານ."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"ປັບໄລຍະແລ່ນທີ່ເຫຼືອຢູ່ຂອງລົດ"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"ປັບຄ່າໄລຍະແລ່ນທີ່ເຫຼືອຢູ່ຂອງລົດ"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"ເຂົ້າເຖິງ HVAC ຂອງລົດ"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"ເຂົ້າເຖິງ HVAC ຂອງລົດທ່ານ."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"ເຂົ້າເຖິງຂໍ້ມູນໄລຍະໄມລ໌ຂອງລົດ"</string>
diff --git a/service/res/values-lt/strings.xml b/service/res/values-lt/strings.xml
index 2342259..02e4a18 100644
--- a/service/res/values-lt/strings.xml
+++ b/service/res/values-lt/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Pasiekti automobilio fotoaparatą (-us)."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"pasiekti automobilio energijos informaciją"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Pasiekti automobilio energijos informaciją."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"koreguoti automobilio likusį atstumą"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Koreguokite automobilio likusio atstumo vertę."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"pasiekti automobilio HVAC"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Pasiekti automobilio HVAC."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"pasiekti automobilio ridos informaciją"</string>
diff --git a/service/res/values-lv/strings.xml b/service/res/values-lv/strings.xml
index f926f13..3651dfc 100644
--- a/service/res/values-lv/strings.xml
+++ b/service/res/values-lv/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Piekļūt automašīnas kamerai(-ām)."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"piekļūt informācijai par automašīnas degvielas/uzlādes līmeni"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Piekļūt informācijai par automašīnas enerģiju."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"pielāgot automašīnas atlikušo attālumu"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Pielāgojiet automašīnas atlikušā attāluma vērtību."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"piekļūt automašīnas gaisa kondicionētājam"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Piekļūt automašīnas gaisa kondicionēšanas sistēmai."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"piekļūt informācijai par automašīnas nobraukumu"</string>
diff --git a/service/res/values-mk/strings.xml b/service/res/values-mk/strings.xml
index b419e52..48876e6 100644
--- a/service/res/values-mk/strings.xml
+++ b/service/res/values-mk/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Пристапува до камерите на автомобилот."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"пристапува до информациите за енергијата на автомобилот"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Пристапува до информациите за енергијата на автомобилот."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"приспособете ја преостанатата вредност на опсегот на автомобилот"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Приспособете ја преостанатата вредност на опсегот на автомобилот."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"пристапува до клима-уредот на автомобилот"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Пристапува до клима-уредот на автомобилот."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"пристапува до информациите за километража на автомобилот"</string>
diff --git a/service/res/values-ml/strings.xml b/service/res/values-ml/strings.xml
index 6e6007f..7250882 100644
--- a/service/res/values-ml/strings.xml
+++ b/service/res/values-ml/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"നിങ്ങളുടെ കാറിന്റെ ക്യാമറ(കൾ) ആക്സസ് ചെയ്യുക."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"കാറിൻ്റെ എനർജി വിവരങ്ങൾ ആക്സസ് ചെയ്യുക"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"നിങ്ങളുടെ കാറിന്റെ എനർജി വിവരങ്ങൾ ആക്സസ് ചെയ്യുക."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"കാറിൽ ശേഷിക്കുന്ന ഇന്ധനം ക്രമീകരിക്കുക"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"കാറിൽ ശേഷിക്കുന്ന ഇന്ധനത്തിന്റെ മൂല്യം ക്രമീകരിക്കുക."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"കാറിൻ്റെ hvac ആക്സസ് ചെയ്യുക"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"നിങ്ങളുടെ കാറിന്റെ hvac ആക്സസ് ചെയ്യുക."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"കാറിൻ്റെ മൈലേജ് വിവരങ്ങൾ ആക്സസ് ചെയ്യുക"</string>
diff --git a/service/res/values-mn/strings.xml b/service/res/values-mn/strings.xml
index 83da614..889d890 100644
--- a/service/res/values-mn/strings.xml
+++ b/service/res/values-mn/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Машиныхаа камерт хандана уу."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"машины эрчим хүчний мэдээлэлд хандах"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Машиныхаа эрчим хүчний мэдээлэлд хандана уу."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"автомашины туулах замын үлдсэн утгыг тохируулах"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Автомашины туулах замын үлдсэн утгыг тохируулна."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"машины халаалт, агааржуулалт болон aгаар цэвэршүүлэгчид хандах"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Машиныхаа халаалт, агааржуулалт болон aгаар цэвэршүүлэгчид хандана уу."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"машины милийн мэдээлэлд хандах"</string>
diff --git a/service/res/values-mr/strings.xml b/service/res/values-mr/strings.xml
index efdc646..9bf221b 100644
--- a/service/res/values-mr/strings.xml
+++ b/service/res/values-mr/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"तुमच्या कारचा(चे) कॅमेरा(रे) अॅक्सेस करा."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"कारच्या ऊर्जेची माहिती अॅक्सेस करा"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"तुमच्या कारची ऊर्जा माहिती अॅक्सेस करा."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"कारची शिल्लक रेंज अॅडजस्ट करा"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"कारच्या शिल्लक रेंजचे मूल्य अॅडजस्ट करा."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"कारचे hvac अॅक्सेस करा"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"तुमच्या कारचे hvac अॅक्सेस करा."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"कारच्या मायलेजची माहिती अॅक्सेस करा"</string>
diff --git a/service/res/values-ms/strings.xml b/service/res/values-ms/strings.xml
index 6869364..93e39e5 100644
--- a/service/res/values-ms/strings.xml
+++ b/service/res/values-ms/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Akses kamera kereta anda."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"akses maklumat tenaga kereta"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Akses maklumat tenaga kereta anda."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"laraskan baki julat kereta"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Laraskan baki nilai julat kereta."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"akses hvac kereta"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Akses hvac kereta anda."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"akses maklumat perbatuan kereta"</string>
diff --git a/service/res/values-my/strings.xml b/service/res/values-my/strings.xml
index e2e8572..e2768b1 100644
--- a/service/res/values-my/strings.xml
+++ b/service/res/values-my/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"သင့်ကား၏ ကင်မရာ(များ)ကို ဝင်ရောက်အသုံးပြုပါမည်။"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"ကား၏ စွမ်းအင်အချက်အလက်များကို ရယူပါမည်"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"ကား၏ စွမ်းအင်ဆိုင်ရာ အချက်အလက်ကို အသုံးပြုပါမည်။"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"ကား၏ အတိုင်းအတာ လက်ကျန်ကို ချိန်ညှိရန်"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"ကား၏ အတိုင်းအတာ လက်ကျန်တန်ဖိုးကို ချိန်ညှိရန်"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"ကား၏ hvac ကို အသုံးပြုပါမည်"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"သင့်ကား၏ \"havc စနစ်\" ကို အသုံးပြုပါမည်။"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"ကား၏ ခရီးမိုင်အချက်အလက်များကို ရယူပါမည်"</string>
diff --git a/service/res/values-nb/strings.xml b/service/res/values-nb/strings.xml
index 62108e6..6e20ffa 100644
--- a/service/res/values-nb/strings.xml
+++ b/service/res/values-nb/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Tilgang til bilens kamera(er)."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"få tilgang til bilens energiinformasjon"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Tilgang til informasjon om bilens energibruk."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"juster bilens gjenværende rekkevidde"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Juster verdien for bilens gjenværende rekkevidde."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"få tilgang til bilens klimaanlegg"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Tilgang til bilens klimaanlegg."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"få informasjon om bilens kjørelengde"</string>
diff --git a/service/res/values-ne/strings.xml b/service/res/values-ne/strings.xml
index add0fb9..76e6b61 100644
--- a/service/res/values-ne/strings.xml
+++ b/service/res/values-ne/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"तपाईंको कारका क्यामेरा(हरू) माथि पहुँच राख्ने।"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"कारको ऊर्जासम्बन्धी जानकारीमाथि पहुँच राख्ने"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"तपाईंको कारको ऊर्जासम्बन्धी जानकारीमाथि पहुँच राख्ने।"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"कारको दायराको बाँकी मान समायोजन गर्नुहोस्"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"कारको दायराको बाँकी मान समायोजन गर्नुहोस्।"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"कारको hvac प्रणालीमाथि पहुँच राख्ने"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"तपाईंको कारको hvac माथि पहुँच राख्ने।"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"कारको माइलेजसम्बन्धी जानकारीमाथि पहुँच राख्ने"</string>
diff --git a/service/res/values-nl/strings.xml b/service/res/values-nl/strings.xml
index 0959bb8..c99c2bc 100644
--- a/service/res/values-nl/strings.xml
+++ b/service/res/values-nl/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Toegang tot de camera(\'s) van je auto."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"toegang tot informatie over energieniveau van auto"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Toegang tot informatie over het energieniveau van je auto."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"resterende actieradius van auto aanpassen"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Waarde voor resterende actieradius van auto aanpassen."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"toegang tot HVAC van auto"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Toegang tot de HVAC van je auto."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"toegang tot informatie over kilometerstand van auto"</string>
diff --git a/service/res/values-or/strings.xml b/service/res/values-or/strings.xml
index 2d90b94..88558cd 100644
--- a/service/res/values-or/strings.xml
+++ b/service/res/values-or/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"ଆପଣଙ୍କ କାର୍ର କ୍ୟାମେରା(ଗୁଡ଼ିକ) ଆକ୍ସେସ୍ କରିପାରେ।"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"କାର୍\'ର ଏନାର୍ଜି ସୂଚନାକୁ ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"ଆପଣଙ୍କ କାର୍ର ଶକ୍ତି ସୂଚନା ଆକ୍ସେସ୍ କରିପାରେ।"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"କାର୍ର ରେଞ୍ଜ୍ ପାଇଁ ଅବଶିଷ୍ଟ ମୂଲ୍ୟ ଆଡ୍ଜଷ୍ଟ୍ କରନ୍ତୁ"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"କାର୍ର ରେଞ୍ଜ୍ ପାଇଁ ଅବଶିଷ୍ଟ ମୂଲ୍ୟ ଆଡ୍ଜଷ୍ଟ୍ କରନ୍ତୁ।"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"କାର୍\'ର hvac ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"ଆପଣଙ୍କ କାର୍ର hvac ଆକ୍ସେସ୍ କରିପାରେ।"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"କାର୍\'ର ମାଇଲେଜ୍ ସୂଚନାକୁ ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
diff --git a/service/res/values-pa/strings.xml b/service/res/values-pa/strings.xml
index d3700ed..c05ae86 100644
--- a/service/res/values-pa/strings.xml
+++ b/service/res/values-pa/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"ਤੁਹਾਡੀ ਕਾਰ ਦੇ ਕੈਮਰੇ ਤੱਕ ਪਹੁੰਚ।"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"ਕਾਰ ਦੀ ਊਰਜਾ ਸੰਬੰਧੀ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"ਤੁਹਾਡੀ ਕਾਰ ਦੀ ਊਰਜਾ ਸੰਬੰਧੀ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ।"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"ਕਾਰ ਦੀ ਬਾਕੀ ਰੇਂਜ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰੋ"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"ਕਾਰ ਦੀ ਬਾਕੀ ਰੇਂਜ ਦੇ ਮੁੱਲ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰੋ।"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"ਕਾਰ ਦੇ hvac ਤੱਕ ਪਹੁੰਚ"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"ਤੁਹਾਡੀ ਕਾਰ ਦੇ hvac ਸਿਸਟਮ ਤੱਕ ਪਹੁੰਚ।"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"ਕਾਰ ਦੀ ਮਾਈਲੇਜ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ"</string>
diff --git a/service/res/values-pl/strings.xml b/service/res/values-pl/strings.xml
index 593181e..de75fbc 100644
--- a/service/res/values-pl/strings.xml
+++ b/service/res/values-pl/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Dostęp do kamer samochodu."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"dostęp do informacji o zasilaniu w samochodzie"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Dostęp do informacji o zasilaniu w samochodzie."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"korekta pozostałego zasięgu samochodu"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Korekta wartości pozostałego zasięgu samochodu."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"dostęp do systemu sterowania temperaturą w samochodzie"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Dostęp do systemu sterowania temperaturą w samochodzie."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"dostęp do informacji o przebiegu samochodu"</string>
diff --git a/service/res/values-pt-rPT/strings.xml b/service/res/values-pt-rPT/strings.xml
index 3ba192b..ed29788 100644
--- a/service/res/values-pt-rPT/strings.xml
+++ b/service/res/values-pt-rPT/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Aceda à(s) câmara(s) do automóvel."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"aceder às informações de energia do automóvel"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Aceda às informações de energia do automóvel."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"ajustar o funcionamento restante do automóvel"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Ajuste o valor restante do funcionamento do automóvel."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"aceder ao AVAC do automóvel"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Aceda ao AVAC do automóvel."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"aceder às informações de quilometragem do automóvel"</string>
diff --git a/service/res/values-pt/strings.xml b/service/res/values-pt/strings.xml
index 3a002c3..c1ef3f5 100644
--- a/service/res/values-pt/strings.xml
+++ b/service/res/values-pt/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Acessar câmeras do carro."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"acessar as informações de energia do carro"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Acessar informações de abastecimento do carro."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"ajustar a autonomia restante do carro"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Ajustar o valor restante de autonomia do carro."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"acessar o HVAC (Aquecimento, ventilação e ar condicionado) do carro"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Acessar o HVAC (Aquecimento, ventilação e ar condicionado) do carro."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"acessar informações de quilometragem do carro"</string>
diff --git a/service/res/values-ro/strings.xml b/service/res/values-ro/strings.xml
index 6f48c30..06a6774 100644
--- a/service/res/values-ro/strings.xml
+++ b/service/res/values-ro/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Accesează camerele mașinii."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"Accesează informațiile despre nivelul de energie al mașinii"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Accesează informațiile despre energie ale mașinii."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"ajustați restul distanței parcurse de mașină"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Ajustați restul distanței parcurse de mașină."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"Accesează sistemul hvac al mașinii"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Accesează sistemul hvac al mașinii."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"Accesează informațiile despre kilometrajul mașinii"</string>
diff --git a/service/res/values-ru/strings.xml b/service/res/values-ru/strings.xml
index 205d54a..387a06a 100644
--- a/service/res/values-ru/strings.xml
+++ b/service/res/values-ru/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Доступ к камерам автомобиля"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"доступ к данным об энергоресурсах автомобиля"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Доступ к данным об энергоресурсах автомобиля"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"Изменение расстояния, которое проедет автомобиль без дозаправки"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Изменение расстояния, которое проедет автомобиль без дозаправки"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"доступ к системе ОВиК"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Доступ к системе ОВиК"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"доступ к данным о пробеге"</string>
diff --git a/service/res/values-si/strings.xml b/service/res/values-si/strings.xml
index 49e9ce4..003c285 100644
--- a/service/res/values-si/strings.xml
+++ b/service/res/values-si/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"ඔබේ මෝටර් රථයේ කැමරා(ව) වෙත ප්රවේශ වන්න."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"මෝටර් රථයේ බලශක්ති තොරතුරුවලට ප්රවේශ වන්න"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"ඔබේ මෝටර් රථයේ බල ශක්ති තොරතුරු වෙත ප්රවේශ වන්න."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"මෝටර් රථ පරාසයේ ඉතිරිය ගළපන්න"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"මෝටර් රථ පරාසයේ ඉතිරිව ඇති අගය ගළපන්න."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"මෝටර් රථයේ hvac වෙත ප්රවේශ වන්න"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"ඔබේ මෝටර් රථයේ hvac වෙත ප්රවේශ වන්න."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"මෝටර් රථයේ ධාවන දුර තොරතුරුවලට ප්රවේශ වන්න"</string>
diff --git a/service/res/values-sk/strings.xml b/service/res/values-sk/strings.xml
index 8e5cb3e..922f93f 100644
--- a/service/res/values-sk/strings.xml
+++ b/service/res/values-sk/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Získajte prístup ku kamerám auta."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"získať prístup k informáciám o energii auta"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Získajte prístup k informáciám o palive a energii auta."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"úprava dojazdu auta – zostatok"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Úprava zostávajúcej hodnoty dojazdu auta."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"získať prístup ku kúreniu, vzduchotechnike a klimatizácii auta"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Získajte prístup k vykurovaniu, ventilácii a klimatizácii auta."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"získať prístup k informáciám o spotrebe auta"</string>
diff --git a/service/res/values-sl/strings.xml b/service/res/values-sl/strings.xml
index 2e00b3a..b1aa949 100644
--- a/service/res/values-sl/strings.xml
+++ b/service/res/values-sl/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Dostop do kamer avtomobila."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"dostop do podatkov o energiji avtomobila"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Dostop do podatkov o energiji avtomobila."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"prilagajanje preostalega dosega avtomobila"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Prilagajanje preostale vrednosti dosega avtomobila."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"dostop do sistema za ogrevanje, hlajenje in prezračevanje avtomobila"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Dostop do sistema za ogrevanje, hlajenje in prezračevanje avtomobila."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"dostop o podatkov o prevoženih kilometrih avtomobila"</string>
diff --git a/service/res/values-sq/strings.xml b/service/res/values-sq/strings.xml
index f7f4684..a550aae 100644
--- a/service/res/values-sq/strings.xml
+++ b/service/res/values-sq/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Qasu te kamera(t) e makinës."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"qasu tek informacionet e energjisë së makinës"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Qasu tek informacionet e energjisë së makinës."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"rregullo vlerën e mbetur të gamës së makinës"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Rregullo vlerën e mbetur të gamës së makinës."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"qasu në sistemin HVAC të makinës"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Qasu në sistemin HVAC të makinës."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"qasu tek informacionet e kilometrazhit të makinës"</string>
diff --git a/service/res/values-sr/strings.xml b/service/res/values-sr/strings.xml
index 0983a07..59ef4b9 100644
--- a/service/res/values-sr/strings.xml
+++ b/service/res/values-sr/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Приступи камерама аутомобила."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"приступ подацима о енергији аутомобила"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Приступи информацијама о енергији аутомобила."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"прилагођавање преосталог домета аутомобила"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Прилагођавање вредности преосталог домета аутомобила."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"приступ грејању, вентилацији и климатизацији аутомобила"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Приступи грејању, вентилацији и климатизацији аутомобила"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"приступ подацима о километражи аутомобила"</string>
diff --git a/service/res/values-sv/strings.xml b/service/res/values-sv/strings.xml
index 3f0ea0c..939fc3f 100644
--- a/service/res/values-sv/strings.xml
+++ b/service/res/values-sv/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Åtkomst till bilens kamera eller kameror."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"åtkomst till information om bilens drivmedel"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Åtkomst till information om bilens drivmedel."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"justera värdet på bilens återstående körsträcka"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Får justera värdet på bilens återstående körsträcka."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"åtkomst till bilens värme, ventilation och luftkonditionering"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Åtkomst till bilens värme-, ventilations- och AC-system."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"åtkomst till information om bilens bränsleförbrukning"</string>
diff --git a/service/res/values-sw/strings.xml b/service/res/values-sw/strings.xml
index 0619eac..2608cc3 100644
--- a/service/res/values-sw/strings.xml
+++ b/service/res/values-sw/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Kufikia kamera ya gari lako."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"kufikia maelezo ya nishati ya gari"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Kufikia maelezo ya nishati ya gari lako."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"kurekebisha umbali unaosalia wa kusafiri wa gari"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Kurekebisha thamani inayosalia ya umbali wa kusafiri wa gari."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"kufikia hali ya joto, hewa na kiyoyozi (hvac) katika gari"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Kufikia hali ya joto, hewa na kiyoyozi (hvac) ya gari lako."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"kufikia maelezo ya maili za gari"</string>
diff --git a/service/res/values-ta/strings.xml b/service/res/values-ta/strings.xml
index 8eab4ef..d9e53ce 100644
--- a/service/res/values-ta/strings.xml
+++ b/service/res/values-ta/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"காரின் கேமராவை அணுகுதல்."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"காரின் எரிபொருள் விவரத்தை அணுக வேண்டும்"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"காரின் எரிபொருள் தகவலை அணுகுதல்."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"கார் சென்றடைய மீதமுள்ள மைலேஜின் மதிப்பை மாற்றும்"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"கார் சென்றடைய மீதமுள்ள மைலேஜின் மதிப்பை மாற்றும்."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"காரின் hvac சிஸ்டத்தை அணுக வேண்டும்"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"காரில் வெப்பம், காற்றோட்டம், குளிர்சாதன வசதி ஆகியவற்றை உள்ளடக்கிய அமைப்பை (hvac) அணுகுதல்."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"காரின் மைலேஜ் பற்றிய தகவலை அணுக வேண்டும்"</string>
diff --git a/service/res/values-te/strings.xml b/service/res/values-te/strings.xml
index 494e476..e5eab73 100644
--- a/service/res/values-te/strings.xml
+++ b/service/res/values-te/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"మీ కారు యొక్క కామెరా(లు)ని యాక్సెస్ చేయండి."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"కారు శక్తి సమాచారాన్ని యాక్సెస్ చేయగలవు"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"మీ కారు శక్తి సమాచారాన్ని యాక్సెస్ చేయండి."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"కారు యొక్క మిగిలిన ప్రయాణ దూరాన్ని సర్దుబాటు చేయండి"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"కారు యొక్క మిగిలిన ప్రయాణ దూర విలువను సర్దుబాటు చేయండి."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"కారు hvacని యాక్సెస్ చేయగలవు"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"మీ కారు యొక్క hvacని యాక్సెస్ చేయండి"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"కారు మైలేజీ సమాచారాన్ని యాక్సెస్ చేయగలవు"</string>
diff --git a/service/res/values-th/strings.xml b/service/res/values-th/strings.xml
index 197bc75..eb437d7 100644
--- a/service/res/values-th/strings.xml
+++ b/service/res/values-th/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"เข้าถึงกล้องของรถ"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"เข้าถึงข้อมูลพลังงานของรถ"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"เข้าถึงข้อมูลพลังงานของรถ"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"ปรับระยะวิ่งที่เหลืออยู่ของรถ"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"ปรับค่าระยะวิ่งที่เหลืออยู่ของรถ"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"เข้าถึง HVAC ของรถ"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"เข้าถึง HVAC ของรถ"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"เข้าถึงข้อมูลระยะไมล์ของรถ"</string>
diff --git a/service/res/values-tl/strings.xml b/service/res/values-tl/strings.xml
index d50637f..9aa1d35 100644
--- a/service/res/values-tl/strings.xml
+++ b/service/res/values-tl/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"I-access ang (mga) camera ng iyong sasakyan."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"i-access ang impormasyon ng enerhiya ng sasakyan"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"I-access ang impormasyon sa enerhiya ng iyong sasakyan."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"isaayos ang natitirang range ng sasakyan"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Isaayos ang value ng natitirang range ng sasakyan."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"i-access ang hvac ng sasakyan"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"I-access ang hvac ng iyong sasakyan."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"i-access ang impormasyon ng mileage ng sasakyan"</string>
diff --git a/service/res/values-tr/strings.xml b/service/res/values-tr/strings.xml
index 861d4cb..22d4981 100644
--- a/service/res/values-tr/strings.xml
+++ b/service/res/values-tr/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Aracınızın kameralarına erişim."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"aracın enerji bilgilerine erişim"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Aracınızın enerji bilgilerine erişim."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"aracın kalan menzil değerini düzenleme"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Aracın kalan menzil değerini düzenler."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"aracın HVAC\'sine erişim"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Aracınızın HVAC\'sine erişim."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"aracın kilometre bilgilerine erişim"</string>
diff --git a/service/res/values-uk/strings.xml b/service/res/values-uk/strings.xml
index 24fc867..3fdcfef 100644
--- a/service/res/values-uk/strings.xml
+++ b/service/res/values-uk/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Доступ до камер автомобіля."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"доступ до інформації про енергоспоживання автомобіля"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Доступ до інформації про енергоспоживання автомобіля."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"коригувати залишок пробігу автомобіля"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Коригувати значення залишку пробігу автомобіля."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"доступ до системи клімат-контролю автомобіля"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Доступ до системи клімат-контролю автомобіля."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"доступ до інформації про пробіг автомобіля"</string>
diff --git a/service/res/values-ur/strings.xml b/service/res/values-ur/strings.xml
index 58f1aca..51c2bba 100644
--- a/service/res/values-ur/strings.xml
+++ b/service/res/values-ur/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"اپنی کار کے کیمرے (کیمروں) تک رسائی حاصل کریں۔"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"کار کی انرجی کی معلومات تک رسائی حاصل کریں"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"اپنی کار کی انرجی کی معلومات تک رسائی حاصل کریں۔"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"کار کی باقی حد ایڈجسٹ کریں"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"کار کی باقی حد قدر کو ایڈجسٹ کریں۔"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"کار کی hvac تک رسائی حاصل کریں"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"اپنی کار کی hvac تک رسائی حاصل کریں۔"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"کار کی مائلیج کی معلومات تک رسائی حاصل کریں"</string>
diff --git a/service/res/values-uz/strings.xml b/service/res/values-uz/strings.xml
index f6bfb87..8837e46 100644
--- a/service/res/values-uz/strings.xml
+++ b/service/res/values-uz/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Avtomobil kamerasidan foydalanish"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"avtomobilning energiya manbalari haqidagi axborotga kirish"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Avtomobilning energiya axborotlariga kirish"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"avtomobil mavjud yonilgʻi bilan bosib oʻtadigan masofani tuzatish"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Avtomobil mavjud yonilgʻi bilan bosib oʻtadigan masofani tuzatish."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"avtomobilning HVAC tizimiga kirish"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Avtomobilning HVAC tizimiga kirish."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"avtomobil yonilgʻisi qancha masofaga yetishi haqidagi axborotga kirish"</string>
diff --git a/service/res/values-vi/strings.xml b/service/res/values-vi/strings.xml
index 57be52a..559d586 100644
--- a/service/res/values-vi/strings.xml
+++ b/service/res/values-vi/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Truy cập vào (các) camera trên ô tô."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"truy cập vào thông tin về năng lượng của ô tô"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Truy cập vào thông tin về mức năng lượng trên ô tô."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"điều chỉnh quãng đường còn đi được của ô tô"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Điều chỉnh giá trị quãng đường còn đi được của ô tô."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"truy cập vào hệ thống điều hòa không khí (hvac) của ô tô"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Truy cập vào hvac của ô tô."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"truy cập vào thông tin về quãng đường đi được của ô tô"</string>
diff --git a/service/res/values-zh-rCN/strings.xml b/service/res/values-zh-rCN/strings.xml
index b30acc4..8bbfc70 100644
--- a/service/res/values-zh-rCN/strings.xml
+++ b/service/res/values-zh-rCN/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"访问汽车摄像头。"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"访问汽车的能耗信息"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"访问汽车的能耗信息。"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"调整汽车的剩余可行驶距离"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"调整汽车的剩余可行驶距离值。"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"访问汽车的暖通空调"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"访问汽车的 HVAC。"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"访问汽车的行驶里程信息"</string>
diff --git a/service/res/values-zh-rHK/strings.xml b/service/res/values-zh-rHK/strings.xml
index e344bfb..296ab1b 100644
--- a/service/res/values-zh-rHK/strings.xml
+++ b/service/res/values-zh-rHK/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"存取汽車攝錄機。"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"存取汽車的能源資訊"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"存取汽車的電量資訊。"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"調整汽車油量餘額"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"調整汽車油量餘額。"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"存取汽車的暖通空調"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"存取汽車的暖通空調。"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"存取汽車里數資訊"</string>
diff --git a/service/res/values-zh-rTW/strings.xml b/service/res/values-zh-rTW/strings.xml
index 1848811..30a5f66 100644
--- a/service/res/values-zh-rTW/strings.xml
+++ b/service/res/values-zh-rTW/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"存取車輛攝影機。"</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"存取車輛的能源資訊"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"存取車輛的能源資訊。"</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"調整汽車的剩餘可行駛距離"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"調整汽車的剩餘可行駛距離值。"</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"存取車輛空調"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"存取車輛空調。"</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"存取車輛的行駛里程資訊"</string>
@@ -73,8 +75,8 @@
<string name="car_permission_desc_diag_read" msgid="1121426363040966178">"讀取車輛的診斷資料。"</string>
<string name="car_permission_label_diag_clear" msgid="4783070510879698157">"清除診斷資料"</string>
<string name="car_permission_desc_diag_clear" msgid="7453222114866042786">"清除車輛的診斷資料。"</string>
- <string name="car_permission_label_vms_publisher" msgid="3049934078926106641">"VMS 發佈者"</string>
- <string name="car_permission_desc_vms_publisher" msgid="5589489298597386828">"發佈 VMS 訊息"</string>
+ <string name="car_permission_label_vms_publisher" msgid="3049934078926106641">"VMS 發布者"</string>
+ <string name="car_permission_desc_vms_publisher" msgid="5589489298597386828">"發布 VMS 訊息"</string>
<string name="car_permission_label_vms_subscriber" msgid="5648841182059222299">"VMS 訂閱者"</string>
<string name="car_permission_desc_vms_subscriber" msgid="7551009457847673620">"訂閱 VMS 訊息"</string>
<string name="car_permission_label_bind_vms_client" msgid="4889732900973280313">"VMS 用戶端服務"</string>
diff --git a/service/res/values-zu/strings.xml b/service/res/values-zu/strings.xml
index 7225857..e2b6b3c 100644
--- a/service/res/values-zu/strings.xml
+++ b/service/res/values-zu/strings.xml
@@ -22,6 +22,8 @@
<string name="car_permission_desc_camera" msgid="917024932164501426">"Finyelela ikhamera yemoto yakho."</string>
<string name="car_permission_label_energy" msgid="7409144323527821558">"finyelela ulwazi lamandla lemoto"</string>
<string name="car_permission_desc_energy" msgid="3392963810053235407">"Finyelela ulwazi lwamandla lwemoto yakho."</string>
+ <string name="car_permission_label_adjust_range_remaining" msgid="839033553999920138">"lungisa ivelu elisele lebanga lemoto"</string>
+ <string name="car_permission_desc_adjust_range_remaining" msgid="2369321650437370673">"Lungisa ivelu elisele lebanga lemoto."</string>
<string name="car_permission_label_hvac" msgid="1499454192558727843">"i-hvac yemoto"</string>
<string name="car_permission_desc_hvac" msgid="3754229695589774195">"Finyelela i-hvac yemoto yakho."</string>
<string name="car_permission_label_mileage" msgid="4661317074631150551">"finyelela ulwazi lwe-mileage lemoto"</string>
diff --git a/service/src/com/android/car/CarUxRestrictionsManagerService.java b/service/src/com/android/car/CarUxRestrictionsManagerService.java
index 1732aa8..bb49ff2 100644
--- a/service/src/com/android/car/CarUxRestrictionsManagerService.java
+++ b/service/src/com/android/car/CarUxRestrictionsManagerService.java
@@ -174,6 +174,7 @@
@Override
public List<CarUxRestrictionsConfiguration> getConfigs() {
+ ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_UX_RESTRICTIONS_CONFIGURATION);
return new ArrayList<>(mCarUxRestrictionsConfigurations.values());
}
@@ -415,6 +416,8 @@
@Override
@Nullable
public List<CarUxRestrictionsConfiguration> getStagedConfigs() {
+ ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_UX_RESTRICTIONS_CONFIGURATION);
+
File stagedConfig = getFile(CONFIG_FILENAME_STAGED);
if (stagedConfig.exists()) {
logd("Attempting to read staged config");
diff --git a/service/src/com/android/car/Standards.kt b/service/src/com/android/car/Standards.kt
new file mode 100644
index 0000000..272b44f
--- /dev/null
+++ b/service/src/com/android/car/Standards.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.car
+
+/**
+ * Identical to [also]. Use to communicate intent of guarding against null. Compatible with
+ * `?:` (elvis operator) if else block is needed.
+ *
+ * Example:
+ * ```
+ * array.firstOrNull()?.guard { Log.d(TAG, "$it is guaranteed to not be null here") }
+ * ```
+ *
+ */
+internal inline fun <T> T.guard(block: (T) -> Unit): T {
+ return this.also(block)
+}
\ No newline at end of file
diff --git a/service/src/com/android/car/VmsPublishersInfo.java b/service/src/com/android/car/VmsPublishersInfo.java
index 4a75953..78ec9fb 100644
--- a/service/src/com/android/car/VmsPublishersInfo.java
+++ b/service/src/com/android/car/VmsPublishersInfo.java
@@ -16,13 +16,13 @@
package com.android.car;
+import android.util.ArrayMap;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
public class VmsPublishersInfo {
private static final String TAG = "VmsPublishersInfo";
@@ -31,9 +31,9 @@
private final Object mLock = new Object();
@GuardedBy("mLock")
- private final Map<InfoWrapper, Integer> mPublishersIds = new HashMap<>();
+ private final ArrayMap<InfoWrapper, Integer> mPublishersIds = new ArrayMap<>();
@GuardedBy("mLock")
- private final Map<Integer, byte[]> mPublishersInfo = new HashMap<>();
+ private final ArrayList<InfoWrapper> mPublishersInfo = new ArrayList<>();
private static class InfoWrapper {
private final byte[] mInfo;
@@ -43,7 +43,7 @@
}
public byte[] getInfo() {
- return mInfo;
+ return mInfo.clone();
}
@Override
@@ -62,15 +62,24 @@
}
/**
- * Returns the ID associated with the publisher info. When called for the first time for a
- * publisher info will store the info and assign an ID
+ * Retrieves the publisher ID for the given publisher information. If the publisher information
+ * has not previously been seen, it will be assigned a new publisher ID.
+ *
+ * @param publisherInfo Publisher information to query or register.
+ * @return Publisher ID for the given publisher information.
*/
public int getIdForInfo(byte[] publisherInfo) {
Integer publisherId;
InfoWrapper wrappedPublisherInfo = new InfoWrapper(publisherInfo);
synchronized (mLock) {
- maybeAddPublisherInfoLocked(wrappedPublisherInfo);
+ // Check if publisher is already registered
publisherId = mPublishersIds.get(wrappedPublisherInfo);
+ if (publisherId == null) {
+ // Add the new publisher and assign it the next ID
+ mPublishersInfo.add(wrappedPublisherInfo);
+ publisherId = mPublishersInfo.size();
+ mPublishersIds.put(wrappedPublisherInfo, publisherId);
+ }
}
if (DBG) {
Log.i(TAG, "Publisher ID is: " + publisherId);
@@ -78,22 +87,16 @@
return publisherId;
}
+ /**
+ * Returns the publisher info associated with the given publisher ID.
+ * @param publisherId Publisher ID to query.
+ * @return Publisher info associated with the ID, or an empty array if publisher ID is unknown.
+ */
public byte[] getPublisherInfo(int publisherId) {
synchronized (mLock) {
- return mPublishersInfo.containsKey(publisherId)
- ? mPublishersInfo.get(publisherId).clone()
- : EMPTY_RESPONSE;
- }
- }
-
- @GuardedBy("mLock")
- private void maybeAddPublisherInfoLocked(InfoWrapper wrappedPublisherInfo) {
- if (!mPublishersIds.containsKey(wrappedPublisherInfo)) {
- // Assign ID to the info
- Integer publisherId = mPublishersIds.size();
-
- mPublishersIds.put(wrappedPublisherInfo, publisherId);
- mPublishersInfo.put(publisherId, wrappedPublisherInfo.getInfo());
+ return publisherId < 1 || publisherId > mPublishersInfo.size()
+ ? EMPTY_RESPONSE
+ : mPublishersInfo.get(publisherId - 1).getInfo();
}
}
}
diff --git a/service/src/com/android/car/pm/TEST_MAPPING b/service/src/com/android/car/pm/TEST_MAPPING
new file mode 100644
index 0000000..d37fe3d
--- /dev/null
+++ b/service/src/com/android/car/pm/TEST_MAPPING
@@ -0,0 +1,34 @@
+{
+ "auto-postsubmit": [
+ {
+ "name": "CarServiceTest",
+ "options" : [
+ {
+ "include-filter": "com.android.car.pm.CarPackageManagerServiceTest"
+ },
+ {
+ "include-filter": "com.android.car.CarPackageManagerTest"
+ }
+ ]
+ },
+ {
+ "name": "CarServiceUnitTest",
+ "options" : [
+ {
+ "include-filter": "com.android.car.pm.VendorServiceControllerTest"
+ },
+ {
+ "include-filter": "com.android.car.pm.VendorServiceInfoTest"
+ }
+ ]
+ },
+ {
+ "name": "AndroidCarApiTest",
+ "options": [
+ {
+ "include-filter": "android.car.apitest.CarPackageManagerTest"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/service/src/com/android/car/storagemonitoring/TEST_MAPPING b/service/src/com/android/car/storagemonitoring/TEST_MAPPING
new file mode 100644
index 0000000..a43eed0
--- /dev/null
+++ b/service/src/com/android/car/storagemonitoring/TEST_MAPPING
@@ -0,0 +1,23 @@
+{
+ "auto-postsubmit": [
+ {
+ "name": "CarServiceTest",
+ "options" : [
+ {
+ "include-filter": "com.android.car.CarStorageMonitoringTest"
+ }
+ ]
+ },
+ {
+ "name": "CarServiceUnitTest",
+ "options" : [
+ {
+ "include-filter": "com.android.car.storagemonitoring.CarStorageMonitoringTest"
+ },
+ {
+ "include-filter": "com.android.car.storagemonitoring.IoStatsTrackerTest"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/service/src/com/android/car/trust/BLEVersionExchangeResolver.java b/service/src/com/android/car/trust/BLEVersionExchangeResolver.java
index 7bdb27e..d5c7383 100644
--- a/service/src/com/android/car/trust/BLEVersionExchangeResolver.java
+++ b/service/src/com/android/car/trust/BLEVersionExchangeResolver.java
@@ -16,15 +16,14 @@
package com.android.car.trust;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattServer;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
-import androidx.annotation.Nullable;
-
import com.android.car.BLEStreamProtos.VersionExchangeProto.BLEVersionExchange;
/**
@@ -42,15 +41,19 @@
* {@link BluetoothDevice} based on the version exchange proto.
*
* @param versionExchange The version exchange proto to resolve
- * @param device The device to send messages to.
- * @param readCharacteristic The characteristic the device will use to write messages to.
- * @param writeCharacteristic The characteristic on the device that message can be written to.
+ * @param device The remote device to send messages to.
+ * @param readCharacteristic The characteristic the remote device will use to write messages to.
+ * This is the characteristic this IHU will read from.
+ * @param writeCharacteristic The characteristic on the remote device that this IHU can write
+ * messages to.
* @return A stream that can send message or {@code null} if resolution was not possible.
*/
@Nullable
- static BleMessageStream resolveToStream(BLEVersionExchange versionExchange,
- BluetoothDevice device, BluetoothGattServer gattServer,
- BluetoothGattCharacteristic writeCharacteristic) {
+ static BleMessageStream resolveToStream(
+ @NonNull BLEVersionExchange versionExchange,
+ @NonNull BluetoothDevice device, @NonNull BlePeripheralManager blePeripheralManager,
+ @NonNull BluetoothGattCharacteristic writeCharacteristic,
+ @NonNull BluetoothGattCharacteristic readCharacteristic) {
int minMessagingVersion = versionExchange.getMinSupportedMessagingVersion();
int minSecurityVersion = versionExchange.getMinSupportedSecurityVersion();
@@ -62,7 +65,11 @@
// Only one supported version, so ensure the minimum version matches.
if (minMessagingVersion == MESSAGING_VERSION && minSecurityVersion == SECURITY_VERSION) {
return new BleMessageStreamV1(
- new Handler(Looper.getMainLooper()), device, gattServer, writeCharacteristic);
+ new Handler(Looper.getMainLooper()),
+ blePeripheralManager,
+ device,
+ writeCharacteristic,
+ readCharacteristic);
}
return null;
@@ -72,6 +79,7 @@
* Returns a version exchange proto with the maximum and minimum protocol and security versions
* this device currently supports.
*/
+ @NonNull
static BLEVersionExchange makeVersionExchange() {
return BLEVersionExchange.newBuilder()
.setMinSupportedMessagingVersion(MESSAGING_VERSION)
diff --git a/service/src/com/android/car/trust/BleCentralManager.kt b/service/src/com/android/car/trust/BleCentralManager.kt
new file mode 100644
index 0000000..cdf5864
--- /dev/null
+++ b/service/src/com/android/car/trust/BleCentralManager.kt
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.car.trust
+
+import android.bluetooth.BluetoothAdapter
+import android.bluetooth.le.BluetoothLeScanner
+import android.bluetooth.le.ScanCallback
+import android.bluetooth.le.ScanFilter
+import android.bluetooth.le.ScanResult
+import android.bluetooth.le.ScanSettings
+import android.content.Context
+import android.content.pm.PackageManager
+import android.os.Handler
+import android.util.Log
+import com.android.car.guard
+import com.android.internal.annotations.GuardedBy
+
+private const val TAG = "BleCentralManager"
+
+private const val RETRY_LIMIT = 5
+private const val RETRY_INTERVAL_MS = 1000
+
+/**
+ * Class that manages BLE scanning operations.
+ */
+open class BleCentralManager(val context: Context) {
+
+ private var scanFilters: List<ScanFilter>? = null
+ private var scanSettings: ScanSettings? = null
+ private var scanCallback: ScanCallback? = null
+ private var scanner: BluetoothLeScanner? = null
+ private var scannerStartCount = 0
+ private val handler = Handler()
+
+ // Internally track scanner state to avoid restarting a stopped scanner
+ private enum class ScannerState {
+ STOPPED,
+ STARTED,
+ SCANNING
+ }
+
+ @GuardedBy("this")
+ @Volatile
+ private var scannerState = ScannerState.STOPPED
+
+ /**
+ * Start the BLE scanning process.
+ *
+ * @param filters Optional [ScanFilter]s to apply to scan results.
+ * @param settings [ScanSettings] to apply to scanner.
+ * @param callback [ScanCallback] for scan events.
+ */
+ fun startScanning(
+ filters: List<ScanFilter>?,
+ settings: ScanSettings,
+ callback: ScanCallback
+ ) {
+ if (!context.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
+ Log.e(TAG, "Attempted start scanning, but system does not support BLE. Ignoring")
+ return
+ }
+
+ scannerStartCount = 0
+ scanFilters = filters
+ scanSettings = settings
+ scanCallback = callback
+ updateScannerState(ScannerState.STARTED)
+ startScanningInternally()
+ }
+
+ private fun startScanningInternally() {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Attempting to start scanning")
+ }
+ if (scanner == null && BluetoothAdapter.getDefaultAdapter() != null) {
+ scanner = BluetoothAdapter.getDefaultAdapter().bluetoothLeScanner
+ }
+ scanner?.guard {
+ it.startScan(scanFilters, scanSettings, internalScanCallback)
+ updateScannerState(ScannerState.SCANNING)
+ } ?: run {
+ // Keep trying
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Scanner unavailable. Trying again.")
+ }
+ handler.postDelayed({ startScanningInternally() }, RETRY_INTERVAL_MS.toLong())
+ }
+ }
+
+ /** Stop the scanner */
+ fun stopScanning() {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Attempting to stop scanning")
+ }
+ scanner?.stopScan(internalScanCallback)
+ scanCallback = null
+ updateScannerState(ScannerState.STOPPED)
+ }
+
+ private fun updateScannerState(newState: ScannerState) {
+ synchronized(this) {
+ scannerState = newState
+ }
+ }
+
+ /** Returns [true] if currently scanning. */
+ fun isScanning(): Boolean {
+ synchronized(this) {
+ return scannerState === ScannerState.SCANNING
+ }
+ }
+
+ /** Clean up the scanning process. */
+ fun cleanup() {
+ scanner?.cleanup()
+ }
+
+ private val internalScanCallback = object : ScanCallback() {
+ override fun onScanResult(callbackType: Int, result: ScanResult) {
+ scanCallback?.onScanResult(callbackType, result)
+ }
+
+ override fun onBatchScanResults(results: List<ScanResult>) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Batch scan found " + results.size + " results.")
+ }
+ scanCallback?.onBatchScanResults(results)
+ }
+
+ override fun onScanFailed(errorCode: Int) {
+ if (scannerStartCount >= RETRY_LIMIT) {
+ Log.e(TAG, "Cannot start BLE Scanner. BT Adapter: " +
+ "${BluetoothAdapter.getDefaultAdapter()} Scanning Retry count: " +
+ scannerStartCount)
+ scanCallback?.onScanFailed(errorCode)
+ return
+ }
+ scannerStartCount++
+ Log.w(TAG, "BLE Scanner failed to start. Error: $errorCode Retry: $scannerStartCount")
+ when (errorCode) {
+ SCAN_FAILED_ALREADY_STARTED -> { } // Do nothing
+ SCAN_FAILED_APPLICATION_REGISTRATION_FAILED, SCAN_FAILED_INTERNAL_ERROR -> {
+ handler.postDelayed({ this@BleCentralManager.startScanningInternally() },
+ RETRY_INTERVAL_MS.toLong())
+ }
+ else -> { } // Ignore other codes
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/service/src/com/android/car/trust/BleMessageStream.kt b/service/src/com/android/car/trust/BleMessageStream.kt
index 118f25b..0759fb0 100644
--- a/service/src/com/android/car/trust/BleMessageStream.kt
+++ b/service/src/com/android/car/trust/BleMessageStream.kt
@@ -18,7 +18,6 @@
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothGattCharacteristic
-import android.bluetooth.BluetoothGattServer
import com.android.car.BLEStreamProtos.BLEOperationProto.OperationType
/**
@@ -32,12 +31,12 @@
/** The [BluetoothDevice] to write and receive messages from. */
val device: BluetoothDevice
- /** The GATT server on the device that holds the read and write characteristics. */
- val gattServer: BluetoothGattServer
-
/** The characteristic on the device to write messages to. */
val writeCharacteristic: BluetoothGattCharacteristic
+ /** The characteristic that messages will be written to by the remote device. */
+ val readCharacteristic: BluetoothGattCharacteristic
+
/** An optional callback that will be notified of the progress of writes and reads. */
var callback: BleMessageStreamCallback?
@@ -59,19 +58,4 @@
* @param isPayloadEncrypted `true` if the message to send has been encrypted.
*/
fun writeMessage(message: ByteArray, operationType: OperationType, isPayloadEncrypted: Boolean)
-
- /**
- * Processes a message from the client.
- *
- * The client should be the [device] of this stream. The message may represent a partial message
- * from the client. The [callback] of this stream should only be notified when the message
- * is complete.
- *
- * @param message The message to process.
- * @param readCharacteristic The characteristic that the message from written to.
- */
- fun processClientMessage(
- message: ByteArray,
- readCharacteristic: BluetoothGattCharacteristic
- )
}
diff --git a/service/src/com/android/car/trust/BleMessageStreamV1.kt b/service/src/com/android/car/trust/BleMessageStreamV1.kt
index c6c1418..984791a 100644
--- a/service/src/com/android/car/trust/BleMessageStreamV1.kt
+++ b/service/src/com/android/car/trust/BleMessageStreamV1.kt
@@ -18,7 +18,6 @@
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothGattCharacteristic
-import android.bluetooth.BluetoothGattServer
import android.os.Handler
import android.util.Log
import com.android.car.BLEStreamProtos.BLEMessageProto.BLEMessage
@@ -41,9 +40,10 @@
*/
internal class BleMessageStreamV1(
private val handler: Handler,
+ private val blePeripheralManager: BlePeripheralManager,
override val device: BluetoothDevice,
- override val gattServer: BluetoothGattServer,
- override val writeCharacteristic: BluetoothGattCharacteristic
+ override val writeCharacteristic: BluetoothGattCharacteristic,
+ override val readCharacteristic: BluetoothGattCharacteristic
) : BleMessageStream {
// Explicitly using an ArrayDequeue here for performance when used as a queue.
private val messageQueue = ArrayDeque<BLEMessage>()
@@ -54,6 +54,10 @@
override var maxWriteSize = 20
override var callback: BleMessageStreamCallback? = null
+ init {
+ blePeripheralManager.addOnCharacteristicWriteListener(::onCharacteristicWrite)
+ }
+
/**
* Writes the given message to the `writeCharacteristic` of this stream.
*
@@ -98,19 +102,34 @@
/**
* Processes a message from the client and notifies the [callback] of the success of this
* call.
- *
- * @param message The message to process.
- * @param readCharacteristic The characteristic that the message from written to.
*/
- override fun processClientMessage(
- message: ByteArray,
- readCharacteristic: BluetoothGattCharacteristic
+ @VisibleForTesting
+ fun onCharacteristicWrite(
+ device: BluetoothDevice,
+ characteristic: BluetoothGattCharacteristic,
+ value: ByteArray
) {
+ if (this.device != device) {
+ Log.w(
+ TAG,
+ "Received a message from a device (${device.address}) that is not the " +
+ "expected device (${device.address}) registered to this stream. Ignoring.")
+ return
+ }
+
+ if (characteristic.uuid != readCharacteristic.uuid) {
+ Log.w(
+ TAG,
+ "Received a write to a characteristic (${characteristic.uuid}) that is not the " +
+ "expected UUID (${readCharacteristic.uuid}). Ignoring.")
+ return
+ }
+
val bleMessage = try {
- BLEMessage.parseFrom(message)
+ BLEMessage.parseFrom(value)
} catch (e: InvalidProtocolBufferException) {
Log.e(TAG, "Can not parse BLE message from client.", e)
- callback?.onMessageReceivedError(readCharacteristic.uuid)
+ callback?.onMessageReceivedError(characteristic.uuid)
return
}
@@ -123,7 +142,7 @@
payloadStream.write(bleMessage)
} catch (e: IOException) {
Log.e(TAG, "Unable to parse the BLE message's payload from client.", e)
- callback?.onMessageReceivedError(readCharacteristic.uuid)
+ callback?.onMessageReceivedError(characteristic.uuid)
return
}
@@ -133,7 +152,7 @@
return
}
- callback?.onMessageReceived(payloadStream.toByteArray(), readCharacteristic.uuid)
+ callback?.onMessageReceived(payloadStream.toByteArray(), characteristic.uuid)
payloadStream.reset()
}
@@ -180,14 +199,10 @@
private fun writeValueAndNotify(message: ByteArray) {
writeCharacteristic.setValue(message)
- val result = gattServer.notifyCharacteristicChanged(
+ blePeripheralManager.notifyCharacteristicChanged(
device,
writeCharacteristic,
/* confirm= */ false)
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Wrote value on writeCharacteristic. Successful: $result")
- }
}
/**
diff --git a/service/src/com/android/car/trust/BleManager.java b/service/src/com/android/car/trust/BlePeripheralManager.java
similarity index 66%
rename from service/src/com/android/car/trust/BleManager.java
rename to service/src/com/android/car/trust/BlePeripheralManager.java
index 421b667..5dc0f87 100644
--- a/service/src/com/android/car/trust/BleManager.java
+++ b/service/src/com/android/car/trust/BlePeripheralManager.java
@@ -17,6 +17,8 @@
import static android.bluetooth.BluetoothProfile.GATT_SERVER;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
@@ -37,20 +39,20 @@
import android.os.Handler;
import android.util.Log;
-import androidx.annotation.Nullable;
-
import com.android.car.Utils;
+import java.util.HashSet;
+import java.util.Set;
import java.util.UUID;
/**
- * A generic class that manages BLE operations like start/stop advertising, notifying connects/
- * disconnects and reading/writing values to GATT characteristics.
+ * A generic class that manages BLE peripheral operations like start/stop advertising, notifying
+ * connects/disconnects and reading/writing values to GATT characteristics.
*
* TODO(b/123248433) This could move to a separate comms library.
*/
-public abstract class BleManager {
- private static final String TAG = BleManager.class.getSimpleName();
+class BlePeripheralManager {
+ private static final String TAG = BlePeripheralManager.class.getSimpleName();
private static final int BLE_RETRY_LIMIT = 5;
private static final int BLE_RETRY_INTERVAL_MS = 1000;
@@ -70,6 +72,12 @@
private final Handler mHandler = new Handler();
private final Context mContext;
+ private final Set<Callback> mCallbacks = new HashSet<>();
+ private final Set<OnCharacteristicWriteListener> mWriteListeners = new HashSet<>();
+ private final Set<OnCharacteristicReadListener> mReadListeners = new HashSet<>();
+
+ private int mMtuSize = 20;
+
private BluetoothManager mBluetoothManager;
private BluetoothLeAdvertiser mAdvertiser;
private BluetoothGattServer mGattServer;
@@ -78,13 +86,78 @@
private int mGattServerRetryStartCount;
private BluetoothGattService mBluetoothGattService;
private AdvertiseCallback mAdvertiseCallback;
- private AdvertiseData mData;
+ private AdvertiseData mAdvertiseData;
- BleManager(Context context) {
+
+ BlePeripheralManager(Context context) {
mContext = context;
}
/**
+ * Registers the given callback to be notified of various events within the
+ * {@link BlePeripheralManager}.
+ *
+ * @param callback The callback to be notified.
+ */
+ void registerCallback(@NonNull Callback callback) {
+ mCallbacks.add(callback);
+ }
+
+ /**
+ * Unregisters a previously registered callback.
+ *
+ * @param callback The callback to unregister.
+ */
+ void unregisterCallback(@NonNull Callback callback) {
+ mCallbacks.remove(callback);
+ }
+
+ /**
+ * Adds a listener to be notified of a write to characteristics.
+ *
+ * @param listener The listener to notify.
+ */
+ void addOnCharacteristicWriteListener(@NonNull OnCharacteristicWriteListener listener) {
+ mWriteListeners.add(listener);
+ }
+
+ /**
+ * Removes the given listener from being notified of characteristic writes.
+ *
+ * @param listener The listener to remove.
+ */
+ void removeOnCharacteristicWriteListener(@NonNull OnCharacteristicWriteListener listener) {
+ mWriteListeners.remove(listener);
+ }
+
+ /**
+ * Adds a listener to be notified of reads to characteristics.
+ *
+ * @param listener The listener to notify.
+ */
+ void addOnCharacteristicReadListener(@NonNull OnCharacteristicReadListener listener) {
+ mReadListeners.add(listener);
+ }
+
+ /**
+ * Removes the given listener from being notified of characteristic reads.
+ *
+ * @param listener The listener to remove.
+ */
+ void removeOnCharacteristicReadistener(@NonNull OnCharacteristicReadListener listener) {
+ mReadListeners.remove(listener);
+ }
+
+ /**
+ * Returns the current MTU size.
+ *
+ * @return The size of the MTU in bytes.
+ */
+ int getMtuSize() {
+ return mMtuSize;
+ }
+
+ /**
* Starts the GATT server with the given {@link BluetoothGattService} and begins
* advertising.
*
@@ -95,75 +168,32 @@
* @param data {@link AdvertiseData} data to advertise
* @param advertiseCallback {@link AdvertiseCallback} callback for advertiser
*/
- protected void startAdvertising(BluetoothGattService service, AdvertiseData data,
+ void startAdvertising(BluetoothGattService service, AdvertiseData data,
AdvertiseCallback advertiseCallback) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "startAdvertising: " + service.getUuid().toString());
}
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
- Log.e(TAG, "System does not support BLE");
+ Log.e(TAG, "Attempted start advertising, but system does not support BLE. "
+ + "Ignoring");
return;
}
mBluetoothGattService = service;
mAdvertiseCallback = advertiseCallback;
- mData = data;
+ mAdvertiseData = data;
mGattServerRetryStartCount = 0;
mBluetoothManager = (BluetoothManager) mContext.getSystemService(
- Context.BLUETOOTH_SERVICE);
+ Context.BLUETOOTH_SERVICE);
openGattServer();
}
- private void openGattServer() {
- // Only open one Gatt server.
- if (mGattServer != null) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Gatt Server created, retry count: " + mGattServerRetryStartCount);
- }
- mGattServer.clearServices();
- mGattServer.addService(mBluetoothGattService);
- AdvertiseSettings settings = new AdvertiseSettings.Builder()
- .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
- .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
- .setConnectable(true)
- .build();
- mAdvertiserStartCount = 0;
- startAdvertisingInternally(settings, mData, mAdvertiseCallback);
- mGattServerRetryStartCount = 0;
- } else if (mGattServerRetryStartCount < GATT_SERVER_RETRY_LIMIT) {
- mGattServer = mBluetoothManager.openGattServer(mContext, mGattServerCallback);
- mGattServerRetryStartCount++;
- mHandler.postDelayed(() -> openGattServer(), GATT_SERVER_RETRY_DELAY_MS);
- } else {
- Log.e(TAG, "Gatt server not created - exceeded retry limit.");
- }
- }
-
- private void startAdvertisingInternally(AdvertiseSettings settings, AdvertiseData data,
- AdvertiseCallback advertiseCallback) {
- if (BluetoothAdapter.getDefaultAdapter() != null) {
- mAdvertiser = BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();
- }
-
- if (mAdvertiser != null) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Advertiser created, retry count: " + mAdvertiserStartCount);
- }
- mAdvertiser.startAdvertising(settings, data, advertiseCallback);
- mAdvertiserStartCount = 0;
- } else if (mAdvertiserStartCount < BLE_RETRY_LIMIT) {
- mHandler.postDelayed(
- () -> startAdvertisingInternally(settings, data, advertiseCallback),
- BLE_RETRY_INTERVAL_MS);
- mAdvertiserStartCount += 1;
- } else {
- Log.e(TAG, "Cannot start BLE Advertisement. BT Adapter: "
- + BluetoothAdapter.getDefaultAdapter() + " Advertise Retry count: "
- + mAdvertiserStartCount);
- }
- }
-
- protected void stopAdvertising(AdvertiseCallback advertiseCallback) {
+ /**
+ * Stops the GATT server from advertising.
+ *
+ * @param advertiseCallback The callback that is associated with the advertisement.
+ */
+ void stopAdvertising(AdvertiseCallback advertiseCallback) {
if (mAdvertiser != null) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "stopAdvertising: ");
@@ -175,8 +205,8 @@
/**
* Notifies the characteristic change via {@link BluetoothGattServer}
*/
- protected void notifyCharacteristicChanged(BluetoothDevice device,
- BluetoothGattCharacteristic characteristic, boolean confirm) {
+ void notifyCharacteristicChanged(@NonNull BluetoothDevice device,
+ @NonNull BluetoothGattCharacteristic characteristic, boolean confirm) {
if (mGattServer == null) {
return;
}
@@ -191,16 +221,17 @@
/**
* Connect the Gatt server of the remote device to retrieve device name.
*/
- protected final void retrieveDeviceName(BluetoothDevice device) {
- mBluetoothGatt = device.connectGatt(getContext(), false, mGattCallback);
+ final void retrieveDeviceName(BluetoothDevice device) {
+ mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback);
}
- protected Context getContext() {
- return mContext;
- }
-
+ /**
+ * Returns the currently opened GATT server within this manager.
+ *
+ * @return An opened GATT server or {@code null} if none have been opened.
+ */
@Nullable
- protected BluetoothGattServer getGattServer() {
+ BluetoothGattServer getGattServer() {
return mGattServer;
}
@@ -208,7 +239,7 @@
* Cleans up the BLE GATT server state.
*/
void cleanup() {
- // Stops the advertiser and GATT server. This needs to be done to avoid leaks
+ // Stops the advertiser, scanner and GATT server. This needs to be done to avoid leaks.
if (mAdvertiser != null) {
mAdvertiser.cleanup();
}
@@ -244,60 +275,55 @@
mGattServer = null;
}
- /**
- * Triggered when the name of the remote device is retrieved.
- *
- * @param deviceName Name of the remote device.
- */
- protected void onDeviceNameRetrieved(@Nullable String deviceName) {
+ private void openGattServer() {
+ // Only open one Gatt server.
+ if (mGattServer != null) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Gatt Server created, retry count: " + mGattServerRetryStartCount);
+ }
+ mGattServer.clearServices();
+ mGattServer.addService(mBluetoothGattService);
+ AdvertiseSettings settings = new AdvertiseSettings.Builder()
+ .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
+ .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
+ .setConnectable(true)
+ .build();
+ mAdvertiserStartCount = 0;
+ startAdvertisingInternally(settings, mAdvertiseData, mAdvertiseCallback);
+ mGattServerRetryStartCount = 0;
+ } else if (mGattServerRetryStartCount < GATT_SERVER_RETRY_LIMIT) {
+ mGattServer = mBluetoothManager.openGattServer(mContext, mGattServerCallback);
+ mGattServerRetryStartCount++;
+ mHandler.postDelayed(() -> openGattServer(), GATT_SERVER_RETRY_DELAY_MS);
+ } else {
+ Log.e(TAG, "Gatt server not created - exceeded retry limit.");
+ }
}
- /**
- * Triggered if a remote client has requested to change the MTU for a given connection.
- *
- * @param size The new MTU size.
- */
- protected void onMtuSizeChanged(int size) {
+ private void startAdvertisingInternally(AdvertiseSettings settings, AdvertiseData data,
+ AdvertiseCallback advertiseCallback) {
+ if (BluetoothAdapter.getDefaultAdapter() != null) {
+ mAdvertiser = BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();
+ }
+
+ if (mAdvertiser != null) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Advertiser created, retry count: " + mAdvertiserStartCount);
+ }
+ mAdvertiser.startAdvertising(settings, data, advertiseCallback);
+ mAdvertiserStartCount = 0;
+ } else if (mAdvertiserStartCount < BLE_RETRY_LIMIT) {
+ mHandler.postDelayed(
+ () -> startAdvertisingInternally(settings, data, advertiseCallback),
+ BLE_RETRY_INTERVAL_MS);
+ mAdvertiserStartCount += 1;
+ } else {
+ Log.e(TAG, "Cannot start BLE Advertisement. BT Adapter: "
+ + BluetoothAdapter.getDefaultAdapter() + " Advertise Retry count: "
+ + mAdvertiserStartCount);
+ }
}
- /**
- * Triggered when a device (GATT client) connected.
- *
- * @param device Remote device that connected on BLE.
- */
- protected void onRemoteDeviceConnected(BluetoothDevice device) {
- }
-
- /**
- * Triggered when a device (GATT client) disconnected.
- *
- * @param device Remote device that disconnected on BLE.
- */
- protected void onRemoteDeviceDisconnected(BluetoothDevice device) {
- }
-
- /**
- * Triggered when this BleManager receives a write request from a remote
- * device. Sub-classes should implement how to handle requests.
- * <p>
- *
- * @see BluetoothGattServerCallback#onCharacteristicWriteRequest(BluetoothDevice, int,
- * BluetoothGattCharacteristic, boolean, boolean, int, byte[])
- */
- protected abstract void onCharacteristicWrite(BluetoothDevice device, int requestId,
- BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean
- responseNeeded, int offset, byte[] value);
-
- /**
- * Triggered when this BleManager receives a read request from a remote device.
- * <p>
- *
- * @see BluetoothGattServerCallback#onCharacteristicReadRequest(BluetoothDevice, int, int,
- * BluetoothGattCharacteristic)
- */
- protected abstract void onCharacteristicRead(BluetoothDevice device,
- int requestId, int offset, BluetoothGattCharacteristic characteristic);
-
private final BluetoothGattServerCallback mGattServerCallback =
new BluetoothGattServerCallback() {
@Override
@@ -308,10 +334,14 @@
}
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
- onRemoteDeviceConnected(device);
+ for (Callback callback : mCallbacks) {
+ callback.onRemoteDeviceConnected(device);
+ }
break;
case BluetoothProfile.STATE_DISCONNECTED:
- onRemoteDeviceDisconnected(device);
+ for (Callback callback : mCallbacks) {
+ callback.onRemoteDeviceDisconnected(device);
+ }
break;
default:
Log.w(TAG,
@@ -337,7 +367,10 @@
mGattServer.sendResponse(device, requestId,
BluetoothGatt.GATT_SUCCESS, offset, characteristic.getValue());
- onCharacteristicRead(device, requestId, offset, characteristic);
+
+ for (OnCharacteristicReadListener listener : mReadListeners) {
+ listener.onCharacteristicRead(device, characteristic);
+ }
}
@Override
@@ -351,8 +384,10 @@
mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS,
offset, value);
- onCharacteristicWrite(device, requestId, characteristic,
- preparedWrite, responseNeeded, offset, value);
+
+ for (OnCharacteristicWriteListener listener : mWriteListeners) {
+ listener.onCharacteristicWrite(device, characteristic, value);
+ }
}
@Override
@@ -373,7 +408,12 @@
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "onMtuChanged: " + mtu + " for device " + device.getAddress());
}
- onMtuSizeChanged(mtu);
+
+ mMtuSize = mtu;
+
+ for (Callback callback : mCallbacks) {
+ callback.onMtuSizeChanged(mtu);
+ }
}
};
@@ -433,10 +473,78 @@
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "BLE Device Name: " + deviceName);
}
- onDeviceNameRetrieved(deviceName);
+
+ for (Callback callback : mCallbacks) {
+ callback.onDeviceNameRetrieved(deviceName);
+ }
} else {
Log.e(TAG, "Reading GAP Failed: " + status);
}
}
};
+
+ /**
+ * Interface to be notified of various events within the {@link BlePeripheralManager}.
+ */
+ interface Callback {
+ /**
+ * Triggered when the name of the remote device is retrieved.
+ *
+ * @param deviceName Name of the remote device.
+ */
+ void onDeviceNameRetrieved(@Nullable String deviceName);
+
+ /**
+ * Triggered if a remote client has requested to change the MTU for a given connection.
+ *
+ * @param size The new MTU size.
+ */
+ void onMtuSizeChanged(int size);
+
+ /**
+ * Triggered when a device (GATT client) connected.
+ *
+ * @param device Remote device that connected on BLE.
+ */
+ void onRemoteDeviceConnected(@NonNull BluetoothDevice device);
+
+ /**
+ * Triggered when a device (GATT client) disconnected.
+ *
+ * @param device Remote device that disconnected on BLE.
+ */
+ void onRemoteDeviceDisconnected(@NonNull BluetoothDevice device);
+ }
+
+ /**
+ * An interface for classes that wish to be notified of writes to a characteristic.
+ */
+ interface OnCharacteristicWriteListener {
+ /**
+ * Triggered when this BlePeripheralManager receives a write request from a remote device.
+ *
+ * @param device The bluetooth device that holds the characteristic.
+ * @param characteristic The characteristic that was written to.
+ * @param value The value that was written.
+ */
+ void onCharacteristicWrite(
+ @NonNull BluetoothDevice device,
+ @NonNull BluetoothGattCharacteristic characteristic,
+ @NonNull byte[] value);
+ }
+
+ /**
+ * An interface for classes that wish to be notified of reads on a characteristic.
+ */
+ interface OnCharacteristicReadListener {
+ /**
+ * Triggered when this BlePeripheralManager receives a read request from a remote device.
+ *
+ * @param device The bluetooth device that holds the characteristic.
+ * @param characteristic The characteristic that was read from.
+ */
+ void onCharacteristicRead(
+ @NonNull BluetoothDevice device,
+ @NonNull BluetoothGattCharacteristic characteristic);
+ }
}
diff --git a/service/src/com/android/car/trust/CarBleCentralManager.kt b/service/src/com/android/car/trust/CarBleCentralManager.kt
new file mode 100644
index 0000000..7571a5d
--- /dev/null
+++ b/service/src/com/android/car/trust/CarBleCentralManager.kt
@@ -0,0 +1,511 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.car.trust
+
+import android.bluetooth.BluetoothDevice
+import android.bluetooth.BluetoothGatt
+import android.bluetooth.BluetoothGattCallback
+import android.bluetooth.BluetoothGattCharacteristic
+import android.bluetooth.BluetoothGattDescriptor
+import android.bluetooth.BluetoothProfile
+import android.bluetooth.le.ScanCallback
+import android.bluetooth.le.ScanResult
+import android.bluetooth.le.ScanSettings
+import android.content.Context
+import android.os.ParcelUuid
+import android.util.Log
+
+import com.android.car.Utils
+import com.android.car.guard
+import com.android.internal.annotations.GuardedBy
+
+import java.math.BigInteger
+import java.util.UUID
+
+import kotlin.concurrent.thread
+
+private const val TAG = "CarBleManager"
+
+// system/bt/internal_include/bt_target.h#GATT_MAX_PHY_CHANNEL
+private const val MAX_CONNECTIONS = 7
+
+private val CHARACTERISTIC_CONFIG = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
+
+/**
+ * Communication manager for a car that maintains continuous connections with all phones in the car
+ * for the duration of a drive.
+ *
+ * @param context Application's [Context].
+ * @param serviceUuid [UUID] of peripheral's service.
+ * @param bgServiceMask iOS overflow bit mask for service UUID.
+ * @param writeCharacteristicUuid [UUID] of characteristic the central will write to.
+ * @param readCharacteristicUuid [UUID] of characteristic the peripheral will write to.
+ */
+internal class CarBleCentralManager(
+ private val context: Context,
+ private val bleCentralManager: BleCentralManager,
+ private val serviceUuid: UUID,
+ private val bgServiceMask: String,
+ private val writeCharacteristicUuid: UUID,
+ private val readCharacteristicUuid: UUID
+) {
+ @GuardedBy("connectedDevices")
+ private val connectedDevices = mutableSetOf<BleDevice>()
+
+ @GuardedBy("ignoredDevices")
+ private val ignoredDevices = mutableSetOf<BleDevice>()
+
+ @GuardedBy("callbacks")
+ private val callbacks = mutableListOf<Callback>()
+
+ private val parsedBgServiceBitMask by lazy {
+ BigInteger(bgServiceMask, 16)
+ }
+
+ private val scanSettings by lazy {
+ ScanSettings.Builder()
+ .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
+ .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
+ .setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
+ .build()
+ }
+
+ /**
+ * Start process of finding and connecting to devices.
+ */
+ fun start() {
+ startScanning()
+ }
+
+ private fun startScanning() {
+ bleCentralManager.startScanning(null, scanSettings, scanCallback)
+ }
+
+ /**
+ * Stop process and disconnect from any connected devices.
+ */
+ fun stop() {
+ bleCentralManager.stopScanning()
+ synchronized(connectedDevices) {
+ connectedDevices.forEach { it.gatt.close() }
+ connectedDevices.clear()
+ }
+ synchronized(callbacks) {
+ callbacks.clear()
+ }
+ }
+
+ /**
+ * Send a message to a connected device.
+ *
+ * @param deviceId Id of connected device.
+ * @param message [ByteArray] Message to send.
+ * @param isEncrypted Whether data should be encrypted prior to sending.
+ */
+ fun sendMessage(deviceId: String, message: ByteArray, isEncrypted: Boolean) {
+ getConnectedDevice(deviceId)?.also {
+ sendMessage(it, message, isEncrypted)
+ } ?: Log.w(TAG, "Attempted to send messsage to unknown device $deviceId. Ignored")
+ }
+
+ private fun sendMessage(bleDevice: BleDevice, message: ByteArray, isEncrypted: Boolean) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Writing ${message.size} bytes to " +
+ "${bleDevice.deviceId ?: "Unidentified device"}.")
+ }
+
+ if (isEncrypted) {
+ sendEncryptedMessage(bleDevice, message)
+ } else {
+ sendUnencryptedMessage(bleDevice, message)
+ }
+ }
+
+ private fun sendUnencryptedMessage(bleDevice: BleDevice, message: ByteArray) {
+ // TODO (b/139066995) Replace with unsecure channel implementation
+ bleDevice.writeCharacteristic?.also {
+ it.value = message
+ if (!bleDevice.gatt.writeCharacteristic(it)) {
+ Log.e(TAG, "Write to ${it.uuid} failed.")
+ }
+ }
+ }
+
+ private fun sendEncryptedMessage(bleDevice: BleDevice, message: ByteArray) {
+ // TODO (b/139066995) Implement secure ble channel
+ }
+
+ private fun getConnectedDevice(gatt: BluetoothGatt): BleDevice? {
+ synchronized(connectedDevices) {
+ return connectedDevices.firstOrNull { it.gatt == gatt }
+ }
+ }
+
+ private fun getConnectedDevice(device: BluetoothDevice): BleDevice? {
+ synchronized(connectedDevices) {
+ return connectedDevices.firstOrNull { it.device == device }
+ }
+ }
+
+ private fun getConnectedDevice(deviceId: String): BleDevice? {
+ synchronized(connectedDevices) {
+ return connectedDevices.firstOrNull { it.deviceId == deviceId }
+ }
+ }
+
+ private fun addConnectedDevice(bleDevice: BleDevice) {
+ synchronized(connectedDevices) {
+ connectedDevices.add(bleDevice)
+ }
+ }
+
+ private fun countConnectedDevices(): Int {
+ synchronized(connectedDevices) {
+ return connectedDevices.count()
+ }
+ }
+
+ private fun removeConnectedDevice(bleDevice: BleDevice) {
+ synchronized(connectedDevices) {
+ connectedDevices.remove(bleDevice)
+ }
+ }
+
+ private fun ignoreDevice(deviceToIgnore: BleDevice) {
+ synchronized(ignoredDevices) {
+ ignoredDevices.add(deviceToIgnore)
+ }
+ }
+
+ private fun isDeviceIgnored(device: BluetoothDevice): Boolean {
+ synchronized(ignoredDevices) {
+ return ignoredDevices.any { it.device == device }
+ }
+ }
+
+ private val scanCallback by lazy {
+ object : ScanCallback() {
+ override fun onBatchScanResults(results: MutableList<ScanResult>) {
+ // This method should never be called because our scan mode is
+ // SCAN_MODE_LOW_LATENCY, meaning we will be notified of individual matches.
+ }
+
+ override fun onScanFailed(errorCode: Int) {
+ Log.e(TAG, "BLE scanning failed with error code: $errorCode")
+ }
+
+ override fun onScanResult(callbackType: Int, result: ScanResult) {
+ if (shouldAttemptConnection(result)) {
+ startDeviceConnection(result.device)
+ }
+ }
+ }
+ }
+
+ private fun shouldAttemptConnection(result: ScanResult): Boolean {
+ // Ignore any results that are not connectable.
+ if (!result.isConnectable) {
+ return false
+ }
+
+ // Do not attempt to connect if we have already hit our max. This should rarely happen
+ // and is protecting against a race condition of scanning stopped and new results coming in.
+ if (countConnectedDevices() >= MAX_CONNECTIONS) {
+ return false
+ }
+
+ val device = result.device
+
+ // Check if already attempting to connect to this device.
+ if (getConnectedDevice(device) != null) {
+ return false
+ }
+
+ // Connect to any device that is advertising our service UUID.
+ if (result.scanRecord.serviceUuids?.contains(ParcelUuid(serviceUuid)) == true ||
+ result.containsUuidsInOverflow(parsedBgServiceBitMask)) {
+ return true
+ }
+
+ // Do not connect if device has already been ignored.
+ if (isDeviceIgnored(device)) {
+ return false
+ }
+
+ // Can safely ignore devices advertising unrecognized service uuids.
+ if (result.scanRecord.serviceUuids?.isNotEmpty() == true) {
+ return false
+ }
+
+ // TODO (b/139066293) Current implementation quickly exhausts connections resulting in
+ // greatly reduced performance for connecting to devices we know we want to connect to.
+ // Return true once fixed.
+ return false
+ }
+
+ private val connectionCallback by lazy {
+ object : BluetoothGattCallback() {
+ override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
+ if (gatt == null) {
+ Log.w(TAG, "Null gatt passed to onConnectionStateChange. Ignoring.")
+ return
+ }
+ val bleDevice = getConnectedDevice(gatt) ?: return
+ when (newState) {
+ BluetoothProfile.STATE_CONNECTED -> {
+ deviceConnected(bleDevice)
+ }
+ BluetoothProfile.STATE_DISCONNECTED -> {
+ deviceDisconnected(bleDevice, status)
+ }
+ else -> {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Connection state changed: " +
+ BluetoothProfile.getConnectionStateName(newState) +
+ " state: $status")
+ }
+ }
+ }
+ }
+
+ override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
+ if (gatt == null) {
+ Log.w(TAG, "Null gatt passed to onServicesDiscovered. Ignoring.")
+ return
+ }
+ val connectedDevice = getConnectedDevice(gatt) ?: return
+ val service = gatt.getService(serviceUuid) ?: run {
+ ignoreDevice(connectedDevice)
+ gatt.disconnect()
+ return
+ }
+ connectedDevice.state = BleDeviceState.CONNECTED
+ val readCharacteristic = service.getCharacteristic(readCharacteristicUuid)
+ val writeCharacteristic = service.getCharacteristic(
+ writeCharacteristicUuid)
+ if (readCharacteristic == null || writeCharacteristic == null) {
+ Log.w(TAG, "Unable to find expected characteristics on peripheral")
+ gatt.disconnect()
+ return
+ }
+ connectedDevice.readCharacteristic = readCharacteristic
+ connectedDevice.writeCharacteristic = writeCharacteristic
+
+ // Turn on notifications for read characteristic
+ val descriptor = readCharacteristic.getDescriptor(CHARACTERISTIC_CONFIG).apply {
+ value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
+ }
+ if (!gatt.writeDescriptor(descriptor)) {
+ Log.e(TAG, "Write descriptor failed!")
+ gatt.disconnect()
+ return
+ }
+
+ if (!gatt.setCharacteristicNotification(readCharacteristic, true)) {
+ Log.e(TAG, "Set notifications failed!")
+ gatt.disconnect()
+ return
+ }
+
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Service and characteristics successfully discovered")
+ }
+ }
+
+ override fun onDescriptorWrite(
+ gatt: BluetoothGatt?,
+ descriptor: BluetoothGattDescriptor?,
+ status: Int
+ ) {
+ if (gatt == null) {
+ Log.w(TAG, "Null gatt passed to onDescriptorWrite. Ignoring.")
+ return
+ }
+
+ // TODO (b/139067881) Replace with sending unique device id
+ getConnectedDevice(gatt)?.guard {
+ sendMessage(it, Utils.uuidToBytes(UUID.randomUUID()), false)
+ } ?: Log.w(TAG, "Descriptor callback called for disconnected device")
+ }
+
+ override fun onCharacteristicChanged(
+ gatt: BluetoothGatt?,
+ characteristic: BluetoothGattCharacteristic?
+ ) {
+ if (characteristic?.uuid != readCharacteristicUuid) {
+ return
+ }
+ if (gatt == null) {
+ Log.w(TAG, "Null gatt passed to onCharacteristicChanged. Ignoring.")
+ return
+ }
+
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Change detected on characteristic " +
+ "${characteristic.uuid}")
+ }
+
+ val connectedDevice = getConnectedDevice(gatt) ?: return
+ val message = characteristic.value
+
+ connectedDevice.deviceId?.also { deviceId ->
+ notifyCallbacks { it.onMessageReceived(deviceId, message) }
+ } ?: run {
+ // Device id is the first message expected back from peripheral
+ val deviceId = String(message)
+ connectedDevice.deviceId = deviceId
+ notifyCallbacks { it.onDeviceConnected(deviceId) }
+ }
+ }
+
+ override fun onCharacteristicWrite(
+ gatt: BluetoothGatt?,
+ characteristic: BluetoothGattCharacteristic?,
+ status: Int
+ ) {
+ }
+ }
+ }
+
+ private fun startDeviceConnection(device: BluetoothDevice) {
+ val gatt = device.connectGatt(context, false, connectionCallback,
+ BluetoothDevice.TRANSPORT_LE) ?: return
+ addConnectedDevice(BleDevice(device, gatt).apply { this.state = BleDeviceState.CONNECTING })
+
+ // Stop scanning if we have reached the maximum connections
+ if (countConnectedDevices() >= MAX_CONNECTIONS) {
+ bleCentralManager.stopScanning()
+ }
+ }
+
+ private fun deviceConnected(device: BleDevice) {
+ device.state = BleDeviceState.PENDING_VERIFICATION
+
+ device.gatt.discoverServices()
+
+ val connectedCount = countConnectedDevices()
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "New device connected: ${device.gatt.device?.address}. " +
+ "Active connections: $connectedCount")
+ }
+ }
+
+ private fun deviceDisconnected(device: BleDevice, status: Int) {
+ removeConnectedDevice(device)
+ device.gatt.close()
+ device.deviceId?.guard { deviceId ->
+ notifyCallbacks { it.onDeviceDisconnected(deviceId) }
+ }
+ val connectedCount = countConnectedDevices()
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Device disconnected: ${device.gatt.device?.address} with " +
+ "state $status. Active connections: $connectedCount")
+ }
+
+ // Start scanning if dropping down from max
+ if (!bleCentralManager.isScanning() && connectedCount < MAX_CONNECTIONS) {
+ startScanning()
+ }
+ }
+
+ /**
+ * Register a callback
+ *
+ * @param callback The [Callback] to register.
+ */
+ fun registerCallback(callback: Callback) {
+ synchronized(callbacks) {
+ callbacks.add(callback)
+ }
+ }
+
+ /**
+ * Unregister a callback
+ *
+ * @param callback The [Callback] to unregister.
+ */
+ fun unregisterCallback(callback: Callback) {
+ synchronized(callbacks) {
+ callbacks.remove(callback)
+ }
+ }
+
+ /**
+ * Trigger notification on registered callbacks.
+ *
+ * @param notification [Callback] notification function.
+ */
+ private fun notifyCallbacks(notification: (Callback) -> Unit) {
+ val callbacksCopy = synchronized(callbacks) { callbacks.toList() }
+ callbacksCopy.forEach {
+ thread(isDaemon = true) { notification(it) }
+ }
+ }
+
+ /**
+ * Callback for triggered events from [CarBleManager]
+ */
+ interface Callback {
+
+ /**
+ * Triggered when device is connected and device id retrieved. Device is now ready to
+ * receive messages.
+ *
+ * @param deviceId Id of device that has connected.
+ */
+ fun onDeviceConnected(deviceId: String)
+
+ /**
+ * Triggered when device is disconnected.
+ *
+ * @param deviceId Id of device that has disconnected.
+ */
+ fun onDeviceDisconnected(deviceId: String)
+
+ /**
+ * Triggered when device has established encryption for secure communication.
+ *
+ * @param deviceId Id of device that has established encryption.
+ */
+ fun onSecureChannelEstablished(deviceId: String)
+
+ /**
+ * Triggered when a new message is detected.
+ *
+ * @param deviceId Id of the device that sent the message.
+ * @param message [ByteArray] Data from message.
+ */
+ fun onMessageReceived(deviceId: String, message: ByteArray)
+ }
+
+ private data class BleDevice(
+ val device: BluetoothDevice,
+ val gatt: BluetoothGatt
+ ) {
+ var state: BleDeviceState = BleDeviceState.UNKNOWN
+ var deviceId: String? = null
+ var writeCharacteristic: BluetoothGattCharacteristic? = null
+ var readCharacteristic: BluetoothGattCharacteristic? = null
+ }
+
+ private enum class BleDeviceState {
+ CONNECTING,
+ PENDING_VERIFICATION,
+ CONNECTED,
+ UNKNOWN
+ }
+}
diff --git a/service/src/com/android/car/trust/CarBleTrustAgent.java b/service/src/com/android/car/trust/CarBleTrustAgent.java
index d3790ff..5760b54 100644
--- a/service/src/com/android/car/trust/CarBleTrustAgent.java
+++ b/service/src/com/android/car/trust/CarBleTrustAgent.java
@@ -234,7 +234,7 @@
private void onBluetoothStateChanged(int state) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "onBluetoothStateChanged: " + state);
+ Log.d(TAG, "onBluetoothStateChanged: " + BluetoothAdapter.nameForState(state));
}
if (!mIsDeviceLocked) {
return;
diff --git a/service/src/com/android/car/trust/CarTrustAgentBleManager.java b/service/src/com/android/car/trust/CarTrustAgentBleManager.java
index 19c13c1..a9061d1 100644
--- a/service/src/com/android/car/trust/CarTrustAgentBleManager.java
+++ b/service/src/com/android/car/trust/CarTrustAgentBleManager.java
@@ -17,6 +17,7 @@
package com.android.car.trust;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGattCharacteristic;
@@ -26,10 +27,10 @@
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
import android.content.Context;
+import android.os.Handler;
import android.os.ParcelUuid;
import android.util.Log;
-import androidx.annotation.Nullable;
import androidx.collection.SimpleArrayMap;
import com.android.car.BLEStreamProtos.BLEOperationProto.OperationType;
@@ -48,11 +49,12 @@
/**
* A BLE Service that is used for communicating with the trusted peer device. This extends from a
- * more generic {@link BleManager} and has more context on the BLE requirements for the Trusted
- * device feature. It has knowledge on the GATT services and characteristics that are specific to
- * the Trusted Device feature.
+ * more generic {@link BlePeripheralManager} and has more context on the BLE requirements for the
+ * Trusted device feature. It has knowledge on the GATT services and characteristics that are
+ * specific to the Trusted Device feature.
*/
-class CarTrustAgentBleManager extends BleManager implements BleMessageStreamCallback {
+class CarTrustAgentBleManager implements BleMessageStreamCallback, BlePeripheralManager.Callback,
+ BlePeripheralManager.OnCharacteristicWriteListener {
private static final String TAG = "CarTrustBLEManager";
/**
@@ -90,6 +92,9 @@
@VisibleForTesting
static final long BLE_MESSAGE_RETRY_DELAY_MS = TimeUnit.SECONDS.toMillis(2);
+ private final Context mContext;
+ private final BlePeripheralManager mBlePeripheralManager;
+
@TrustedDeviceOperation
private int mCurrentTrustedDeviceOperation = TRUSTED_DEVICE_OPERATION_NONE;
private String mOriginalBluetoothName;
@@ -124,14 +129,18 @@
private UUID mUnlockServerWriteUuid;
private BluetoothGattService mUnlockGattService;
+ @Nullable
private BleMessageStream mMessageStream;
+ private final Handler mHandler = new Handler();
// A map of enrollment/unlock client write uuid -> listener
private final SimpleArrayMap<UUID, DataReceivedListener> mDataReceivedListeners =
new SimpleArrayMap<>();
- CarTrustAgentBleManager(Context context) {
- super(context);
+ CarTrustAgentBleManager(Context context, BlePeripheralManager blePeripheralManager) {
+ mContext = context;
+ mBlePeripheralManager = blePeripheralManager;
+ mBlePeripheralManager.registerCallback(this);
}
/**
@@ -141,6 +150,14 @@
mUniqueId = Utils.uuidToBytes(uniqueId);
}
+ void cleanup() {
+ mBlePeripheralManager.cleanup();
+ }
+
+ void stopGattServer() {
+ mBlePeripheralManager.stopGattServer();
+ }
+
// Overriding some of the {@link BLEManager} methods to be specific for Trusted Device feature.
@Override
public void onRemoteDeviceConnected(BluetoothDevice device) {
@@ -153,7 +170,7 @@
// stored in sharedPreference for further use.
if (mCurrentTrustedDeviceOperation == TRUSTED_DEVICE_OPERATION_ENROLLMENT
&& device.getName() == null) {
- retrieveDeviceName(device);
+ mBlePeripheralManager.retrieveDeviceName(device);
}
if (mMessageStream != null) {
@@ -163,12 +180,14 @@
mSendMessageCallback = null;
+ mBlePeripheralManager.addOnCharacteristicWriteListener(this);
mBleEventCallbacks.forEach(bleEventCallback ->
bleEventCallback.onRemoteDeviceConnected(device));
}
@Override
public void onRemoteDeviceDisconnected(BluetoothDevice device) {
+ mBlePeripheralManager.removeOnCharacteristicWriteListener(this);
mBleEventCallbacks.forEach(bleEventCallback ->
bleEventCallback.onRemoteDeviceDisconnected(device));
@@ -181,13 +200,13 @@
}
@Override
- protected void onDeviceNameRetrieved(@Nullable String deviceName) {
+ public void onDeviceNameRetrieved(@Nullable String deviceName) {
mBleEventCallbacks.forEach(bleEventCallback ->
bleEventCallback.onClientDeviceNameRetrieved(deviceName));
}
@Override
- protected void onMtuSizeChanged(int size) {
+ public void onMtuSizeChanged(int size) {
mMaxWriteSize = size - ATT_PAYLOAD_RESERVED_BYTES;
if (mMessageStream != null) {
@@ -201,9 +220,8 @@
}
@Override
- public void onCharacteristicWrite(BluetoothDevice device, int requestId,
- BluetoothGattCharacteristic characteristic, boolean preparedWrite,
- boolean responseNeeded, int offset, byte[] value) {
+ public void onCharacteristicWrite(BluetoothDevice device,
+ BluetoothGattCharacteristic characteristic, byte[] value) {
UUID uuid = characteristic.getUuid();
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "onCharacteristicWrite received uuid: " + uuid);
@@ -214,26 +232,8 @@
return;
}
- // Retrieve the read characteristic that corresponds to the characteristic that was just
- // written to.
- BluetoothGattCharacteristic readCharacteristic = uuid.equals(mEnrollmentClientWriteUuid)
- ? mEnrollmentGattService.getCharacteristic(uuid)
- : mUnlockGattService.getCharacteristic(uuid);
-
- // If this occurs, then there is a bug in the retrieval code above.
- if (readCharacteristic == null) {
- Log.e(TAG, "No characteristic corresponding to UUID (" + uuid + ") "
- + "that was written to. So message cannot be processed.");
- return;
- }
-
- mMessageStream.processClientMessage(value, readCharacteristic);
- }
-
- @Override
- public void onCharacteristicRead(BluetoothDevice device, int requestId, int offset,
- final BluetoothGattCharacteristic characteristic) {
- // Ignored read requests.
+ Log.e(TAG, "Received a message but message stream has already been created. "
+ + "Was this manager not unregistered as a listener for writes?");
}
@VisibleForTesting
@@ -247,12 +247,25 @@
getCharacteristicForWrite(clientCharacteristicUUID);
if (writeCharacteristic == null) {
- Log.e(TAG, "Invalid UUID (" + clientCharacteristicUUID
+ Log.e(TAG, "Invalid write UUID (" + clientCharacteristicUUID
+ ") during version exchange; disconnecting from remote device.");
disconnectRemoteDevice();
return;
}
+ BluetoothGattCharacteristic readCharacteristic =
+ clientCharacteristicUUID.equals(mEnrollmentClientWriteUuid)
+ ? mEnrollmentGattService.getCharacteristic(clientCharacteristicUUID)
+ : mUnlockGattService.getCharacteristic(clientCharacteristicUUID);
+
+ // If this occurs, then there is a bug in the retrieval code above.
+ if (readCharacteristic == null) {
+ Log.e(TAG, "No read characteristic corresponding to UUID ("
+ + clientCharacteristicUUID + "). Cannot listen for messages. Disconnecting.");
+ disconnectRemoteDevice();
+ return;
+ }
+
BLEVersionExchange deviceVersion;
try {
deviceVersion = BLEVersionExchange.parseFrom(value);
@@ -263,7 +276,8 @@
}
mMessageStream = BLEVersionExchangeResolver.resolveToStream(
- deviceVersion, device, getGattServer(), writeCharacteristic);
+ deviceVersion, device, mBlePeripheralManager, writeCharacteristic,
+ readCharacteristic);
mMessageStream.setMaxWriteSize(mMaxWriteSize);
mMessageStream.setCallback(this);
@@ -274,6 +288,10 @@
return;
}
+ // No need for this manager to listen for any writes; the stream will handle that from now
+ // on.
+ mBlePeripheralManager.removeOnCharacteristicWriteListener(this);
+
// The message stream is not used to send the IHU's version, but will be used for
// any subsequent messages.
BLEVersionExchange headunitVersion = BLEVersionExchangeResolver.makeVersionExchange();
@@ -292,11 +310,11 @@
*/
void setupEnrollmentBleServer() {
mEnrollmentServiceUuid = UUID.fromString(
- getContext().getString(R.string.enrollment_service_uuid));
+ mContext.getString(R.string.enrollment_service_uuid));
mEnrollmentClientWriteUuid = UUID.fromString(
- getContext().getString(R.string.enrollment_client_write_uuid));
+ mContext.getString(R.string.enrollment_client_write_uuid));
mEnrollmentServerWriteUuid = UUID.fromString(
- getContext().getString(R.string.enrollment_server_write_uuid));
+ mContext.getString(R.string.enrollment_server_write_uuid));
mEnrollmentGattService = new BluetoothGattService(mEnrollmentServiceUuid,
BluetoothGattService.SERVICE_TYPE_PRIMARY);
@@ -326,11 +344,11 @@
* from the phone to the head unit.
*/
void setupUnlockBleServer() {
- mUnlockServiceUuid = UUID.fromString(getContext().getString(R.string.unlock_service_uuid));
+ mUnlockServiceUuid = UUID.fromString(mContext.getString(R.string.unlock_service_uuid));
mUnlockClientWriteUuid = UUID
- .fromString(getContext().getString(R.string.unlock_client_write_uuid));
+ .fromString(mContext.getString(R.string.unlock_client_write_uuid));
mUnlockServerWriteUuid = UUID
- .fromString(getContext().getString(R.string.unlock_server_write_uuid));
+ .fromString(mContext.getString(R.string.unlock_server_write_uuid));
mUnlockGattService = new BluetoothGattService(mUnlockServiceUuid,
BluetoothGattService.SERVICE_TYPE_PRIMARY);
@@ -410,7 +428,23 @@
+ mOriginalBluetoothName + " to " + deviceName);
}
}
- startAdvertising(mEnrollmentGattService,
+
+ attemptAdvertising();
+ }
+
+ private void attemptAdvertising() {
+ // Validate the adapter name change has happened. If not, try again after delay.
+ if (mOriginalBluetoothName != null
+ && BluetoothAdapter.getDefaultAdapter().getName().equals(mOriginalBluetoothName)) {
+ mHandler.postDelayed(this::attemptAdvertising, BLE_MESSAGE_RETRY_DELAY_MS);
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Adapter name change has not taken affect prior to advertising attempt. "
+ + "Trying again.");
+ }
+ return;
+ }
+
+ mBlePeripheralManager.startAdvertising(mEnrollmentGattService,
new AdvertiseData.Builder()
.setIncludeDeviceName(true)
.addServiceUuid(new ParcelUuid(mEnrollmentServiceUuid))
@@ -425,9 +459,10 @@
+ mOriginalBluetoothName);
}
BluetoothAdapter.getDefaultAdapter().setName(mOriginalBluetoothName);
+ mOriginalBluetoothName = null;
}
if (mEnrollmentAdvertisingCallback != null) {
- stopAdvertising(mEnrollmentAdvertisingCallback);
+ mBlePeripheralManager.stopAdvertising(mEnrollmentAdvertisingCallback);
}
}
@@ -437,7 +472,7 @@
return;
}
mCurrentTrustedDeviceOperation = TRUSTED_DEVICE_OPERATION_UNLOCK;
- startAdvertising(mUnlockGattService,
+ mBlePeripheralManager.startAdvertising(mUnlockGattService,
new AdvertiseData.Builder()
.setIncludeDeviceName(false)
.addServiceData(new ParcelUuid(mUnlockServiceUuid), mUniqueId)
@@ -448,11 +483,11 @@
void stopUnlockAdvertising() {
mCurrentTrustedDeviceOperation = TRUSTED_DEVICE_OPERATION_NONE;
- stopAdvertising(mUnlockAdvertisingCallback);
+ mBlePeripheralManager.stopAdvertising(mUnlockAdvertisingCallback);
}
void disconnectRemoteDevice() {
- stopGattServer();
+ mBlePeripheralManager.stopGattServer();
}
void sendMessage(byte[] message, OperationType operation, boolean isPayloadEncrypted,
@@ -480,7 +515,7 @@
private void setValueOnCharacteristicAndNotify(BluetoothDevice device, byte[] message,
BluetoothGattCharacteristic characteristic) {
characteristic.setValue(message);
- notifyCharacteristicChanged(device, characteristic, false);
+ mBlePeripheralManager.notifyCharacteristicChanged(device, characteristic, false);
}
/**
diff --git a/service/src/com/android/car/trust/CarTrustAgentUnlockService.java b/service/src/com/android/car/trust/CarTrustAgentUnlockService.java
index 1b51368..7104c69 100644
--- a/service/src/com/android/car/trust/CarTrustAgentUnlockService.java
+++ b/service/src/com/android/car/trust/CarTrustAgentUnlockService.java
@@ -47,22 +47,14 @@
import com.android.car.trust.CarTrustAgentBleManager.SendMessageCallback;
import com.android.internal.annotations.GuardedBy;
-import com.google.security.cryptauth.lib.securegcm.D2DConnectionContext;
-import com.google.security.cryptauth.lib.securemessage.CryptoOps;
-
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.security.InvalidKeyException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.util.LinkedList;
import java.util.Queue;
import java.util.UUID;
-import javax.crypto.spec.SecretKeySpec;
-
/**
* A service that interacts with the Trust Agent {@link CarBleTrustAgent} and a comms (BLE) service
* {@link CarTrustAgentBleManager} to receive the necessary credentials to authenticate
@@ -102,10 +94,6 @@
// Arbitrary log size
private static final int MAX_LOG_SIZE = 20;
- private static final byte[] RESUME = "RESUME".getBytes();
- private static final byte[] SERVER = "SERVER".getBytes();
- private static final byte[] CLIENT = "CLIENT".getBytes();
- private static final int RESUME_HMAC_LENGTH = 32;
private static final byte[] ACKNOWLEDGEMENT_MESSAGE = "ACK".getBytes();
@@ -113,15 +101,14 @@
// State increments to the next state on successful completion.
private static final int UNLOCK_STATE_WAITING_FOR_UNIQUE_ID = 0;
private static final int UNLOCK_STATE_KEY_EXCHANGE_IN_PROGRESS = 1;
- private static final int UNLOCK_STATE_WAITING_FOR_CLIENT_AUTH = 2;
- private static final int UNLOCK_STATE_MUTUAL_AUTH_ESTABLISHED = 3;
- private static final int UNLOCK_STATE_PHONE_CREDENTIALS_RECEIVED = 4;
+ private static final int UNLOCK_STATE_MUTUAL_AUTH_ESTABLISHED = 2;
+ private static final int UNLOCK_STATE_PHONE_CREDENTIALS_RECEIVED = 3;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = {"UNLOCK_STATE_"}, value = {UNLOCK_STATE_WAITING_FOR_UNIQUE_ID,
- UNLOCK_STATE_KEY_EXCHANGE_IN_PROGRESS, UNLOCK_STATE_WAITING_FOR_CLIENT_AUTH,
- UNLOCK_STATE_MUTUAL_AUTH_ESTABLISHED, UNLOCK_STATE_PHONE_CREDENTIALS_RECEIVED})
+ @IntDef(prefix = {"UNLOCK_STATE_"},
+ value = {UNLOCK_STATE_WAITING_FOR_UNIQUE_ID, UNLOCK_STATE_KEY_EXCHANGE_IN_PROGRESS,
+ UNLOCK_STATE_MUTUAL_AUTH_ESTABLISHED, UNLOCK_STATE_PHONE_CREDENTIALS_RECEIVED})
@interface UnlockState {
}
@@ -143,20 +130,17 @@
private BluetoothDevice mRemoteUnlockDevice;
private EncryptionRunner mEncryptionRunner = EncryptionRunnerFactory.newRunner();
- private HandshakeMessage mHandshakeMessage;
private Key mEncryptionKey;
@HandshakeMessage.HandshakeState
private int mEncryptionState = HandshakeMessage.HandshakeState.UNKNOWN;
- private D2DConnectionContext mPrevContext;
- private D2DConnectionContext mCurrentContext;
-
CarTrustAgentUnlockService(Context context, CarTrustedDeviceService service,
CarTrustAgentBleManager bleService) {
mTrustedDeviceService = service;
mCarTrustAgentBleManager = bleService;
mUnlockClientWriteUuid = UUID.fromString(context
.getString(R.string.unlock_client_write_uuid));
+ mEncryptionRunner.setIsReconnect(true);
mSendMessageCallback = () -> mCarTrustAgentBleManager.disconnectRemoteDevice();
}
@@ -242,8 +226,6 @@
synchronized (mDeviceLock) {
mRemoteUnlockDevice = null;
}
- mPrevContext = null;
- mCurrentContext = null;
}
void onRemoteDeviceConnected(BluetoothDevice device) {
@@ -302,21 +284,6 @@
resetUnlockStateOnFailure();
}
break;
- case UNLOCK_STATE_WAITING_FOR_CLIENT_AUTH:
- if (!authenticateClient(value)) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "HMAC from the phone is not correct. Cannot resume session. Need"
- + " to re-enroll");
- }
- mTrustedDeviceService.clearEncryptionKey(mClientDeviceId);
- resetUnlockStateOnFailure();
- return;
- }
-
- logUnlockEvent(CLIENT_AUTHENTICATED);
- sendServerAuthToClient();
- mCurrentUnlockState = UNLOCK_STATE_MUTUAL_AUTH_ESTABLISHED;
- break;
case UNLOCK_STATE_MUTUAL_AUTH_ESTABLISHED:
if (mEncryptionKey == null) {
Log.e(TAG, "Current session key null. Unexpected at this stage: "
@@ -380,16 +347,17 @@
}
private void processKeyExchangeHandshakeMessage(byte[] message) throws HandshakeException {
+ HandshakeMessage handshakeMessage;
switch (mEncryptionState) {
case HandshakeMessage.HandshakeState.UNKNOWN:
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Responding to handshake init request.");
}
- mHandshakeMessage = mEncryptionRunner.respondToInitRequest(message);
- mEncryptionState = mHandshakeMessage.getHandshakeState();
+ handshakeMessage = mEncryptionRunner.respondToInitRequest(message);
+ mEncryptionState = handshakeMessage.getHandshakeState();
mCarTrustAgentBleManager.sendMessage(
- mHandshakeMessage.getNextMessage(),
+ handshakeMessage.getNextMessage(),
OperationType.ENCRYPTION_HANDSHAKE,
/* isPayloadEncrypted= */ false, mSendMessageCallback);
logUnlockEvent(UNLOCK_ENCRYPTION_STATE, mEncryptionState);
@@ -400,128 +368,60 @@
Log.d(TAG, "Continuing handshake.");
}
- mHandshakeMessage = mEncryptionRunner.continueHandshake(message);
- mEncryptionState = mHandshakeMessage.getHandshakeState();
+ handshakeMessage = mEncryptionRunner.continueHandshake(message);
+ mEncryptionState = handshakeMessage.getHandshakeState();
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Updated encryption state: " + mEncryptionState);
- }
+ logUnlockEvent(UNLOCK_ENCRYPTION_STATE, mEncryptionState);
- // The state is updated after a call to continueHandshake(). Thus, need to check
- // if we're in the next stage.
- if (mEncryptionState == HandshakeMessage.HandshakeState.VERIFICATION_NEEDED) {
- logUnlockEvent(UNLOCK_ENCRYPTION_STATE, mEncryptionState);
- showVerificationCode();
+ if (mEncryptionState != HandshakeMessage.HandshakeState.RESUMING_SESSION) {
+ Log.e(TAG,
+ "Handshake did not went to resume session after calling verify PIN. "
+ + "Instead got state: " + mEncryptionState);
+ resetUnlockStateOnFailure();
return;
}
-
- // control shouldn't get here with Ukey2
- mCarTrustAgentBleManager.sendMessage(
- mHandshakeMessage.getNextMessage(),
- OperationType.ENCRYPTION_HANDSHAKE, /*isPayloadEncrypted= */false,
- mSendMessageCallback);
+ logUnlockEvent(WAITING_FOR_CLIENT_AUTH);
+ break;
+ case HandshakeMessage.HandshakeState.RESUMING_SESSION:
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Start reconnection authentication.");
+ }
+ if (mClientDeviceId == null) {
+ resetUnlockStateOnFailure();
+ return;
+ }
+ handshakeMessage = mEncryptionRunner.authenticateReconnection(
+ message, mTrustedDeviceService.getEncryptionKey(mClientDeviceId));
+ mEncryptionKey = handshakeMessage.getKey();
+ mEncryptionState = handshakeMessage.getHandshakeState();
+ logUnlockEvent(UNLOCK_ENCRYPTION_STATE, mEncryptionState);
+ if (mEncryptionState != HandshakeMessage.HandshakeState.FINISHED) {
+ resetUnlockStateOnFailure();
+ return;
+ }
+ mCurrentUnlockState = UNLOCK_STATE_MUTUAL_AUTH_ESTABLISHED;
+ sendServerAuthToClient(handshakeMessage.getNextMessage());
+ logUnlockEvent(CLIENT_AUTHENTICATED);
break;
case HandshakeMessage.HandshakeState.VERIFICATION_NEEDED:
case HandshakeMessage.HandshakeState.FINISHED:
// Should never reach this case since this state should occur after a verification
// code has been accepted. But it should mean handshake is done and the message
- // is one for the escrow token. Start Mutual Auth from server - compute MACs and
- // send it over
- showVerificationCode();
- break;
-
+ // is one for the escrow token. Waiting Mutual Auth from client, authenticate,
+ // compute MACs and send it over
default:
Log.w(TAG, "Encountered invalid handshake state: " + mEncryptionState);
break;
}
}
- /**
- * Verify the handshake.
- * TODO(b/134073741) combine this with the method in CarTrustAgentEnrollmentService and
- * have this take a boolean to blindly confirm the numeric code.
- */
- private void showVerificationCode() {
- HandshakeMessage handshakeMessage;
-
- // Blindly accept the verification code.
- try {
- handshakeMessage = mEncryptionRunner.verifyPin();
- } catch (HandshakeException e) {
- Log.e(TAG, "Verify pin failed for new keys - Unexpected");
- resetUnlockStateOnFailure();
- return;
- }
-
- if (handshakeMessage.getHandshakeState() != HandshakeMessage.HandshakeState.FINISHED) {
- Log.e(TAG, "Handshake not finished after calling verify PIN. Instead got state: "
- + handshakeMessage.getHandshakeState());
- resetUnlockStateOnFailure();
- return;
- }
-
- mEncryptionState = HandshakeMessage.HandshakeState.FINISHED;
- mEncryptionKey = handshakeMessage.getKey();
- mCurrentContext = D2DConnectionContext.fromSavedSession(mEncryptionKey.asBytes());
-
- if (mClientDeviceId == null) {
- resetUnlockStateOnFailure();
- return;
- }
- byte[] oldSessionKeyBytes = mTrustedDeviceService.getEncryptionKey(mClientDeviceId);
- if (oldSessionKeyBytes == null) {
- Log.e(TAG,
- "Could not retrieve previous session keys! Have to re-enroll trusted device");
- resetUnlockStateOnFailure();
- return;
- }
-
- mPrevContext = D2DConnectionContext.fromSavedSession(oldSessionKeyBytes);
- if (mPrevContext == null) {
- resetUnlockStateOnFailure();
- return;
- }
-
- // Now wait for the phone to send its MAC.
- mCurrentUnlockState = UNLOCK_STATE_WAITING_FOR_CLIENT_AUTH;
- logUnlockEvent(WAITING_FOR_CLIENT_AUTH);
- }
-
- private void sendServerAuthToClient() {
- byte[] resumeBytes = computeMAC(mPrevContext, mCurrentContext, SERVER);
- if (resumeBytes == null) {
- return;
- }
+ private void sendServerAuthToClient(byte[] resumeBytes) {
// send to client
mCarTrustAgentBleManager.sendMessage(resumeBytes,
OperationType.CLIENT_MESSAGE, /* isPayloadEncrypted= */false,
mSendMessageCallback);
}
- @Nullable
- private byte[] computeMAC(D2DConnectionContext previous, D2DConnectionContext next,
- byte[] info) {
- try {
- SecretKeySpec inputKeyMaterial = new SecretKeySpec(
- Utils.concatByteArrays(previous.getSessionUnique(), next.getSessionUnique()),
- "" /* key type is just plain raw bytes */);
- return CryptoOps.hkdf(inputKeyMaterial, RESUME, info);
- } catch (NoSuchAlgorithmException | InvalidKeyException e) {
- // Does not happen in practice
- Log.e(TAG, "Compute MAC failed");
- return null;
- }
- }
-
- private boolean authenticateClient(byte[] message) {
- if (message.length != RESUME_HMAC_LENGTH) {
- Log.e(TAG, "failing because message.length is " + message.length);
- return false;
- }
- return MessageDigest.isEqual(message,
- computeMAC(mPrevContext, mCurrentContext, CLIENT));
- }
-
void processCredentials(byte[] credentials) {
if (mUnlockDelegate == null) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
@@ -567,16 +467,12 @@
*/
private void resetEncryptionState() {
mEncryptionRunner = EncryptionRunnerFactory.newRunner();
- mHandshakeMessage = null;
+ // It should always be a reconnection for unlock because only enrolled device can unlock
+ // the IHU.
+ mEncryptionRunner.setIsReconnect(true);
mEncryptionKey = null;
mEncryptionState = HandshakeMessage.HandshakeState.UNKNOWN;
mCurrentUnlockState = UNLOCK_STATE_WAITING_FOR_UNIQUE_ID;
- if (mCurrentContext != null) {
- mCurrentContext = null;
- }
- if (mPrevContext != null) {
- mPrevContext = null;
- }
}
void dump(PrintWriter writer) {
diff --git a/service/src/com/android/car/trust/CarTrustedDeviceService.java b/service/src/com/android/car/trust/CarTrustedDeviceService.java
index 9779848..1ffdbd3 100644
--- a/service/src/com/android/car/trust/CarTrustedDeviceService.java
+++ b/service/src/com/android/car/trust/CarTrustedDeviceService.java
@@ -16,6 +16,7 @@
package com.android.car.trust;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.bluetooth.BluetoothDevice;
@@ -85,7 +86,8 @@
public CarTrustedDeviceService(Context context) {
mContext = context;
- mCarTrustAgentBleManager = new CarTrustAgentBleManager(context);
+ BlePeripheralManager blePeripheralManager = new BlePeripheralManager(context);
+ mCarTrustAgentBleManager = new CarTrustAgentBleManager(context, blePeripheralManager);
mCarTrustAgentEnrollmentService = new CarTrustAgentEnrollmentService(mContext, this,
mCarTrustAgentBleManager);
mCarTrustAgentUnlockService = new CarTrustAgentUnlockService(mContext, this,
@@ -239,7 +241,7 @@
@Nullable
byte[] getEncryptionKey(String deviceId) {
SharedPreferences prefs = getSharedPrefs();
- String key = PREF_ENCRYPTION_KEY_PREFIX + deviceId;
+ String key = createSharedPrefKey(deviceId);
if (!prefs.contains(key)) {
return null;
}
@@ -271,13 +273,13 @@
if (encryptedKey == null) {
return false;
}
- if (getSharedPrefs().contains(deviceId)) {
+ if (getSharedPrefs().contains(createSharedPrefKey(deviceId))) {
clearEncryptionKey(deviceId);
}
return getSharedPrefs()
.edit()
- .putString(PREF_ENCRYPTION_KEY_PREFIX + deviceId, encryptedKey)
+ .putString(createSharedPrefKey(deviceId), encryptedKey)
.commit();
}
@@ -290,7 +292,10 @@
if (deviceId == null) {
return;
}
- getSharedPrefs().edit().remove(deviceId);
+ getSharedPrefs()
+ .edit()
+ .remove(createSharedPrefKey(deviceId))
+ .commit();
}
/**
@@ -391,4 +396,8 @@
throw new IllegalStateException(e);
}
}
+
+ private String createSharedPrefKey(@NonNull String deviceId) {
+ return PREF_ENCRYPTION_KEY_PREFIX + deviceId;
+ }
}
diff --git a/service/src/com/android/car/trust/ScanResults.kt b/service/src/com/android/car/trust/ScanResults.kt
new file mode 100644
index 0000000..d9818c9
--- /dev/null
+++ b/service/src/com/android/car/trust/ScanResults.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:JvmName("ScanResults")
+
+package com.android.car.trust
+
+import android.bluetooth.le.ScanResult
+import android.util.Log
+
+import java.math.BigInteger
+
+private const val TAG = "ScanResults"
+
+private const val IOS_OVERFLOW_LENGTH = 0x14
+private const val IOS_ADVERTISING_TYPE = 0xff
+private const val IOS_ADVERTISING_TYPE_LENGTH = 1
+private const val IOS_OVERFLOW_CUSTOM_ID: Long = 0x4c0001
+private const val IOS_OVERFLOW_CUSTOM_ID_LENGTH = 3
+private const val IOS_OVERFLOW_CONTENT_LENGTH = IOS_OVERFLOW_LENGTH -
+ IOS_OVERFLOW_CUSTOM_ID_LENGTH - IOS_ADVERTISING_TYPE_LENGTH
+
+/**
+ * When an iOS peripheral device goes into a background state, the service UUIDs and other
+ * identifying information are removed from the advertising data and replaced with a hashed
+ * bit in a special "overflow" area. There is no documentation on the layout of this area,
+ * and the below was compiled from experimentation and examples from others who have worked
+ * on reverse engineering iOS background peripherals.
+ *
+ * My best guess is Apple is taking the service UUID and hashing it into a bloom filter. This
+ * would allow any device with the same hashing function to filter for all devices that
+ * might contain the desired service. Since we do not have access to this hashing function,
+ * we must first advertise our service from an iOS device and manually inspect the bit that
+ * is flipped. Once known, it can be passed to [serviceUuidMask] and used as a filter.
+ *
+ * EXAMPLE
+ *
+ * Foreground contents:
+ * 02011A1107FB349B5F8000008000100000C53A00000709546573746572000000000000000000000000000000000000000000000000000000000000000000
+ *
+ * Background contents:
+ * 02011A14FF4C0001000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000
+ *
+ * The overflow bytes are comprised of four parts:
+ * Length -> 14
+ * Advertising type -> FF
+ * Id custom to Apple -> 4C0001
+ * Contents where hashed values are stored -> 00000000000000000000000000200000
+ *
+ * Apple's documentation on advertising from the background:
+ * https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/CoreBluetoothBackgroundProcessingForIOSApps/PerformingTasksWhileYourAppIsInTheBackground.html#//apple_ref/doc/uid/TP40013257-CH7-SW9
+ *
+ * Other similar reverse engineering:
+ * http://www.pagepinner.com/2014/04/how-to-get-ble-overflow-hash-bit-from.html
+ */
+fun ScanResult.containsUuidsInOverflow(serviceUuidMask: BigInteger): Boolean {
+ val overflowBytes = ByteArray(IOS_OVERFLOW_CONTENT_LENGTH)
+ val scanData = scanRecord.bytes
+ var outPtr = 0
+ var overflowPtr = 0
+
+ try {
+ while (overflowPtr < scanData.size - IOS_OVERFLOW_LENGTH) {
+ val length = scanData[overflowPtr++].toInt()
+ if (length == 0) {
+ break
+ }
+
+ if (scanData[overflowPtr].toInt() and 0xff != IOS_ADVERTISING_TYPE) {
+ continue
+ }
+ overflowPtr++
+
+ if (length != IOS_OVERFLOW_LENGTH) {
+ return false
+ }
+
+ val idBytes = ByteArray(IOS_OVERFLOW_CUSTOM_ID_LENGTH)
+ for (i in 0 until IOS_OVERFLOW_CUSTOM_ID_LENGTH) {
+ idBytes[i] = scanData[overflowPtr++]
+ }
+ if (BigInteger(idBytes) != BigInteger.valueOf(IOS_OVERFLOW_CUSTOM_ID)) {
+ return false
+ }
+
+ for (i in 0 until IOS_OVERFLOW_CONTENT_LENGTH) {
+ val value = scanData[overflowPtr++]
+ overflowBytes[outPtr] = value
+ outPtr++
+ }
+
+ break
+ }
+
+ if (outPtr == IOS_OVERFLOW_CONTENT_LENGTH) {
+ val overflowBytesValue = BigInteger(overflowBytes)
+ // Did the overflow contain the service uuid bit?
+ return (overflowBytesValue and serviceUuidMask).signum() == 1
+ }
+ } catch (e: ArrayIndexOutOfBoundsException) {
+ Log.w(TAG, "Inspecting advertisement overflow bytes went out of bounds.")
+ }
+
+ return false
+}
\ No newline at end of file
diff --git a/service/src/com/android/car/vms/VmsClientManager.java b/service/src/com/android/car/vms/VmsClientManager.java
index ba92a46..1649319 100644
--- a/service/src/com/android/car/vms/VmsClientManager.java
+++ b/service/src/com/android/car/vms/VmsClientManager.java
@@ -121,8 +121,7 @@
}
mCurrentUser = currentUserId;
- if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())
- || mUserManager.isUserUnlocked(mCurrentUser)) {
+ if (mUserManager.isUserUnlocked(mCurrentUser)) {
bindToSystemClients();
bindToUserClients();
}
@@ -235,11 +234,11 @@
private void bindToSystemClients() {
String[] clientNames = mContext.getResources().getStringArray(
R.array.vmsPublisherSystemClients);
- Log.i(TAG, "Attempting to bind " + clientNames.length + " system client(s)");
synchronized (mSystemClients) {
if (!mSystemUserUnlocked) {
return;
}
+ Log.i(TAG, "Attempting to bind " + clientNames.length + " system client(s)");
for (String clientName : clientNames) {
bind(mSystemClients, clientName, UserHandle.SYSTEM);
}
diff --git a/tests/CarDeveloperOptions/res/values-b+sr+Latn/strings.xml b/tests/CarDeveloperOptions/res/values-b+sr+Latn/strings.xml
index c0c06cf..572de09 100644
--- a/tests/CarDeveloperOptions/res/values-b+sr+Latn/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-b+sr+Latn/strings.xml
@@ -2880,9 +2880,9 @@
<item quantity="other">Proveri sertifikate</item>
</plurals>
<string name="user_settings_title" msgid="7917598650933179545">"Više korisnika"</string>
- <string name="user_settings_footer_text" product="device" msgid="4573858247439190545">"Delite uređaj tako što ćete dodati nove korisnike. Svaki korisnik ima lični prostor na uređaju za prilagođene početne ekrane, naloge, aplikacije, podešavanja i još mnogo toga."</string>
- <string name="user_settings_footer_text" product="tablet" msgid="780018221428132918">"Delite tablet tako što ćete dodati nove korisnike. Svaki korisnik ima lični prostor na tabletu za prilagođene početne ekrane, naloge, aplikacije, podešavanja i još mnogo toga."</string>
- <string name="user_settings_footer_text" product="default" msgid="1470859614968237491">"Delite telefon tako što ćete dodati nove korisnike. Svaki korisnik ima lični prostor na telefonu za prilagođene početne ekrane, naloge, aplikacije, podešavanja i još mnogo toga."</string>
+ <string name="user_settings_footer_text" product="device" msgid="4573858247439190545">"Delite uređaj tako što ćete dodati nove korisnike. Svaki korisnik ima lični prostor na uređaju za prilagođene početne ekrane, naloge, aplikacije, podešavanja i drugo."</string>
+ <string name="user_settings_footer_text" product="tablet" msgid="780018221428132918">"Delite tablet tako što ćete dodati nove korisnike. Svaki korisnik ima lični prostor na tabletu za prilagođene početne ekrane, naloge, aplikacije, podešavanja i drugo."</string>
+ <string name="user_settings_footer_text" product="default" msgid="1470859614968237491">"Delite telefon tako što ćete dodati nove korisnike. Svaki korisnik ima lični prostor na telefonu za prilagođene početne ekrane, naloge, aplikacije, podešavanja i drugo."</string>
<string name="user_list_title" msgid="6670258645246192324">"Korisnici i profili"</string>
<string name="user_add_user_or_profile_menu" msgid="4220679989900149336">"Dodaj korisnika ili profil"</string>
<string name="user_add_user_menu" msgid="9006572936456324794">"Dodaj korisnika"</string>
diff --git a/tests/CarDeveloperOptions/res/values-bn/strings.xml b/tests/CarDeveloperOptions/res/values-bn/strings.xml
index d43defa..3d97d41 100644
--- a/tests/CarDeveloperOptions/res/values-bn/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-bn/strings.xml
@@ -982,7 +982,7 @@
<string name="wifi_scan_always_turnon_message" msgid="7811846312032594248">"লোকেশন নির্ভুলতা উন্নতি ও অন্যান্য উদ্দ্যেশ্যের জন্য <xliff:g id="APP_NAME">%1$s</xliff:g> নেটওয়ার্ক স্ক্যান চালু করতে চাইছে, এমনকি ওয়াই-ফাই বন্ধ থাকা সত্ত্বেও।\n\nযে সব অ্যাপ্লিকেশানগুলি স্ক্যান করতে চাই তাদের জন্য এটির অনুমতি দেবেন?"</string>
<string name="wifi_scan_always_turnoff_message" msgid="556993843641750002">"এটি বন্ধ করতে, ওভারফ্লো মেনুতে ‘উন্নত’ লেখায় যান"</string>
<string name="wifi_scan_always_confirm_allow" msgid="8857664849515496237">"অনুমতি দিন"</string>
- <string name="wifi_scan_always_confirm_deny" msgid="6190909841125369403">"আস্বীকার করুন"</string>
+ <string name="wifi_scan_always_confirm_deny" msgid="6190909841125369403">"অস্বীকার করুন"</string>
<string name="wifi_hotspot_title" msgid="2631956539767069385">"কানেক্ট করতে প্রবেশ করবেন?"</string>
<string name="wifi_hotspot_message" msgid="6762452611090766607">"<xliff:g id="APP_NAME">%1$s</xliff:g> এর চাহিদা অনুযায়ী নেটওয়ার্কের সাথে কানেক্ট হওয়ার পূর্বে আপনাকে অনলাইনে প্রবেশ করতে হবে।"</string>
<string name="wifi_hotspot_connect" msgid="409079339360849653">"কানেক্ট করুন"</string>
@@ -3071,7 +3071,7 @@
<string name="keywords_factory_data_reset" msgid="5865739790670615499">"ওয়াইপ করুন, মুছুন, ফিরিয়ে আনুন, মুছুন, সরান, ফ্যাক্টরি রিসেট করুন"</string>
<string name="keywords_printing" msgid="8499167841024606451">"প্রিন্টার"</string>
<string name="keywords_sounds" msgid="9155626618185269312">"স্পিকার বিপ, স্পিকার, ভলিউম, মিউট, সাইলেন্স, অডিও, মিউজিক"</string>
- <string name="keywords_sounds_and_notifications_interruptions" msgid="7106220678170229900">"বিরক্ত করবেন না, বাধা দেওয়া, বাধা, বিরতি"</string>
+ <string name="keywords_sounds_and_notifications_interruptions" msgid="7106220678170229900">"বিরক্ত করবে না, বাধা দেওয়া, বাধা, বিরতি"</string>
<string name="keywords_app" msgid="8058542404742867098">"RAM"</string>
<string name="keywords_location" msgid="6439463166207072559">"আশেপাশে, লোকেশন, ইতিহাস, রিপোর্টিং, জিপিএস"</string>
<string name="keywords_accounts" msgid="5908945725229306088">"অ্যাকাউন্ট"</string>
@@ -3123,7 +3123,7 @@
<string name="keywords_battery_saver_sticky" msgid="8733804259716284872">"ব্যাটারি সেভার, স্টিকি, লেগে থাকা, পাওয়ার সেভার, ব্যাটারি"</string>
<string name="default_sound" msgid="6675629744816442953">"ডিফল্ট সাউন্ড"</string>
<string name="sound_settings_summary" msgid="8467549670633195109">"রিং ভলিউম <xliff:g id="PERCENTAGE">%1$s</xliff:g> তে রয়েছে"</string>
- <string name="sound_dashboard_summary" msgid="5187301919242823508">"ভলিউম, কম্পন, বিরক্ত করবেন না"</string>
+ <string name="sound_dashboard_summary" msgid="5187301919242823508">"ভলিউম, কম্পন, বিরক্ত করবে না"</string>
<string name="sound_settings_summary_vibrate" msgid="2194491116884798590">"রিঙ্গারকে ভাইব্রেট অবস্থায় সেট করা হয়েছে"</string>
<string name="sound_settings_summary_silent" msgid="899823817462768876">"রিঙ্গারকে নীরব অবস্থায় সেট করা হয়েছে"</string>
<string name="sound_settings_example_summary" msgid="2091822107298841827">"রিং ভলিউম ৮০% তে রয়েছে"</string>
@@ -3161,8 +3161,8 @@
<item quantity="one"><xliff:g id="ON_COUNT">%d</xliff:g>টি চালু করা আছে</item>
<item quantity="other"><xliff:g id="ON_COUNT">%d</xliff:g>টি চালু করা আছে</item>
</plurals>
- <string name="zen_mode_settings_title" msgid="3425263414594779244">"বিরক্ত করবেন না"</string>
- <string name="zen_mode_settings_turn_on_dialog_title" msgid="3062548369931058282">"\'বিরক্ত করবেন না\' মোড চালু করুন"</string>
+ <string name="zen_mode_settings_title" msgid="3425263414594779244">"বিরক্ত করবে না"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="3062548369931058282">"\'বিরক্ত করবে না\' মোড চালু করুন"</string>
<string name="zen_mode_behavior_settings_title" msgid="423125904296667490">"ব্যতিক্রম"</string>
<string name="zen_mode_duration_settings_title" msgid="5522668871014735728">"ডিফল্ট সময়কাল"</string>
<string name="zen_mode_behavior_allow_title" msgid="2440627647424280842">"এগুলির সাউন্ড ও ভাইব্রেশন হবে"</string>
@@ -3178,7 +3178,7 @@
<string name="zen_mode_automatic_rule_settings_page_title" msgid="5272888746413504692">"সময়সূচি"</string>
<string name="zen_mode_schedule_category_title" msgid="1936785755444711221">"সময়সূচি"</string>
<string name="zen_mode_automation_suggestion_title" msgid="4921779962633710347">"নির্দিষ্ট সময়ে ফোন সাইলেন্ট করুন"</string>
- <string name="zen_mode_automation_suggestion_summary" msgid="2709837472884371037">"\'বিরক্ত করবেন না\' মোডের নিয়ম সেট-আপ করুন"</string>
+ <string name="zen_mode_automation_suggestion_summary" msgid="2709837472884371037">"\'বিরক্ত করবে না\' মোডের নিয়ম সেট-আপ করুন"</string>
<string name="zen_mode_schedule_title" msgid="5275268813192802631">"সময়সূচি"</string>
<string name="zen_mode_use_automatic_rule" msgid="446326253915861824">"সময়সূচি ব্যবহার করুন"</string>
<string name="zen_mode_option_important_interruptions" msgid="5173944276846940149">"শুধুমাত্র অগ্রাধিকার"</string>
@@ -3187,14 +3187,14 @@
<string name="zen_mode_summary_combination" msgid="6960111215170691605">"<xliff:g id="MODE">%1$s</xliff:g>: <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
<string name="zen_mode_visual_interruptions_settings_title" msgid="8378266552787406849">"ভিজ্যুয়াল ব্যাঘাতগুলিকে ব্লক করুন"</string>
<string name="zen_mode_visual_signals_settings_subtitle" msgid="6608239691864638854">"ভিজুয়াল সঙ্কেতগুলি চালু করুন"</string>
- <string name="zen_mode_settings_category" msgid="5601680733422424922">"যখন \'বিরক্ত করবেন না চালু\' থাকবে"</string>
+ <string name="zen_mode_settings_category" msgid="5601680733422424922">"যখন \'বিরক্ত করবে না চালু\' থাকবে"</string>
<string name="zen_mode_restrict_notifications_title" msgid="7486753018073540477">"বিজ্ঞপ্তি ব্লক করুন"</string>
<string name="zen_mode_restrict_notifications_mute" msgid="2673665450311184875">"বিজ্ঞপ্তি থেকে কোনও সাউন্ড হবে না"</string>
<string name="zen_mode_restrict_notifications_mute_summary" msgid="1696217042353376674">"আপনার স্ক্রিনে বিজ্ঞপ্তি দেখতে পাবেন"</string>
<string name="zen_mode_restrict_notifications_mute_footer" msgid="3049522809520549054">"বিজ্ঞপ্তি দেখানো হলে ফোনে সাউন্ড বা ভাইব্রেশন হবে না।"</string>
<string name="zen_mode_restrict_notifications_hide" msgid="3296933643539682552">"বিজ্ঞপ্তি থেকে কোনও কিছু দেখা বা শোনা যাবে না"</string>
<string name="zen_mode_restrict_notifications_hide_summary" msgid="1449301153755270168">"আপনি কোনও বিজ্ঞপ্তি দেখতে বা শুনতে পাবেন না"</string>
- <string name="zen_mode_restrict_notifications_hide_footer" msgid="7617688597593946765">"নতুন অথবা আগে থেকে রয়েছে এমন বিজ্ঞপ্তির ক্ষেত্রে আপনার ফোনে ভাইব্রেশন অথবা সাউন্ড হবে না বা কোনও কিছু দেখাবে না। মনে রাখবেন, ফোনের অ্যাক্টিভিটি এবং স্ট্যাটাস সংক্রান্ত জরুরি বিজ্ঞপ্তি দেখানো হবে।\n\nআপনি ফোনে \"বিরক্ত করবেন না মোড\" বন্ধ করে রাখলে, স্ক্রিনের উপর থেকে নিচে সোয়াইপ করে মিস হওয়া বিজ্ঞপ্তিগুলি দেখুন।"</string>
+ <string name="zen_mode_restrict_notifications_hide_footer" msgid="7617688597593946765">"নতুন অথবা আগে থেকে রয়েছে এমন বিজ্ঞপ্তির ক্ষেত্রে আপনার ফোনে ভাইব্রেশন অথবা সাউন্ড হবে না বা কোনও কিছু দেখাবে না। মনে রাখবেন, ফোনের অ্যাক্টিভিটি এবং স্ট্যাটাস সংক্রান্ত জরুরি বিজ্ঞপ্তি দেখানো হবে।\n\nআপনি ফোনে \"বিরক্ত করবে না মোড\" বন্ধ করে রাখলে, স্ক্রিনের উপর থেকে নিচে সোয়াইপ করে মিস হওয়া বিজ্ঞপ্তিগুলি দেখুন।"</string>
<string name="zen_mode_restrict_notifications_custom" msgid="3167252482570424133">"কাস্টম"</string>
<string name="zen_mode_restrict_notifications_enable_custom" msgid="6376983315529894440">"কাস্টম সেটিং চালু করুন"</string>
<string name="zen_mode_restrict_notifications_disable_custom" msgid="8004212081465043044">"কাস্টম সেটিং সরান"</string>
@@ -3225,11 +3225,11 @@
<string name="zen_mode_enable_dialog_turn_on" msgid="6396050543542026184">"চালু করুন"</string>
<string name="zen_mode_button_turn_on" msgid="1097964136225943415">"এখনই চালু করুন"</string>
<string name="zen_mode_button_turn_off" msgid="3990967728457149454">"এখনই বন্ধ করুন"</string>
- <string name="zen_mode_settings_dnd_manual_end_time" msgid="4307574188962071429">"\'বিরক্ত করবেন না\' মোডটি <xliff:g id="FORMATTED_TIME">%s</xliff:g> পর্যন্ত চালু থাকবে"</string>
- <string name="zen_mode_settings_dnd_manual_indefinite" msgid="3701005376825238752">"\'বিরক্ত করবেন না\' মোডটি বন্ধ না করা পর্যন্ত সেটি চালু থাকবে"</string>
- <string name="zen_mode_settings_dnd_automatic_rule" msgid="2843297614114625408">"(<xliff:g id="RULE_NAME">%s</xliff:g>) শিডিউলের জন্য বিরক্ত করবেন না মোডটি নিজে থেকেই চালু হয়ে গেছে"</string>
- <string name="zen_mode_settings_dnd_automatic_rule_app" msgid="5103454923160912313">"<xliff:g id="APP_NAME">%s</xliff:g> অ্যাপটি নিজে থেকেই \'বিরক্ত করবেন না\' মোড চালু করে দিয়েছে"</string>
- <string name="zen_mode_settings_dnd_custom_settings_footer" msgid="6335108298640066560">"কাস্টম সেটিংস সহ <xliff:g id="RULE_NAMES">%s</xliff:g>-এর জন্য \'বিরক্ত করবেন না\' মোডটি চালু আছে।"</string>
+ <string name="zen_mode_settings_dnd_manual_end_time" msgid="4307574188962071429">"\'বিরক্ত করবে না\' মোডটি <xliff:g id="FORMATTED_TIME">%s</xliff:g> পর্যন্ত চালু থাকবে"</string>
+ <string name="zen_mode_settings_dnd_manual_indefinite" msgid="3701005376825238752">"\'বিরক্ত করবে না\' মোডটি বন্ধ না করা পর্যন্ত সেটি চালু থাকবে"</string>
+ <string name="zen_mode_settings_dnd_automatic_rule" msgid="2843297614114625408">"(<xliff:g id="RULE_NAME">%s</xliff:g>) শিডিউলের জন্য বিরক্ত করবে না মোডটি নিজে থেকেই চালু হয়ে গেছে"</string>
+ <string name="zen_mode_settings_dnd_automatic_rule_app" msgid="5103454923160912313">"<xliff:g id="APP_NAME">%s</xliff:g> অ্যাপটি নিজে থেকেই \'বিরক্ত করবে না\' মোড চালু করে দিয়েছে"</string>
+ <string name="zen_mode_settings_dnd_custom_settings_footer" msgid="6335108298640066560">"কাস্টম সেটিংস সহ <xliff:g id="RULE_NAMES">%s</xliff:g>-এর জন্য \'বিরক্ত করবে না\' মোডটি চালু আছে।"</string>
<string name="zen_mode_settings_dnd_custom_settings_footer_link" msgid="4007974052885089379"><annotation id="link">" কাস্টম সেটিংস দেখুন"</annotation></string>
<string name="zen_interruption_level_priority" msgid="9178419297408319234">"শুধুমাত্র অগ্রাধিকার"</string>
<string name="zen_mode_and_condition" msgid="4123722186007123567">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
@@ -3252,7 +3252,7 @@
<string name="zen_category_exceptions" msgid="2139670640033601899">"ব্যতিক্রম"</string>
<string name="zen_category_schedule" msgid="989629666210114164">"সময় ঠিক করুন"</string>
<string name="zen_sound_title" msgid="3429086967245473870">"সবগুলি দেখুন"</string>
- <string name="zen_sound_footer" msgid="1778673975517424878">"\'বিরক্ত করবেন না\' মোড চালু থাকলে আপনি উপরে যে আইটেমগুলি ব্যতিক্রম হিসেবে চিহ্নিত করবেন সেগুলি ছাড়া বাকি সবকিছুর ক্ষেত্রে সাউন্ড এবং ভাইব্রেশন মিউট করা হবে।"</string>
+ <string name="zen_sound_footer" msgid="1778673975517424878">"\'বিরক্ত করবে না\' মোড চালু থাকলে আপনি উপরে যে আইটেমগুলি ব্যতিক্রম হিসেবে চিহ্নিত করবেন সেগুলি ছাড়া বাকি সবকিছুর ক্ষেত্রে সাউন্ড এবং ভাইব্রেশন মিউট করা হবে।"</string>
<string name="zen_sound_category_title" msgid="2109447208414722786">"এগুলি ছাড়া সবকিছু মিউট করুন"</string>
<string name="zen_sound_all_muted" msgid="4844094866910870591">"মিউট করা আছে"</string>
<string name="zen_sound_none_muted" msgid="4869385974769188085">"মিউট করা নেই"</string>
@@ -3265,14 +3265,14 @@
<string name="zen_custom_settings_notifications_header" msgid="7469592764589354302">"বিজ্ঞপ্তি"</string>
<string name="zen_custom_settings_duration_header" msgid="1806465684026300942">"সময়কাল"</string>
<string name="zen_msg_event_reminder_title" msgid="8685224436389816905">"মেসেজ, ইভেন্ট ও রিমাইন্ডার"</string>
- <string name="zen_msg_event_reminder_footer" msgid="164400918479831580">"\'বিরক্ত করবেন না\' মোড চালু থাকলে আপনি উপরে যে আইটেমগুলি ব্যতিক্রম হিসেবে চিহ্নিত করবেন সেগুলি ছাড়া বাকি সমস্ত মেসেজ, রিমাইন্ডার এবং ইভেন্ট মিউট করা হবে। আপনার বন্ধুবান্ধব, পরিবারের সদস্য অথবা অন্য পরিচিতিরা যাতে আপনার সাথে যোগাযোগ করতে পারেন তার জন্য আপনি মেসেজের সেটিংস অ্যাডজাস্ট করে নিতে পারেন।"</string>
+ <string name="zen_msg_event_reminder_footer" msgid="164400918479831580">"\'বিরক্ত করবে না\' মোড চালু থাকলে আপনি উপরে যে আইটেমগুলি ব্যতিক্রম হিসেবে চিহ্নিত করবেন সেগুলি ছাড়া বাকি সমস্ত মেসেজ, রিমাইন্ডার এবং ইভেন্ট মিউট করা হবে। আপনার বন্ধুবান্ধব, পরিবারের সদস্য অথবা অন্য পরিচিতিরা যাতে আপনার সাথে যোগাযোগ করতে পারেন তার জন্য আপনি মেসেজের সেটিংস অ্যাডজাস্ট করে নিতে পারেন।"</string>
<string name="zen_onboarding_ok" msgid="6403635918125323678">"হয়ে গেছে"</string>
<string name="zen_onboarding_settings" msgid="1416466597876383322">"সেটিংস"</string>
<string name="zen_onboarding_new_setting_title" msgid="3622673375041304362">"বিজ্ঞপ্তি থেকে কোনও কিছু দেখা বা শোনা যাবে না"</string>
<string name="zen_onboarding_current_setting_title" msgid="2560330551761407563">"বিজ্ঞপ্তি থেকে কোনও সাউন্ড হবে না"</string>
<string name="zen_onboarding_new_setting_summary" msgid="8264430315983860075">"আপনি কোনও বিজ্ঞপ্তি দেখতে বা শুনতে পাবেন না। যারা তারা চিহ্নিত পরিচিতি এবং আগে যারা ফোন করেছেন তারা আবার ফোন করতে পারবেন।"</string>
<string name="zen_onboarding_current_setting_summary" msgid="3569246708507270821">"(বর্তমান সেটিং)"</string>
- <string name="zen_onboarding_dnd_visual_disturbances_header" msgid="7584229011611927613">"\"বিরক্ত করবেন না\" মোডের বিজ্ঞপ্তির সেটিংস পরিবর্তন করবেন?"</string>
+ <string name="zen_onboarding_dnd_visual_disturbances_header" msgid="7584229011611927613">"\"বিরক্ত করবে না\" মোডের বিজ্ঞপ্তির সেটিংস পরিবর্তন করবেন?"</string>
<string name="sound_work_settings" msgid="4140215240360927923">"কর্মস্থলের প্রোফাইলের ধ্বনিগুলি"</string>
<string name="work_use_personal_sounds_title" msgid="531727195073003599">"ব্যক্তিগত প্রোফাইলের ধ্বনিগুলি ব্যবহার করুন"</string>
<string name="work_use_personal_sounds_summary" msgid="2886871383995187441">"কাজ এবং ব্যক্তিগত প্রোফাইলের জন্য একই শব্দ"</string>
@@ -3364,10 +3364,10 @@
<string name="no_notification_assistant" msgid="9140123568386413264">"অ্যাসিস্ট্যান্টের পরিষেবা পাওয়া যাবে না"</string>
<string name="no_notification_listeners" msgid="1366386609506834717">"ইনস্টল করা কোনো অ্যাপের অনুরোধকৃত বিজ্ঞপ্তির অ্যাক্সেস নেই৷"</string>
<string name="notification_assistant_security_warning_title" msgid="4190584438086738496">"<xliff:g id="SERVICE">%1$s</xliff:g>-কে বিজ্ঞপ্তিতে অ্যাক্সেস দিতে চান?"</string>
- <string name="notification_assistant_security_warning_summary" msgid="6924513399671031930">"<xliff:g id="NOTIFICATION_ASSISTANT_NAME">%1$s</xliff:g> পরিচিতির নাম এবং আপনি পেয়েছেন এমন টেক্সট মেসেজ সহ ব্যক্তিগত তথ্যের সব বিজ্ঞপ্তি পড়তে পারবে। এর মধ্যে থাকা বিজ্ঞপ্তি পরিবর্তন করতে বা অ্যাকশন বোতাম ট্রিগার করতে বা খারিজ করতে পারবে। \n\nএই অ্যাপ \'বিরক্ত করবেন না\' বিকল্পটিকে চালু বা বন্ধ করার এবং সম্পর্কিত সেটিংস পরিবর্তন করতে পারবে।"</string>
+ <string name="notification_assistant_security_warning_summary" msgid="6924513399671031930">"<xliff:g id="NOTIFICATION_ASSISTANT_NAME">%1$s</xliff:g> পরিচিতির নাম এবং আপনি পেয়েছেন এমন টেক্সট মেসেজ সহ ব্যক্তিগত তথ্যের সব বিজ্ঞপ্তি পড়তে পারবে। এর মধ্যে থাকা বিজ্ঞপ্তি পরিবর্তন করতে বা অ্যাকশন বোতাম ট্রিগার করতে বা খারিজ করতে পারবে। \n\nএই অ্যাপ \'বিরক্ত করবে না\' বিকল্পটিকে চালু বা বন্ধ করার এবং সম্পর্কিত সেটিংস পরিবর্তন করতে পারবে।"</string>
<string name="notification_listener_security_warning_title" msgid="4902253246428777797">"<xliff:g id="SERVICE">%1$s</xliff:g> এর জন্য বিজ্ঞপ্তির অ্যাক্সেসে অনুমতি দেবেন?"</string>
- <string name="notification_listener_security_warning_summary" msgid="4454702907350100288">"<xliff:g id="NOTIFICATION_LISTENER_NAME">%1$s</xliff:g>, পরিচিতির নাম ও আপনার গৃহীত পাঠ্য বার্তাগুলির মত ব্যক্তিগত তথ্য সহ সমস্ত বিজ্ঞপ্তি পড়তে সক্ষম হবে৷ এটি আবার এর মধ্যে থাকা বিজ্ঞপ্তিগুলি বা নির্দিষ্ট কাজের বোতামগুলি খারিজ করতে পারবে। \n\nএছাড়াও এটি এই অ্যাপ্লিকেশানকে, \'বিরক্ত করবেন না\' বিকল্পটিকে চালু বা বন্ধ করার এবং সংশ্লিষ্ট সেটিংস পরিবর্তন করার ক্ষমতা প্রদান করবে৷"</string>
- <string name="notification_listener_disable_warning_summary" msgid="162165151519082978">"যদি আপনি <xliff:g id="NOTIFICATION_LISTENER_NAME">%1$s</xliff:g> এর জন্য বিজ্ঞপ্তির অ্যাক্সেস বন্ধ করেন, তাহলে \'বিরক্ত করবেন না\' এর অ্যাক্সেসও বন্ধ হয়ে যেতে পারে৷"</string>
+ <string name="notification_listener_security_warning_summary" msgid="4454702907350100288">"<xliff:g id="NOTIFICATION_LISTENER_NAME">%1$s</xliff:g>, পরিচিতির নাম ও আপনার গৃহীত পাঠ্য বার্তাগুলির মত ব্যক্তিগত তথ্য সহ সমস্ত বিজ্ঞপ্তি পড়তে সক্ষম হবে৷ এটি আবার এর মধ্যে থাকা বিজ্ঞপ্তিগুলি বা নির্দিষ্ট কাজের বোতামগুলি খারিজ করতে পারবে। \n\nএছাড়াও এটি এই অ্যাপ্লিকেশানকে, \'বিরক্ত করবে না\' বিকল্পটিকে চালু বা বন্ধ করার এবং সংশ্লিষ্ট সেটিংস পরিবর্তন করার ক্ষমতা প্রদান করবে৷"</string>
+ <string name="notification_listener_disable_warning_summary" msgid="162165151519082978">"যদি আপনি <xliff:g id="NOTIFICATION_LISTENER_NAME">%1$s</xliff:g> এর জন্য বিজ্ঞপ্তির অ্যাক্সেস বন্ধ করেন, তাহলে \'বিরক্ত করবে না\' এর অ্যাক্সেসও বন্ধ হয়ে যেতে পারে৷"</string>
<string name="notification_listener_disable_warning_confirm" msgid="7863495391671154188">"বন্ধ করুন"</string>
<string name="notification_listener_disable_warning_cancel" msgid="6264631825225298458">"বাতিল করুন"</string>
<string name="vr_listeners_title" msgid="511483902408792832">"(ভিআর)VR সহায়তাকারী পরিষেবাগুলি"</string>
@@ -3383,9 +3383,9 @@
<string name="picture_in_picture_app_detail_title" msgid="3916189052657425936">"ছবির-মধ্যে-ছবি"</string>
<string name="picture_in_picture_app_detail_switch" msgid="747422998967185418">"ছবির-মধ্যে-ছবি তৈরির অনুমতি দিন"</string>
<string name="picture_in_picture_app_detail_summary" msgid="918632751775525347">"অ্যাপটি খোলা থাকার সময় অথবা আপনি এটি ছেড়ে বেরিয়ে গেলে (যেমন, কোনও ভিডিও দেখার জন্য) এটিকে একটি ছবির-মধ্যে-ছবি সমেত উইন্ডো তৈরি করার অনুমতি দিন। চালু থাকা অন্যান্য অ্যাপের উপরে এই উইন্ডোটি দেখা যাবে।"</string>
- <string name="manage_zen_access_title" msgid="3058206309728524196">"বিরক্ত করবেন না মোডের ক্ষেত্রে অ্যাক্সেস"</string>
- <string name="zen_access_detail_switch" msgid="8706332327904974500">"\'বিরক্ত করবেন না\' মোডের জন্য অনুমতি দিন"</string>
- <string name="zen_access_empty_text" msgid="7667538993781607731">"ইনস্টল করা নেই এমন অ্যাপগুলি বিরক্ত করবেন না অ্যাক্সেস করুন এর অনুরোধ জানিয়েছে"</string>
+ <string name="manage_zen_access_title" msgid="3058206309728524196">"বিরক্ত করবে না মোডের ক্ষেত্রে অ্যাক্সেস"</string>
+ <string name="zen_access_detail_switch" msgid="8706332327904974500">"\'বিরক্ত করবে না\' মোডের জন্য অনুমতি দিন"</string>
+ <string name="zen_access_empty_text" msgid="7667538993781607731">"ইনস্টল করা নেই এমন অ্যাপগুলি বিরক্ত করবে না অ্যাক্সেস করুন এর অনুরোধ জানিয়েছে"</string>
<string name="loading_notification_apps" msgid="1978345231934072091">"অ্যাপ্লিকেশানগুলি লোড করা হচ্ছে..."</string>
<string name="app_notifications_off_desc" msgid="3904090905748895146">"আপনার অনুরোধ অনুযায়ী Android এই অ্যাপের বিজ্ঞপ্তি এই ডিভাইসে দেখাচ্ছে না"</string>
<string name="channel_notifications_off_desc" msgid="8005444443218306611">"আপনার অনুরোধ অনুযায়ী Android এই বিভাগের বিজ্ঞপ্তিগুলি এই ডিভাইসে দেখাচ্ছে না"</string>
@@ -3415,8 +3415,8 @@
<string name="notification_content_block_summary" msgid="2743896875255591743">"ছায়া বা পেরিফেরাল ডিভাইসে কখনও বিজ্ঞপ্তিগুলি দেখায় না"</string>
<string name="notification_badge_title" msgid="8989086619255666442">"বিজ্ঞপ্তির ডট দেখানোর অনুমতি দিন"</string>
<string name="notification_channel_badge_title" msgid="8228215248332054612">"বিজ্ঞপ্তির ডট দেখান"</string>
- <string name="app_notification_override_dnd_title" msgid="1757042206738172601">"\'বিরক্ত করবেন না\' ওভাররাইড করুন"</string>
- <string name="app_notification_override_dnd_summary" msgid="3152957611171210980">"\'বিরক্ত করবেন না\' মোড চালু থাকলেও এই বিজ্ঞপ্তিগুলির জন্য আওয়াজ হতে দিন"</string>
+ <string name="app_notification_override_dnd_title" msgid="1757042206738172601">"\'বিরক্ত করবে না\' ওভাররাইড করুন"</string>
+ <string name="app_notification_override_dnd_summary" msgid="3152957611171210980">"\'বিরক্ত করবে না\' মোড চালু থাকলেও এই বিজ্ঞপ্তিগুলির জন্য আওয়াজ হতে দিন"</string>
<string name="app_notification_visibility_override_title" msgid="2349335170165637672">"লক স্ক্রিনে"</string>
<string name="app_notification_row_banned" msgid="2079325338122151677">"অবরুদ্ধ"</string>
<string name="app_notification_row_priority" msgid="432299064888787236">"অগ্রাধিকার"</string>
@@ -3439,13 +3439,13 @@
<string name="zen_mode_delete_rule_confirmation" msgid="2646596466259025978">"\"<xliff:g id="RULE">%1$s</xliff:g>\" নিয়ম মুছে ফেলবেন?"</string>
<string name="zen_mode_delete_rule_button" msgid="611058106279881991">"মুছুন"</string>
<string name="zen_mode_rule_type_unknown" msgid="2819480113355191421">"অজানা"</string>
- <string name="zen_mode_app_set_behavior" msgid="8597398780262575571">"এই সেটিংগুলি এখনই পরিবর্তন করা যাবে না। অ্যাপটি (<xliff:g id="APP_NAME">%1$s</xliff:g>) কাস্টম আচরণের সাথে \'বিরক্ত করবেন না\'\' মোডটি নিজে থেকেই চালু করে দিয়েছে।"</string>
- <string name="zen_mode_unknown_app_set_behavior" msgid="5666462954329932302">"এই সেটিংগুলি এখনই পরিবর্তন করা যাবে না। অ্যাপটি কাস্টম আচরণের সাথে \'বিরক্ত করবেন না\'\' মোডটি নিজে থেকেই চালু করে দিয়েছে।"</string>
- <string name="zen_mode_qs_set_behavior" msgid="788646569296973998">"এই সেটিংগুলি এখনই পরিবর্তন করা যাবে না। কাস্টম আচরণের সাথে ম্যানুয়ালী \'\'বিরক্ত করবেন না\'\' মোডটি চালু করা ছিল।"</string>
+ <string name="zen_mode_app_set_behavior" msgid="8597398780262575571">"এই সেটিংগুলি এখনই পরিবর্তন করা যাবে না। অ্যাপটি (<xliff:g id="APP_NAME">%1$s</xliff:g>) কাস্টম আচরণের সাথে \'বিরক্ত করবে না\'\' মোডটি নিজে থেকেই চালু করে দিয়েছে।"</string>
+ <string name="zen_mode_unknown_app_set_behavior" msgid="5666462954329932302">"এই সেটিংগুলি এখনই পরিবর্তন করা যাবে না। অ্যাপটি কাস্টম আচরণের সাথে \'বিরক্ত করবে না\'\' মোডটি নিজে থেকেই চালু করে দিয়েছে।"</string>
+ <string name="zen_mode_qs_set_behavior" msgid="788646569296973998">"এই সেটিংগুলি এখনই পরিবর্তন করা যাবে না। কাস্টম আচরণের সাথে ম্যানুয়ালী \'\'বিরক্ত করবে না\'\' মোডটি চালু করা ছিল।"</string>
<string name="zen_schedule_rule_type_name" msgid="4516851728113801329">"সময়"</string>
- <string name="zen_schedule_rule_enabled_toast" msgid="1742354493045049048">"বিরক্ত করবেন না চালু করার জন্য, নির্দিষ্ট সময়ের জন্য স্বয়ংক্রিয়ভাবে নিয়ম সেট করা"</string>
+ <string name="zen_schedule_rule_enabled_toast" msgid="1742354493045049048">"বিরক্ত করবে না চালু করার জন্য, নির্দিষ্ট সময়ের জন্য স্বয়ংক্রিয়ভাবে নিয়ম সেট করা"</string>
<string name="zen_event_rule_type_name" msgid="7467729997336583342">"ইভেন্ট"</string>
- <string name="zen_event_rule_enabled_toast" msgid="7087368268966855976">"বিরক্ত করবেন না চালু করার জন্য, নির্দিষ্ট সময়ের জন্য স্বয়ংক্রিয়ভাবে নিয়ম সেট করা"</string>
+ <string name="zen_event_rule_enabled_toast" msgid="7087368268966855976">"বিরক্ত করবে না চালু করার জন্য, নির্দিষ্ট সময়ের জন্য স্বয়ংক্রিয়ভাবে নিয়ম সেট করা"</string>
<string name="zen_mode_event_rule_calendar" msgid="6088077103908487442">"এর জন্য ইভেন্টগুলি চলাকালীন"</string>
<string name="zen_mode_event_rule_summary_calendar_template" msgid="4027207992040792657">"<xliff:g id="CALENDAR">%1$s</xliff:g> এর জন্য ইভেন্টগুলি চলাকালীন"</string>
<string name="zen_mode_event_rule_summary_any_calendar" msgid="7590085295784895885">"যেকোনো ক্যালেন্ডার"</string>
@@ -3463,7 +3463,7 @@
<string name="zen_mode_schedule_rule_days_all" msgid="8814173364016139675">"প্রতিদিন"</string>
<string name="zen_mode_schedule_alarm_title" msgid="2078194049274875023">"অ্যালার্ম সমাপ্তি সময়কে ওভাররাইড করতে পারে"</string>
<string name="zen_mode_schedule_alarm_summary" msgid="5556997989911412070">"কোনও অ্যালার্ম বাজলে সময়সূচী বন্ধ হয়ে যায়"</string>
- <string name="zen_mode_custom_behavior_title" msgid="8908861697886331001">"\'বিরক্ত করবেন না\' মোড"</string>
+ <string name="zen_mode_custom_behavior_title" msgid="8908861697886331001">"\'বিরক্ত করবে না\' মোড"</string>
<string name="zen_mode_custom_behavior_summary_default" msgid="3509865340195397447">"ডিফল্ট সেটিংস ব্যবহার করুন"</string>
<string name="zen_mode_custom_behavior_summary" msgid="7206909852887332604">"এই সময়ের জন্য কাস্টম সেটিংস তৈরি করুন"</string>
<string name="zen_mode_custom_behavior_category_title" msgid="7451686525113262087">"\'<xliff:g id="SCHEDULE_NAME">%1$s</xliff:g>\'-এর জন্য"</string>
@@ -3504,8 +3504,8 @@
<string name="zen_mode_bypassing_apps" msgid="3080739479028713449">"অ্যাপ ওভাররাইডের অনুমতি দিন"</string>
<string name="zen_mode_bypassing_apps_title" msgid="2115024664615538847">"অ্যাপ এক্সেপশন"</string>
<plurals name="zen_mode_bypassing_apps_subtext" formatted="false" msgid="8723144434730871572">
- <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">%1$d</xliff:g>টি অ্যাপকে বিজ্ঞপ্তি দেওয়ার অনুমতি দেওয়া হয়, তাহলে বিরক্ত করবে না মোড ওভাররাইড হতে পারে।</item>
+ <item quantity="other">যদি <xliff:g id="NUMBER">%1$d</xliff:g>টি অ্যাপকে বিজ্ঞপ্তি দেওয়ার অনুমতি দেওয়া হয়, তাহলে বিরক্ত করবে না মোড ওভাররাইড হতে পারে।</item>
</plurals>
<string name="zen_mode_events_list" msgid="8578102701815684873">"ইভেন্ট"</string>
<string name="zen_mode_all_callers" msgid="4455039040077343838">"যেকেউ"</string>
@@ -3537,10 +3537,10 @@
<string name="zen_mode_summary_alarms_only_by_time" msgid="2462898862757904560">"শুধুমাত্র <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> পর্যন্ত অ্যালার্মগুলি পরিবর্তন করুন"</string>
<string name="zen_mode_summary_always" msgid="2703276042913200837">"সর্বদা বাধা দেওয়াতে পরিবর্তন করুন"</string>
<string name="zen_mode_screen_on" msgid="7098470659072167219">"যখন স্ক্রিন চালু থাকে"</string>
- <string name="zen_mode_screen_on_summary" msgid="8275416649295357524">"\'বিরক্ত করবেন না\' দ্বারা মিউট করা বিজ্ঞপ্তিগুলিকে স্ক্রিনে প্রদর্শিত হতে এবং একটি স্ট্যাটাস বার আইকন দেখাতে দিন"</string>
+ <string name="zen_mode_screen_on_summary" msgid="8275416649295357524">"\'বিরক্ত করবে না\' দ্বারা মিউট করা বিজ্ঞপ্তিগুলিকে স্ক্রিনে প্রদর্শিত হতে এবং একটি স্ট্যাটাস বার আইকন দেখাতে দিন"</string>
<string name="zen_mode_screen_off" msgid="84211490206459038">"যখন স্ক্রিন বন্ধ থাকে"</string>
- <string name="zen_mode_screen_off_summary" msgid="8592179073243001267">"\'বিরক্ত করবেন না\' দ্বারা নীরব করা বিজ্ঞপ্তিগুলিকে স্ক্রিন চালু করতে এবং লাইটটি জ্বলাতে ও নেভাতে দিন"</string>
- <string name="zen_mode_screen_off_summary_no_led" msgid="7255874108150630145">"\'বিরক্ত করবেন না\' দ্বারা নীরব করা বিজ্ঞপ্তিগুলিকে স্ক্রিন চালু করতে দিন"</string>
+ <string name="zen_mode_screen_off_summary" msgid="8592179073243001267">"\'বিরক্ত করবে না\' দ্বারা নীরব করা বিজ্ঞপ্তিগুলিকে স্ক্রিন চালু করতে এবং লাইটটি জ্বলাতে ও নেভাতে দিন"</string>
+ <string name="zen_mode_screen_off_summary_no_led" msgid="7255874108150630145">"\'বিরক্ত করবে না\' দ্বারা নীরব করা বিজ্ঞপ্তিগুলিকে স্ক্রিন চালু করতে দিন"</string>
<string name="notification_app_settings_button" msgid="3651180424198580907">"বিজ্ঞপ্তির সেটিংস"</string>
<string name="suggestion_button_text" msgid="5783566542423813847">"ঠিক আছে"</string>
<string name="device_feedback" msgid="4042352891448769818">"এই ডিভাইসের সম্পর্কে মতামত পাঠান"</string>
@@ -3602,7 +3602,7 @@
<string name="notifications_silenced" msgid="538923056987616372">"মিউট করা হয়েছে"</string>
<string name="notifications_redacted" msgid="308836040236690014">"সংবেদনশীল সামগ্রীকে লক স্ক্রীনে দেখানো হবে না"</string>
<string name="notifications_hidden" msgid="3665505522897010205">"লক স্ক্রীনে দেখানো হবে না"</string>
- <string name="notifications_priority" msgid="8849045645983017929">"\'বিরক্ত করবেন না\' ওভাররাইড করা হয়েছে"</string>
+ <string name="notifications_priority" msgid="8849045645983017929">"\'বিরক্ত করবে না\' ওভাররাইড করা হয়েছে"</string>
<string name="notifications_summary_divider" msgid="3148951310482572028">" / "</string>
<string name="notification_summary_level" msgid="309162160355022027">"লেভেল %d"</string>
<string name="notification_summary_channel" msgid="3372346622071114366">"<xliff:g id="CHANNEL_NAME">%1$s</xliff:g> • <xliff:g id="GROUP_NAME">%2$s</xliff:g>"</string>
@@ -3634,7 +3634,7 @@
<string name="filter_notif_urgent_channels" msgid="5000735867167027148">"বিভাগগুলি: জরুরী গুরুত্বের"</string>
<string name="filter_notif_low_channels" msgid="6859599463135775287">"বিভাগগুলি: কম গুরুত্বের"</string>
<string name="filter_notif_blocked_channels" msgid="6110799550327612670">"বিভাগগুলি: বন্ধ আছে"</string>
- <string name="filter_notif_dnd_channels" msgid="3251570137256371092">"বিভাগগুলি: বিরক্ত করবেন না কে ওভাররাইড করে"</string>
+ <string name="filter_notif_dnd_channels" msgid="3251570137256371092">"বিভাগগুলি: বিরক্ত করবে না কে ওভাররাইড করে"</string>
<string name="advanced_apps" msgid="6643869089344883537">"উন্নত"</string>
<string name="configure_apps" msgid="4066683118857400943">"অ্যাপ্লিকেশান কনফিগার করুন"</string>
<string name="unknown_app" msgid="2312052973570376877">"অজানা অ্যাপ্লিকেশান"</string>
@@ -3779,11 +3779,11 @@
<string name="running_frequency" msgid="7545170806968474449">"পুনরাবৃত্তির হার"</string>
<string name="memory_maximum_usage" msgid="4734981118293469479">"সর্বাধিক ব্যবহার"</string>
<string name="no_data_usage" msgid="903383745620135746">"কোনো ডেটা ব্যবহৃত হয়নি"</string>
- <string name="zen_access_warning_dialog_title" msgid="7704910289810337055">"<xliff:g id="APP">%1$s</xliff:g> ব্যবহারের জন্য \'বিরক্ত করবেন না\' -তে অ্যাক্সেসের অনুমতি দেবেন?"</string>
- <string name="zen_access_warning_dialog_summary" msgid="2717755746850874577">"অ্যাপটি \'বিরক্ত করবেন না\' চালু/বন্ধ করতে সক্ষম হবে এবং এই সংক্রান্ত সেটিংসে পরিবর্তনগুলি করবে।"</string>
+ <string name="zen_access_warning_dialog_title" msgid="7704910289810337055">"<xliff:g id="APP">%1$s</xliff:g> ব্যবহারের জন্য \'বিরক্ত করবে না\' -তে অ্যাক্সেসের অনুমতি দেবেন?"</string>
+ <string name="zen_access_warning_dialog_summary" msgid="2717755746850874577">"অ্যাপটি \'বিরক্ত করবে না\' চালু/বন্ধ করতে সক্ষম হবে এবং এই সংক্রান্ত সেটিংসে পরিবর্তনগুলি করবে।"</string>
<string name="zen_access_disabled_package_warning" msgid="7086237569177576966">"বিজ্ঞপ্তির অ্যাক্সেস চালু থাকার কারণে এটিকে অবশ্যই চালু থাকতে হবে"</string>
- <string name="zen_access_revoke_warning_dialog_title" msgid="6850994585577513299">"<xliff:g id="APP">%1$s</xliff:g> এর জন্য \'বিরক্ত করবেন না\' তে অ্যাক্সেস প্রত্যাহার করবেন?"</string>
- <string name="zen_access_revoke_warning_dialog_summary" msgid="3487422193181311403">"এই অ্যাপ্লিকেশানের দ্বারা তৈরি হওয়া সমস্ত \'বিরক্ত করবেন না\' নিয়মগুলিকে সরানো হবে৷"</string>
+ <string name="zen_access_revoke_warning_dialog_title" msgid="6850994585577513299">"<xliff:g id="APP">%1$s</xliff:g> এর জন্য \'বিরক্ত করবে না\' তে অ্যাক্সেস প্রত্যাহার করবেন?"</string>
+ <string name="zen_access_revoke_warning_dialog_summary" msgid="3487422193181311403">"এই অ্যাপ্লিকেশানের দ্বারা তৈরি হওয়া সমস্ত \'বিরক্ত করবে না\' নিয়মগুলিকে সরানো হবে৷"</string>
<string name="ignore_optimizations_on" msgid="4373971641328943551">"অপ্টিমাইজ করবেন না"</string>
<string name="ignore_optimizations_off" msgid="4372289432580282870">"অপ্টিমাইজ করুন"</string>
<string name="ignore_optimizations_on_desc" msgid="2904484569799521559">"এতে চার্জ আরও দ্রুত শেষ হয়ে যেতে পারে। ব্যাকগ্রাউন্ডে ব্যাটারি ব্যবহার করা থেকে অ্যাপটিকে আর সীমাবদ্ধ করা হবে না।"</string>
@@ -3883,7 +3883,7 @@
<string name="condition_hotspot_title" msgid="4143299802283098506">"হটস্পট চালু আছে"</string>
<string name="condition_airplane_title" msgid="8484582712516148433">"বিমান মোড চালু করা আছে"</string>
<string name="condition_airplane_summary" msgid="3021193218494740742">"নেটওয়ার্ক উপলভ্য নেই"</string>
- <string name="condition_zen_title" msgid="2128184708916052585">"\'বিরক্ত করবেন না\' মোড চালু আছে"</string>
+ <string name="condition_zen_title" msgid="2128184708916052585">"\'বিরক্ত করবে না\' মোড চালু আছে"</string>
<string name="condition_zen_summary_phone_muted" msgid="4396050395522974654">"ফোন মিউট করা আছে"</string>
<string name="condition_zen_summary_with_exceptions" msgid="3435216391993785818">"ব্যতিক্রম সহ"</string>
<string name="condition_battery_title" msgid="6704870010912986274">"ব্যাটারি সেভার চালু আছে"</string>
@@ -4124,7 +4124,7 @@
<string name="ambient_display_pickup_summary" product="default" msgid="8798915340594367449">"সময়, বিজ্ঞপ্তি এবং অন্যান্য তথ্য দেখতে আপনার ফোনটি তুলে ধরুন।"</string>
<string name="ambient_display_pickup_summary" product="tablet" msgid="1077745287100012928">"সময়, বিজ্ঞপ্তি এবং অন্যান্য তথ্য দেখতে আপনার ট্যাবলেটটি তুলে ধরুন।"</string>
<string name="ambient_display_pickup_summary" product="device" msgid="404199660076598026">"সময়, বিজ্ঞপ্তি এবং অন্যান্য তথ্য দেখতে আপনার ডিভাইসটি তুলে ধরুন।"</string>
- <string name="ambient_display_tap_screen_title" product="default" msgid="2784322628239960695">"ফোন যাচাই করতে ট্যাপ করুন"</string>
+ <string name="ambient_display_tap_screen_title" product="default" msgid="2784322628239960695">"ফোন চেক করতে ট্যাপ করুন"</string>
<string name="ambient_display_tap_screen_title" product="tablet" msgid="6434521782016864148">"ট্যাবলেট যাচাই করতে ট্যাপ করুন"</string>
<string name="ambient_display_tap_screen_title" product="device" msgid="4396793721852647356">"ডিভাইস যাচাই করতে ট্যাপ করুন"</string>
<string name="ambient_display_tap_screen_summary" msgid="7869039870571925213">"সময়, বিজ্ঞপ্তি এবং অন্যান্য তথ্য দেখতে আপনার স্ক্রিনে ট্যাপ করুন।"</string>
@@ -4265,7 +4265,7 @@
<string name="storage_movies_tv" msgid="7282484273991655296">"সিনেমা ও টিভি অ্যাপ"</string>
<string name="carrier_provisioning" msgid="3309125279191534469">"পরিষেবা প্রদানকারীর ব্যবস্থামূলক তথ্য"</string>
<string name="trigger_carrier_provisioning" msgid="6284005970057901477">"ট্রিগার পরিষেবা প্রদানকারীর ব্যবস্থা"</string>
- <string name="zen_suggestion_title" msgid="2134699720214231950">"\'বিরক্ত করবেন না\' মোডটি আপডেট করুন"</string>
+ <string name="zen_suggestion_title" msgid="2134699720214231950">"\'বিরক্ত করবে না\' মোডটি আপডেট করুন"</string>
<string name="zen_suggestion_summary" msgid="4041062903237952737">"যাতে বিরক্ত হতে না হয় তার জন্য বিজ্ঞপ্তি পজ করুন"</string>
<string name="disabled_low_ram_device" msgid="4958060232123741721">"এই বৈশিষ্ট্যটি এই ডিভাইসে উপলব্ধ নেই"</string>
<string name="disabled_feature" msgid="3747549387387702365">"এই ফিচারটি উপলভ্য নেই"</string>
diff --git a/tests/CarDeveloperOptions/res/values-bs/strings.xml b/tests/CarDeveloperOptions/res/values-bs/strings.xml
index 09e47ec..90e21fd 100644
--- a/tests/CarDeveloperOptions/res/values-bs/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-bs/strings.xml
@@ -2180,7 +2180,7 @@
<string name="captioning_foreground_opacity" msgid="7635639017810117478">"Prozirnost teksta"</string>
<string name="captioning_edge_color" msgid="4330622137047993780">"Boja rubova"</string>
<string name="captioning_edge_type" msgid="4414946407430588162">"Vrsta rubova"</string>
- <string name="captioning_typeface" msgid="7893208796949341767">"Skup fontova"</string>
+ <string name="captioning_typeface" msgid="7893208796949341767">"Porodica fontova"</string>
<string name="captioning_preview_text" msgid="4877753964772618049">"Stilovi će izgledati ovako"</string>
<string name="captioning_preview_characters" msgid="6469599599352973561">"Aa"</string>
<string name="locale_default" msgid="910074908458214054">"Zadano"</string>
diff --git a/tests/CarDeveloperOptions/res/values-ca/strings.xml b/tests/CarDeveloperOptions/res/values-ca/strings.xml
index ecedea7..be89149 100644
--- a/tests/CarDeveloperOptions/res/values-ca/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-ca/strings.xml
@@ -355,7 +355,7 @@
<string name="owner_info_settings_title" msgid="2537966178998339896">"Missatge a la pantalla de bloqueig"</string>
<string name="security_enable_widgets_title" msgid="1701510007926738088">"Activa els widgets"</string>
<string name="security_enable_widgets_disabled_summary" msgid="4408176087132339331">"Desactivada per l\'administrador"</string>
- <string name="lockdown_settings_title" msgid="4534779922580115990">"Mostra l\'opció Bloqueig de seguretat"</string>
+ <string name="lockdown_settings_title" msgid="4534779922580115990">"Mostra l\'opció de bloqueig de seguretat"</string>
<string name="lockdown_settings_summary" msgid="7270756909878256174">"Mostra l\'opció del botó d\'engegada que desactiva Smart Lock, el desbloqueig amb l\'empremta digital i les notificacions a la pantalla de bloqueig"</string>
<string name="trust_agents_extend_unlock_title" msgid="3582017561316089951">"Desbloqueig ampliat per a agents de confiança"</string>
<string name="trust_agents_extend_unlock_summary" msgid="3543997596586078084">"Si s\'activa, els agents de confiança mantindran el dispositiu desbloquejat durant més temps, però ja no podran desbloquejar un dispositiu bloquejat."</string>
@@ -1554,7 +1554,7 @@
<string name="menu_cancel" msgid="1292949233623397786">"Descarta"</string>
<string name="error_title" msgid="6595678722641187629"></string>
<string name="error_name_empty" msgid="4638536651499727722">"El camp Nom no pot ser buit."</string>
- <string name="error_apn_empty" msgid="4849569239327147849">"L\'APN no pot estar buit."</string>
+ <string name="error_apn_empty" msgid="4849569239327147849">"L\'APN no pot ser buit."</string>
<string name="error_mcc_not3" msgid="1333037488064427164">"El camp MCC ha de tenir 3 dígits."</string>
<string name="error_mnc_not23" msgid="6738398924368729180">"El camp MNC ha de tenir 2 o 3 dígits."</string>
<string name="error_adding_apn_type" msgid="671634520340569678">"L\'operador no permet afegir APN de tipus %s."</string>
@@ -2499,7 +2499,7 @@
<string name="voice_input_settings" msgid="4983011614890521505">"Configuració de l\'entrada de veu"</string>
<string name="voice_input_settings_title" msgid="6865032806501269306">"Entrada de veu"</string>
<string name="voice_service_preference_section_title" msgid="2984112696100778038">"Serveis d\'entrada de veu"</string>
- <string name="voice_interactor_preference_summary" msgid="7321365727286121067">"Paraula activa i interacció completes"</string>
+ <string name="voice_interactor_preference_summary" msgid="7321365727286121067">"Paraula d\'activació i interacció completes"</string>
<string name="voice_recognizer_preference_summary" msgid="3681161319745912594">"Conversió de parla a text simple"</string>
<string name="voice_interaction_security_warning" msgid="4986261746316889768">"Aquest servei d\'entrada de veu podrà supervisar sempre la veu i controlar les aplicacions compatibles amb l\'entrada de veu en nom teu. Procedeix de l\'aplicació <xliff:g id="VOICE_INPUT_SERVICE_APP_NAME">%s</xliff:g>. Vols activar l\'ús d\'aquest servei?"</string>
<string name="tts_engine_preference_title" msgid="1183116842356275061">"Motor preferent"</string>
@@ -2547,7 +2547,7 @@
<string name="backup_data_title" msgid="4461508563849583624">"Còpia de seguretat de les meves dades"</string>
<string name="backup_data_summary" msgid="555459891017933746">"Fes una còpia de seguretat als servidors de Google de dades d\'aplicacions, contrasenyes Wi-Fi i altres opcions de configuració"</string>
<string name="backup_configure_account_title" msgid="1534734650559070294">"Compte de còpia de seguretat"</string>
- <string name="backup_data_management_title" msgid="6299288795610243508">"Gestiona el compte per a la còpia de seguretat"</string>
+ <string name="backup_data_management_title" msgid="6299288795610243508">"Gestiona el compte de còpia de seguretat"</string>
<string name="include_app_data_title" msgid="6117211611131913293">"Inclou dades de l\'aplicació"</string>
<string name="auto_restore_title" msgid="8367486774010915221">"Restauració automàtica"</string>
<string name="auto_restore_summary" msgid="1941047568966428377">"Quan tornis a instal·lar una aplicació, restaura la configuració i les dades incloses a la còpia de seguretat"</string>
@@ -3581,7 +3581,7 @@
<string name="imei_information_title" msgid="7666097743700170757">"Informació sobre l\'IMEI"</string>
<string name="imei_information_summary" msgid="716516316022275083">"Informació relativa a l\'IMEI"</string>
<string name="slot_number" msgid="785422579177068698">"(Ranura <xliff:g id="SLOT_NUM">%1$d</xliff:g>)"</string>
- <string name="launch_by_default" msgid="6106985160202769725">"Obre de manera determinada"</string>
+ <string name="launch_by_default" msgid="6106985160202769725">"Obre de manera predeterminada"</string>
<string name="app_launch_domain_links_title" msgid="2987289657348349133">"Obertura d\'enllaços"</string>
<string name="app_launch_open_domain_urls_title" msgid="8595126859922391331">"Obrir els enllaços admesos"</string>
<string name="app_launch_open_domain_urls_summary" msgid="6803029846855502366">"Obre sense demanar-ho"</string>
diff --git a/tests/CarDeveloperOptions/res/values-cs/strings.xml b/tests/CarDeveloperOptions/res/values-cs/strings.xml
index ed2c4c7..5997f98 100644
--- a/tests/CarDeveloperOptions/res/values-cs/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-cs/strings.xml
@@ -389,7 +389,7 @@
<string name="decryption_settings_summary" product="default" msgid="7401802133199522441">"Telefon není šifrován"</string>
<string name="encryption_and_credential_settings_summary" product="tablet" msgid="8170667308598998791">"Zařízení je zašifrováno"</string>
<string name="decryption_settings_summary" product="tablet" msgid="7524119945312453569">"Zařízení není šifrováno"</string>
- <string name="lockscreen_settings_title" msgid="1221505938891948413">"Zobrazení na obrazovce uzamčení"</string>
+ <string name="lockscreen_settings_title" msgid="1221505938891948413">"Displej zámku obrazovky"</string>
<string name="lockscreen_settings_what_to_show_category" msgid="3133378945821488654">"Co zobrazit"</string>
<string name="security_settings_summary" msgid="5210109100643223686">"Moje poloha, odemknutí obrazovky, zámek SIM, zámek úložiště pověření"</string>
<string name="cdma_security_settings_summary" msgid="1783066617800041869">"Nastavení funkce Moje poloha, odemknutí obrazovky a zamknutí úložiště pověření"</string>
@@ -4488,7 +4488,7 @@
<string name="empty_networks_list" msgid="5170020017144403884">"Žádná síť nebyla nalezena."</string>
<string name="network_query_error" msgid="525635151099480463">"Nebyla nalezena žádná síť. Zkuste to znovu."</string>
<string name="forbidden_network" msgid="8493827960968261182">"(zakázáno)"</string>
- <string name="no_sim_card" msgid="3708682108324275635">"Není vložena SIM karta"</string>
+ <string name="no_sim_card" msgid="3708682108324275635">"Chybí SIM karta"</string>
<string name="preferred_network_mode_wcdma_perf_summary" msgid="6899270534608086704">"Preferovaný režim sítě: preferováno WCDMA"</string>
<string name="preferred_network_mode_gsm_only_summary" msgid="3688217977701592962">"Preferovaný režim sítě: pouze GSM"</string>
<string name="preferred_network_mode_wcdma_only_summary" msgid="745707973728245943">"Preferovaný režim sítě: pouze WCDMA"</string>
diff --git a/tests/CarDeveloperOptions/res/values-da/strings.xml b/tests/CarDeveloperOptions/res/values-da/strings.xml
index a2c527a..d13df6f 100644
--- a/tests/CarDeveloperOptions/res/values-da/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-da/strings.xml
@@ -3039,7 +3039,7 @@
<string name="account_dashboard_title" msgid="4734300939532555885">"Konti"</string>
<string name="account_dashboard_default_summary" msgid="6822549669771936206">"Ingen konti er tilføjet"</string>
<string name="app_default_dashboard_title" msgid="6575301028225232193">"Standardapps"</string>
- <string name="system_dashboard_summary" msgid="6582464466735779394">"Sprog, bevægelser, klokkeslæt, bckup"</string>
+ <string name="system_dashboard_summary" msgid="6582464466735779394">"Sprog, bevægelser, klokkeslæt, backup"</string>
<string name="search_results_title" msgid="4160717656435503940">"Indstillinger"</string>
<string name="keywords_wifi" msgid="8477688080895466846">"wifi, wi-fi, netværksforbindelse, internet, trådløs, data, wi fi"</string>
<string name="keywords_wifi_notify_open_networks" msgid="1031260564121854773">"Wi‑Fi-notifikation, wifi-notifikation"</string>
diff --git a/tests/CarDeveloperOptions/res/values-es-rUS/strings.xml b/tests/CarDeveloperOptions/res/values-es-rUS/strings.xml
index 5d1d4a9..cad68f6 100644
--- a/tests/CarDeveloperOptions/res/values-es-rUS/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-es-rUS/strings.xml
@@ -4122,7 +4122,7 @@
<string name="ambient_display_pickup_summary" product="default" msgid="8798915340594367449">"Para consultar la hora, las notificaciones y otra información, levanta el teléfono."</string>
<string name="ambient_display_pickup_summary" product="tablet" msgid="1077745287100012928">"Para consultar la hora, las notificaciones y otra información, levanta la tablet."</string>
<string name="ambient_display_pickup_summary" product="device" msgid="404199660076598026">"Para consultar la hora, las notificaciones y otra información, levanta el dispositivo."</string>
- <string name="ambient_display_tap_screen_title" product="default" msgid="2784322628239960695">"Presiona para revisar el teléfono"</string>
+ <string name="ambient_display_tap_screen_title" product="default" msgid="2784322628239960695">"Presionar para revisar el teléfono"</string>
<string name="ambient_display_tap_screen_title" product="tablet" msgid="6434521782016864148">"Presiona para revisar la tablet"</string>
<string name="ambient_display_tap_screen_title" product="device" msgid="4396793721852647356">"Presiona para revisar el dispositivo"</string>
<string name="ambient_display_tap_screen_summary" msgid="7869039870571925213">"Para consultar la hora, las notificaciones y otra información, presiona la pantalla."</string>
diff --git a/tests/CarDeveloperOptions/res/values-es/strings.xml b/tests/CarDeveloperOptions/res/values-es/strings.xml
index 13f8221..8f0ec45 100644
--- a/tests/CarDeveloperOptions/res/values-es/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-es/strings.xml
@@ -1178,7 +1178,7 @@
<string name="brightness" msgid="7309120144111305275">"Nivel de brillo"</string>
<string name="brightness_title" msgid="5660190946911149690">"Brillo"</string>
<string name="brightness_summary" msgid="8687101964451818730">"Ajustar el brillo de la pantalla"</string>
- <string name="auto_brightness_title" msgid="908511534369820426">"Brillo automático"</string>
+ <string name="auto_brightness_title" msgid="908511534369820426">"Brillo adaptativo"</string>
<string name="auto_brightness_summary_on" msgid="121488862610275737">"Activado"</string>
<string name="auto_brightness_summary_off" msgid="8569141123211510256">"Desactivado"</string>
<string name="auto_brightness_summary_very_low" msgid="7625647285740629347">"El brillo preferido es muy bajo"</string>
@@ -1196,7 +1196,7 @@
<string name="auto_brightness_off_summary" msgid="6162650416289359104">"No ajustar en función de la luz ambiental"</string>
<string name="auto_brightness_very_high_summary" msgid="7202032980509583918">"Aumenta el uso de la batería"</string>
<string name="auto_brightness_disclaimer" msgid="5416696351199148809">"Optimiza el brillo en función de la luz ambiental. Puedes ajustarlo temporalmente aunque actives esta función."</string>
- <string name="auto_brightness_description" msgid="8209140379089535411">"El brillo de la pantalla se ajustará automáticamente según el entorno y las actividades que hagas. Puedes mover el control deslizante para que la función de brillo adaptable reconozca tus preferencias."</string>
+ <string name="auto_brightness_description" msgid="8209140379089535411">"El brillo de la pantalla se ajustará automáticamente según el entorno y las actividades que hagas. Puedes mover el control deslizante para que la función de brillo adaptativo reconozca tus preferencias."</string>
<string name="display_white_balance_title" msgid="5747260735311935143">"Balance de blancos de pantalla"</string>
<string name="adaptive_sleep_title" msgid="3237620948260957018">"Modo privado"</string>
<string name="adaptive_sleep_summary_on" msgid="6670369739228487082">"Activado: la pantalla no se apagará si estás mirándola"</string>
@@ -4071,7 +4071,7 @@
<string name="dark_ui_mode_title" msgid="8774932716427742413">"Seleccionar tema"</string>
<string name="dark_ui_settings_light_summary" msgid="5219102347744462812">"Esta configuración también se utiliza para las aplicaciones"</string>
<string name="dark_ui_settings_dark_summary" msgid="7042737828943784289">"Las aplicaciones que lo admitan también se cambiarán al tema oscuro"</string>
- <string name="quick_settings_developer_tiles" msgid="7423485925757678719">"Iconos para desarrolladores en Ajustes rápidos"</string>
+ <string name="quick_settings_developer_tiles" msgid="7423485925757678719">"Iconos para desarrolladores en ajustes rápidos"</string>
<string name="winscope_trace_quick_settings_title" msgid="940971040388411374">"Rastro de Winscope"</string>
<string name="sensors_off_quick_settings_title" msgid="3655699045300438902">"Sensores desactivados"</string>
<string name="managed_profile_settings_title" msgid="4340409321523532402">"Ajustes de perfil de trabajo"</string>
diff --git a/tests/CarDeveloperOptions/res/values-eu/strings.xml b/tests/CarDeveloperOptions/res/values-eu/strings.xml
index 00ebec3..6a242b6 100644
--- a/tests/CarDeveloperOptions/res/values-eu/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-eu/strings.xml
@@ -531,11 +531,11 @@
<string name="crypt_keeper_warn_wipe" msgid="700814581500057050">"Abisua: desblokeatzeko beste <xliff:g id="COUNT">^1</xliff:g> saiakera oker egiten badituzu, gailuko datu guztiak ezabatuko dira!"</string>
<string name="crypt_keeper_enter_password" msgid="726933635335219421">"Idatzi pasahitza"</string>
<string name="crypt_keeper_failed_title" msgid="1906382607060855782">"Ezin izan da enkriptatu"</string>
- <string name="crypt_keeper_failed_summary" product="tablet" msgid="7844833877734529625">"Enkriptatzea eten da eta ezin da osatu. Ondorioz, ezin izango dituzu tabletako datuak atzitu.\n\nTableta erabiltzen jarraitzeko, jatorrizko datuak berrezarri behar dituzu. Datuak berrezarri ondoren tableta konfiguratzen duzunean, Google kontuan gordetako babeskopiaren datuak leheneratu ahal izango dituzu."</string>
- <string name="crypt_keeper_failed_summary" product="default" msgid="2895589681839090312">"Enkriptatzea eten da eta ezin da osatu. Ondorioz, ezin izango dituzu telefonoko datuak atzitu.\n\nTelefonoa erabiltzen jarraitzeko, jatorrizko datuak berrezarri behar dituzu. Datuak berrezarri ondoren telefonoa konfiguratzen duzunean, Google kontuan gordetako babeskopien datuak leheneratu ahal izango dituzu."</string>
+ <string name="crypt_keeper_failed_summary" product="tablet" msgid="7844833877734529625">"Enkriptatzea eten da eta ezin da osatu. Ondorioz, ezin izango dituzu tabletako datuak atzitu.\n\nTableta erabiltzen jarraitzeko, jatorrizko datuak berrezarri behar dituzu. Datuak berrezarri ondoren tableta konfiguratzen duzunean, Google-ko kontuan gordetako babeskopiaren datuak leheneratu ahal izango dituzu."</string>
+ <string name="crypt_keeper_failed_summary" product="default" msgid="2895589681839090312">"Enkriptatzea eten da eta ezin da osatu. Ondorioz, ezin izango dituzu telefonoko datuak atzitu.\n\nTelefonoa erabiltzen jarraitzeko, jatorrizko datuak berrezarri behar dituzu. Datuak berrezarri ondoren telefonoa konfiguratzen duzunean, Google-ko kontuan gordetako babeskopien datuak leheneratu ahal izango dituzu."</string>
<string name="crypt_keeper_data_corrupt_title" msgid="6561535293845985713">"Ezin izan da desenkriptatu"</string>
- <string name="crypt_keeper_data_corrupt_summary" product="tablet" msgid="7018748502706237323">"Idatzi duzun pasahitza zuzena da, baina datuak hondatuta daude. \n\nTableta erabiltzen jarraitzeko, jatorrizko datuak berrezarri beharko dituzu. Berrezarri ondoren, tableta konfiguratzen duzunean, Google kontuan egindako babeskopiak leheneratu ahal izango dituzu."</string>
- <string name="crypt_keeper_data_corrupt_summary" product="default" msgid="5798580588985326937">"Idatzi duzun pasahitza zuzena da, baina datuak hondatuta daude. \n\nTelefonoa erabiltzen jarraitzeko, jatorrizko datuak berrezarri beharko dituzu. Berrezarri ondoren, telefonoa konfiguratzen duzunean, Google kontuan egindako babeskopiak leheneratu ahal izango dituzu."</string>
+ <string name="crypt_keeper_data_corrupt_summary" product="tablet" msgid="7018748502706237323">"Idatzi duzun pasahitza zuzena da, baina datuak hondatuta daude. \n\nTableta erabiltzen jarraitzeko, jatorrizko datuak berrezarri beharko dituzu. Berrezarri ondoren, tableta konfiguratzen duzunean, Google-ko kontuan egindako babeskopiak leheneratu ahal izango dituzu."</string>
+ <string name="crypt_keeper_data_corrupt_summary" product="default" msgid="5798580588985326937">"Idatzi duzun pasahitza zuzena da, baina datuak hondatuta daude. \n\nTelefonoa erabiltzen jarraitzeko, jatorrizko datuak berrezarri beharko dituzu. Berrezarri ondoren, telefonoa konfiguratzen duzunean, Google-ko kontuan egindako babeskopiak leheneratu ahal izango dituzu."</string>
<string name="crypt_keeper_switch_input_method" msgid="4744137470890459582">"Aldatu idazketa-metodoa"</string>
<string name="suggested_lock_settings_title" msgid="1518155558803371661">"Babestu telefonoa"</string>
<string name="suggested_lock_settings_summary" product="tablet" msgid="1861066918594412519">"Ezarri pantailaren blokeoa tableta babesteko"</string>
@@ -1399,7 +1399,7 @@
<string name="sd_ejecting_title" msgid="595074246815112145">"Desmuntatzen"</string>
<string name="sd_ejecting_summary" msgid="5708943172014003213">"Desmuntatzea abian da"</string>
<string name="storage_low_title" msgid="6957178208426099592">"Memoria agortzen ari da"</string>
- <string name="storage_low_summary" msgid="4475275204869514141">"Baliteke sistemaren funtzio batzuk behar bezala ez funtzionatzea, esaterako, sinkronizazioa. Saiatu memorian tokia egiten elementu batzuk ezabatuta edo desainguratuta, adibidez, aplikazioak edo multimedia-edukia."</string>
+ <string name="storage_low_summary" msgid="4475275204869514141">"Baliteke sistemaren funtzio batzuek behar bezala ez funtzionatzea; esaterako, sinkronizazioak. Memorian tokia egiteko, ezabatu elementu batzuk (adibidez, aplikazioak edo multimedia-edukia) edo ken iezaiezu aingura."</string>
<string name="storage_menu_rename" msgid="3731682449294417745">"Aldatu izena"</string>
<string name="storage_menu_mount" msgid="6395893560780365473">"Muntatu"</string>
<string name="storage_menu_unmount" msgid="5041360076873514189">"Atera"</string>
@@ -2546,7 +2546,7 @@
<string name="personal_data_section_title" msgid="9161854418510071558">"Datu pertsonalak"</string>
<string name="backup_data_title" msgid="4461508563849583624">"Egin nire datuen babeskopia"</string>
<string name="backup_data_summary" msgid="555459891017933746">"Egin datuen, Wi-Fi pasahitzen eta beste ezarpenen babeskopia Google zerbitzarietan."</string>
- <string name="backup_configure_account_title" msgid="1534734650559070294">"Babeskopien kontua"</string>
+ <string name="backup_configure_account_title" msgid="1534734650559070294">"Babesk. gordetzeko kontua"</string>
<string name="backup_data_management_title" msgid="6299288795610243508">"Kudeatu babeskopiak gordetzeko kontua"</string>
<string name="include_app_data_title" msgid="6117211611131913293">"Sartu aplikazioetako datuak"</string>
<string name="auto_restore_title" msgid="8367486774010915221">"Leheneratze automatikoa"</string>
@@ -2697,8 +2697,8 @@
<string name="data_usage_app_restrict_dialog" msgid="4022530391896478031">"Eginbide horren eraginez, baliteke atzeko planoko datuak beharrezko dituzten aplikazioek funtzionatzeari uztea, sare mugikorrak baino ez badaude erabilgarri.\n\n Datuak behar bezala erabiltzeko kontrol gehiago dituzu aplikazioaren barruko ezarpenetan."</string>
<string name="data_usage_restrict_denied_dialog" msgid="18928292832775805">"Atzeko planoko datuak murrizteko, datu-konexioarekin erabil daitezkeen datuak mugatu behar dituzu."</string>
<string name="data_usage_auto_sync_on_dialog_title" msgid="2342323408229702005">"Sinkronizazio automatikoa aktibatu?"</string>
- <string name="data_usage_auto_sync_on_dialog" product="tablet" msgid="4935430284683238901">"Kontuei sarean egiten dizkiezun aldaketa guztiak automatikoki kopiatuko dira tabletan.\n\nHorrez gain, baliteke kontu batzuek tabletan egiten dituzun aldaketak sarean kopiatzea. Google kontuek horrela funtzionatzen dute."</string>
- <string name="data_usage_auto_sync_on_dialog" product="default" msgid="5004823486046340090">"Kontuei sarean egiten dizkiezun aldaketa guztiak automatikoki kopiatuko dira telefonoan.\n\nHorrez gain, baliteke kontu batzuek telefonoan egiten dituzun aldaketak sarean kopiatzea. Google kontuek horrela funtzionatzen dute."</string>
+ <string name="data_usage_auto_sync_on_dialog" product="tablet" msgid="4935430284683238901">"Kontuei sarean egiten dizkiezun aldaketa guztiak automatikoki kopiatuko dira tabletan.\n\nHorrez gain, baliteke kontu batzuek tabletan egiten dituzun aldaketak sarean kopiatzea. Google-ko kontuek horrela funtzionatzen dute."</string>
+ <string name="data_usage_auto_sync_on_dialog" product="default" msgid="5004823486046340090">"Kontuei sarean egiten dizkiezun aldaketa guztiak automatikoki kopiatuko dira telefonoan.\n\nHorrez gain, baliteke kontu batzuek telefonoan egiten dituzun aldaketak sarean kopiatzea. Google-ko kontuek horrela funtzionatzen dute."</string>
<string name="data_usage_auto_sync_off_dialog_title" msgid="7105334544291643305">"Sinkronizazio automatikoa desaktibatu?"</string>
<string name="data_usage_auto_sync_off_dialog" msgid="4057984234450947964">"Datuak eta bateria aurrezten lagunduko dizu, baina kontu bakoitza eskuz sinkronizatu beharko duzu informazio berriena biltzeko. Gainera, ez duzu berritasunen jakinarazpenik jasoko."</string>
<string name="data_usage_cycle_editor_title" msgid="4967309390043599889">"Erabilera-zikloa berrezartzeko data"</string>
@@ -4113,18 +4113,18 @@
<string name="swipe_up_to_switch_apps_summary" msgid="4644068184114154787">"Aplikazioa aldatzeko, pasatu hatza gora Hasiera botoian, eta pasa ezazu berriro aplikazio guztiak ikusteko. Edozein pantailatan funtzionatzen du. Ikuspegi orokorraren botoia ez da egongo pantailaren behealdean eskuinetara."</string>
<string name="swipe_up_to_switch_apps_suggestion_title" msgid="7641846365137536128">"Probatu Hasiera botoi berria"</string>
<string name="swipe_up_to_switch_apps_suggestion_summary" msgid="7338653224520387852">"Aktibatu aplikazioa aldatzeko keinu berria"</string>
- <string name="ambient_display_title" product="default" msgid="6785677099744344088">"Sakatu birritan telefonoa bertan dagoena ikusteko"</string>
+ <string name="ambient_display_title" product="default" msgid="6785677099744344088">"Sakatu birritan telefonoa pantailako informazioa ikusteko"</string>
<string name="ambient_display_title" product="tablet" msgid="1106285490888683613">"Sakatu birritan tableta bertan dagoela ikusteko"</string>
<string name="ambient_display_title" product="device" msgid="5064644474876041478">"Sakatu birritan gailua bertan dagoela ikusteko"</string>
<string name="ambient_display_summary" msgid="4882910328216411109">"Ordua, jakinarazpenak eta bestelako informazioa ikusteko, sakatu pantaila birritan."</string>
- <string name="ambient_display_pickup_title" product="default" msgid="7141652156907066938">"Jaso telefonoa bertan dagoena ikusteko"</string>
+ <string name="ambient_display_pickup_title" product="default" msgid="7141652156907066938">"Jaso telefonoa pantailako informazioa ikusteko"</string>
<string name="ambient_display_pickup_title" product="tablet" msgid="1555456400210301959">"Jaso tableta bertan dagoela ikusteko"</string>
<string name="ambient_display_pickup_title" product="device" msgid="2480126522988135037">"Jaso gailua bertan dagoela ikusteko"</string>
<string name="ambient_display_wake_screen_title" msgid="3376988352851077102">"Esnarazi pantaila"</string>
<string name="ambient_display_pickup_summary" product="default" msgid="8798915340594367449">"Ordua, jakinarazpenak eta bestelako informazioa ikusteko, hartu telefonoa."</string>
<string name="ambient_display_pickup_summary" product="tablet" msgid="1077745287100012928">"Ordua, jakinarazpenak eta bestelako informazioa ikusteko, hartu tableta."</string>
<string name="ambient_display_pickup_summary" product="device" msgid="404199660076598026">"Ordua, jakinarazpenak eta bestelako informazioa ikusteko, hartu gailua."</string>
- <string name="ambient_display_tap_screen_title" product="default" msgid="2784322628239960695">"Sakatu telefonoa egiaztatzeko"</string>
+ <string name="ambient_display_tap_screen_title" product="default" msgid="2784322628239960695">"Sakatu telefonoa pantailako informazioa ikusteko"</string>
<string name="ambient_display_tap_screen_title" product="tablet" msgid="6434521782016864148">"Sakatu tableta egiaztatzeko"</string>
<string name="ambient_display_tap_screen_title" product="device" msgid="4396793721852647356">"Sakatu gailua egiaztatzeko"</string>
<string name="ambient_display_tap_screen_summary" msgid="7869039870571925213">"Ordua, jakinarazpenak eta bestelako informazioa ikusteko, sakatu pantaila."</string>
diff --git a/tests/CarDeveloperOptions/res/values-fa/strings.xml b/tests/CarDeveloperOptions/res/values-fa/strings.xml
index 44c80f4..31030ad 100644
--- a/tests/CarDeveloperOptions/res/values-fa/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-fa/strings.xml
@@ -4117,7 +4117,7 @@
<string name="ambient_display_title" product="tablet" msgid="1106285490888683613">"برای بررسی رایانه لوحی، دو ضربه سریع بزنید"</string>
<string name="ambient_display_title" product="device" msgid="5064644474876041478">"برای بررسی دستگاه، دو ضربه سریع بزنید"</string>
<string name="ambient_display_summary" msgid="4882910328216411109">"برای بررسی زمان، اعلانها و اطلاعات دیگر، روی صفحهنمایش دو ضربه سریع بزنید."</string>
- <string name="ambient_display_pickup_title" product="default" msgid="7141652156907066938">"برای بررسی تلفن، آن را بردارید"</string>
+ <string name="ambient_display_pickup_title" product="default" msgid="7141652156907066938">"بررسی تلفن با برداشتن"</string>
<string name="ambient_display_pickup_title" product="tablet" msgid="1555456400210301959">"برای بررسی رایانه لوحی، آن را بردارید"</string>
<string name="ambient_display_pickup_title" product="device" msgid="2480126522988135037">"برای بررسی دستگاه، آن را بردارید"</string>
<string name="ambient_display_wake_screen_title" msgid="3376988352851077102">"روشن کردن نمایشگر"</string>
diff --git a/tests/CarDeveloperOptions/res/values-fr-rCA/strings.xml b/tests/CarDeveloperOptions/res/values-fr-rCA/strings.xml
index eb6583a..80040cc 100644
--- a/tests/CarDeveloperOptions/res/values-fr-rCA/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-fr-rCA/strings.xml
@@ -4122,8 +4122,8 @@
<string name="ambient_display_pickup_title" product="device" msgid="2480126522988135037">"Saisissez l\'appareil pour consulter les notifications"</string>
<string name="ambient_display_wake_screen_title" msgid="3376988352851077102">"Réactiver l\'écran"</string>
<string name="ambient_display_pickup_summary" product="default" msgid="8798915340594367449">"Pour vérifier l\'heure, vos notifications et d\'autres renseignements, saisir votre téléphone."</string>
- <string name="ambient_display_pickup_summary" product="tablet" msgid="1077745287100012928">"Pour vérifier l\'heure, vos notifications et d\'autres renseignements, saisissez votre tablette."</string>
- <string name="ambient_display_pickup_summary" product="device" msgid="404199660076598026">"Pour vérifier l\'heure, vos notifications et d\'autres renseignements, saisissez votre appareil."</string>
+ <string name="ambient_display_pickup_summary" product="tablet" msgid="1077745287100012928">"Pour vérifier l\'heure, vos notifications et d\'autres renseignements, saisir votre tablette."</string>
+ <string name="ambient_display_pickup_summary" product="device" msgid="404199660076598026">"Pour vérifier l\'heure, vos notifications et d\'autres renseignements, saisir votre appareil."</string>
<string name="ambient_display_tap_screen_title" product="default" msgid="2784322628239960695">"Toucher pour vérifier le téléphone"</string>
<string name="ambient_display_tap_screen_title" product="tablet" msgid="6434521782016864148">"Toucher pour vérifier la tablette"</string>
<string name="ambient_display_tap_screen_title" product="device" msgid="4396793721852647356">"Toucher pour vérifier l\'appareil"</string>
diff --git a/tests/CarDeveloperOptions/res/values-fr/strings.xml b/tests/CarDeveloperOptions/res/values-fr/strings.xml
index 8217c49..2fd84c4 100644
--- a/tests/CarDeveloperOptions/res/values-fr/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-fr/strings.xml
@@ -1256,7 +1256,7 @@
<string name="ambient_display_category_triggers" msgid="3496111745340047504">"Activation du mode Veille"</string>
<string name="doze_title" msgid="235269029233857546">"Nouvelles notifications"</string>
<string name="doze_summary" msgid="6762274282827831706">"Activer l\'écran lors de la réception de notifications"</string>
- <string name="doze_always_on_title" msgid="8555184965031789941">"Toujours activé"</string>
+ <string name="doze_always_on_title" msgid="8555184965031789941">"Mode Always-on"</string>
<string name="doze_always_on_summary" msgid="7654436900436328950">"Afficher l\'heure, les icônes de notification et d\'autres informations. Batterie davantage sollicitée."</string>
<string name="title_font_size" msgid="5021464556860010851">"Taille de la police"</string>
<string name="short_summary_font_size" msgid="4141077908728522946">"Agrandir ou réduire le texte"</string>
@@ -2056,7 +2056,7 @@
<string name="accessibility_screen_magnification_navbar_configuration_warning" msgid="6477234309484795550">"Le bouton Accessibilité est défini sur <xliff:g id="SERVICE">%1$s</xliff:g>. Pour utiliser la loupe, appuyez de manière prolongée sur le bouton Accessibilité, puis sélectionnez la loupe."</string>
<string name="accessibility_global_gesture_preference_title" msgid="3842279082831426816">"Raccourci (volume)"</string>
<string name="accessibility_shortcut_service_title" msgid="3516052294376744060">"Service associé au raccourci"</string>
- <string name="accessibility_shortcut_service_on_lock_screen_title" msgid="1279441617927949980">"Autoriser depuis écran verrouillage"</string>
+ <string name="accessibility_shortcut_service_on_lock_screen_title" msgid="1279441617927949980">"Autoriser depuis l\'écran verrouillé"</string>
<string name="accessibility_shortcut_description" msgid="1427049334225166395">"Lorsque le raccourci est activé, vous pouvez appuyer sur les deux touches de volume pendant trois secondes pour lancer une fonctionnalité d\'accessibilité."</string>
<string name="accessibility_toggle_high_text_contrast_preference_title" msgid="5652244684961877255">"Texte avec contraste élevé"</string>
<string name="accessibility_toggle_screen_magnification_auto_update_preference_title" msgid="2466317284195934003">"Mise à jour auto de la loupe"</string>
diff --git a/tests/CarDeveloperOptions/res/values-gl/strings.xml b/tests/CarDeveloperOptions/res/values-gl/strings.xml
index 39c99aa..a025faa 100644
--- a/tests/CarDeveloperOptions/res/values-gl/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-gl/strings.xml
@@ -2546,8 +2546,8 @@
<string name="personal_data_section_title" msgid="9161854418510071558">"Datos persoais"</string>
<string name="backup_data_title" msgid="4461508563849583624">"Realizar copia de seguranza dos meus datos"</string>
<string name="backup_data_summary" msgid="555459891017933746">"Crea unha copia de seguranza dos datos da aplicación, dos contrasinais das redes wifi e doutras configuracións en servidores de Google"</string>
- <string name="backup_configure_account_title" msgid="1534734650559070294">"Conta de copia seguranza"</string>
- <string name="backup_data_management_title" msgid="6299288795610243508">"Xestionar conta de copia de seguranza"</string>
+ <string name="backup_configure_account_title" msgid="1534734650559070294">"Copia de seguranza: conta"</string>
+ <string name="backup_data_management_title" msgid="6299288795610243508">"Xestionar conta para a copia de seguranza"</string>
<string name="include_app_data_title" msgid="6117211611131913293">"Incluír datos de aplicacións"</string>
<string name="auto_restore_title" msgid="8367486774010915221">"Restauración automática"</string>
<string name="auto_restore_summary" msgid="1941047568966428377">"Cando volvas instalar unha aplicación, restaura a configuración e os datos dos que fixeches unha copia de seguranza"</string>
@@ -4114,18 +4114,18 @@
<string name="swipe_up_to_switch_apps_summary" msgid="4644068184114154787">"Para cambiar de aplicacións, pasa o dedo cara arriba no botón de inicio. Pásao de novo para ver todas as aplicacións. Este xesto funciona en calquera pantalla, así que deixarás de ter na parte inferior dereita o botón Visión xeral."</string>
<string name="swipe_up_to_switch_apps_suggestion_title" msgid="7641846365137536128">"Proba o novo botón de inicio"</string>
<string name="swipe_up_to_switch_apps_suggestion_summary" msgid="7338653224520387852">"Activa o novo xesto para cambiar de aplicacións"</string>
- <string name="ambient_display_title" product="default" msgid="6785677099744344088">"Dobre toque para consultar o teléfono"</string>
+ <string name="ambient_display_title" product="default" msgid="6785677099744344088">"Dobre toque no teléfono para consultalo"</string>
<string name="ambient_display_title" product="tablet" msgid="1106285490888683613">"Tocar dúas veces para consultar a tableta"</string>
<string name="ambient_display_title" product="device" msgid="5064644474876041478">"Tocar dúas veces para consultar o dispositivo"</string>
<string name="ambient_display_summary" msgid="4882910328216411109">"Para consultar a hora, as notificacións e outra información, toca a pantalla dúas veces."</string>
- <string name="ambient_display_pickup_title" product="default" msgid="7141652156907066938">"Levantar teléfono para consultalo"</string>
+ <string name="ambient_display_pickup_title" product="default" msgid="7141652156907066938">"Levantar o teléfono para consultalo"</string>
<string name="ambient_display_pickup_title" product="tablet" msgid="1555456400210301959">"Levantar a tableta para consultala"</string>
<string name="ambient_display_pickup_title" product="device" msgid="2480126522988135037">"Levantar o dispositivo para consultalo"</string>
<string name="ambient_display_wake_screen_title" msgid="3376988352851077102">"Activar a pantalla de bloqueo"</string>
<string name="ambient_display_pickup_summary" product="default" msgid="8798915340594367449">"Para consultar a hora, as notificacións e outros datos, colle o teléfono."</string>
<string name="ambient_display_pickup_summary" product="tablet" msgid="1077745287100012928">"Para consultar a hora, as notificacións e outros datos, colle a tableta."</string>
<string name="ambient_display_pickup_summary" product="device" msgid="404199660076598026">"Para consultar a hora, as notificacións e outros datos, colle o dispositivo."</string>
- <string name="ambient_display_tap_screen_title" product="default" msgid="2784322628239960695">"Tocar para consultar o teléfono"</string>
+ <string name="ambient_display_tap_screen_title" product="default" msgid="2784322628239960695">"Toque no teléfono para consultalo"</string>
<string name="ambient_display_tap_screen_title" product="tablet" msgid="6434521782016864148">"Toca para consultar a tableta"</string>
<string name="ambient_display_tap_screen_title" product="device" msgid="4396793721852647356">"Tocar para consultar o dispositivo"</string>
<string name="ambient_display_tap_screen_summary" msgid="7869039870571925213">"Para consultar a hora, as notificacións e outra información, toca a pantalla."</string>
diff --git a/tests/CarDeveloperOptions/res/values-hi/arrays.xml b/tests/CarDeveloperOptions/res/values-hi/arrays.xml
index 2aa2a7b..f88282e 100644
--- a/tests/CarDeveloperOptions/res/values-hi/arrays.xml
+++ b/tests/CarDeveloperOptions/res/values-hi/arrays.xml
@@ -56,7 +56,7 @@
<item msgid="6816207058895999545">"स्कैन कर रहा है…"</item>
<item msgid="8058143476674427024">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> से कनेक्ट कर रहा है…"</item>
<item msgid="7547609081339573756">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> के साथ प्रमाणीकरण कर रहा है…"</item>
- <item msgid="5145158315060185414">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> से IP पता प्राप्त कर रहा है..."</item>
+ <item msgid="5145158315060185414">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> से IP पता पा रहा है..."</item>
<item msgid="3283243151651124831">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> से कनेक्ट किया गया"</item>
<item msgid="6600156231416890902">"निलंबित"</item>
<item msgid="4133290864821295785">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> से डिस्कनेक्ट कर रहा है…"</item>
@@ -173,7 +173,7 @@
<item msgid="6123238544099198034">"मैसेज (एसएमएस) पाएं"</item>
<item msgid="838342167431596036">"आपातकालीन मैसेज (एसएमएस) पाएं"</item>
<item msgid="8554432731560956686">"मल्टीमीडिया मैसेज (एमएमएस) पाएं"</item>
- <item msgid="7464863464299515059">"WAP पुश प्राप्त करें"</item>
+ <item msgid="7464863464299515059">"WAP पुश पाएं"</item>
<item msgid="310463075729606765">"मैसेज (एसएमएस) भेजें"</item>
<item msgid="7338021933527689514">"ICC मैसेज (एसएमएस) पढ़ें"</item>
<item msgid="6130369335466613036">"ICC मैसेज (एसएमएस) लिखें"</item>
@@ -197,7 +197,7 @@
<item msgid="8506227454543690851">"सचेत रखें"</item>
<item msgid="1108160036049727420">"जगह की निगरानी करें"</item>
<item msgid="1496205959751719491">"उच्च पावर वाली जगह की निगरानी करें"</item>
- <item msgid="3776296279910987380">"उपयोग के आंकड़े प्राप्त करें"</item>
+ <item msgid="3776296279910987380">"उपयोग के आंकड़े पाएं"</item>
<item msgid="8827100324471975602">"माइक्रोफ़ोन म्यूट/अनम्यूट करें"</item>
<item msgid="6880736730520126864">"टोस्ट दिखाएं"</item>
<item msgid="4933375960222609935">"प्रोजेक्ट मीडिया"</item>
@@ -216,7 +216,7 @@
<item msgid="8356842191824684631">"मेमोरी पढ़ें"</item>
<item msgid="5671906070163291500">"मेमोरी लिखें"</item>
<item msgid="2791955098549340418">"स्क्रीन चालू करें"</item>
- <item msgid="5599435119609178367">"खाते प्राप्त करें"</item>
+ <item msgid="5599435119609178367">"खाते पाएं"</item>
<item msgid="1165623660533024666">"पृष्ठभूमि में चलाएं"</item>
<item msgid="6423861043647911030">"सुलभता सुविधाओं के लिए आवाज़"</item>
</string-array>
@@ -264,7 +264,7 @@
<item msgid="5133991377896747027">"सचेत रखें"</item>
<item msgid="2464189519136248621">"स्थान"</item>
<item msgid="2062677934050803037">"जगह"</item>
- <item msgid="1735171933192715957">"उपयोग के आंकड़े प्राप्त करें"</item>
+ <item msgid="1735171933192715957">"उपयोग के आंकड़े पाएं"</item>
<item msgid="1014093788778383554">"माइक्रोफ़ोन म्यूट/अनम्यूट करें"</item>
<item msgid="4199297950608622850">"टोस्ट दिखाएं"</item>
<item msgid="2527962435313398821">"प्रोजेक्ट मीडिया"</item>
@@ -283,7 +283,7 @@
<item msgid="7224489175375229399">"मेमोरी पढ़ें"</item>
<item msgid="8472735063903258202">"मेमोरी लिखें"</item>
<item msgid="4069276819909595110">"स्क्रीन चालू करें"</item>
- <item msgid="1228338896751121025">"खाते प्राप्त करें"</item>
+ <item msgid="1228338896751121025">"खाते पाएं"</item>
<item msgid="3181581793459233672">"पृष्ठभूमि में चलाएं"</item>
<item msgid="2340936043025374076">"सुलभता सुविधाओं के लिए आवाज़"</item>
</string-array>
diff --git a/tests/CarDeveloperOptions/res/values-hi/strings.xml b/tests/CarDeveloperOptions/res/values-hi/strings.xml
index 8a90c96..39d6cbb 100644
--- a/tests/CarDeveloperOptions/res/values-hi/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-hi/strings.xml
@@ -222,7 +222,7 @@
<string name="radio_info_call_redirect_label" msgid="2679891718182753061">"कॉल रीडयरेक्ट:"</string>
<string name="radio_info_ppp_resets_label" msgid="2785162965440312941">"बूट के बाद से PPP रीसेट की संख्या:"</string>
<string name="radio_info_current_network_label" msgid="5785805819312999094">"वर्तमान नेटवर्क:"</string>
- <string name="radio_info_ppp_received_label" msgid="5217391494757374330">"डेटा प्राप्त हुआ:"</string>
+ <string name="radio_info_ppp_received_label" msgid="5217391494757374330">"डेटा पाया गया:"</string>
<string name="radio_info_gsm_service_label" msgid="7488842563230281026">"वॉइस सेवा:"</string>
<string name="radio_info_signal_strength_label" msgid="7773514616083573394">"सिग्नल की शक्ति:"</string>
<string name="radio_info_call_status_label" msgid="8241020608714164780">"वॉइस कॉल स्थिति:"</string>
@@ -372,8 +372,8 @@
<string name="location_settings_master_switch_title" msgid="3108016866082816733">"जगह की जानकारी की सुविधा का इस्तेमाल करें"</string>
<string name="location_settings_summary_location_off" msgid="5563530256978372978">"बंद करें"</string>
<plurals name="location_settings_summary_location_on" formatted="false" msgid="7893342914540884818">
- <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_1">%1$d</xliff:g> ऐप्लिकेशन जगह की जानकारी ऐक्सेस कर सकते हैं</item>
+ <item quantity="other">चालू - <xliff:g id="COUNT_1">%1$d</xliff:g> ऐप्लिकेशन जगह की जानकारी ऐक्सेस कर सकते हैं</item>
</plurals>
<string name="location_settings_loading_app_permission_stats" msgid="7818169326621327628">"लोड हो रहा है…"</string>
<string name="account_settings_title" msgid="7870321267198486578">"खाते"</string>
@@ -425,7 +425,7 @@
<string name="security_settings_face_settings_require_confirmation" msgid="7312024271060416438">"हमेशा पुष्टि करना ज़रूरी है"</string>
<string name="security_settings_face_settings_require_confirmation_details" msgid="8740564864091803429">"ऐप्लिकेशन में प्रमाणित करते समय हमेशा पुष्टि करना ज़रूरी है"</string>
<string name="security_settings_face_settings_remove_face_data" msgid="2821359954483136239">"चेहरे का डेटा हटाएं"</string>
- <string name="security_settings_face_settings_footer" msgid="4627175759990550715">"आप अपने चेहरे के ज़रिए अपने डिवाइस को अनलॉक कर सकते हैं और ऐप्लिकेशन एक्सेस कर सकते हैं. "<annotation id="url">"ज़्यादा जानें"</annotation></string>
+ <string name="security_settings_face_settings_footer" msgid="4627175759990550715">"आप अपने चेहरे के ज़रिए अपने डिवाइस को अनलॉक कर सकते हैं और ऐप्लिकेशन ऐक्सेस कर सकते हैं. "<annotation id="url">"ज़्यादा जानें"</annotation></string>
<string name="security_settings_face_settings_remove_dialog_title" msgid="5675319895815271094">"चेहरे से जुड़ा डेटा मिटाएं?"</string>
<string name="security_settings_face_settings_remove_dialog_details" msgid="3754494807169276107">"चेहरे की पहचान करके डिवाइस को अनलॉक करने की सुविधा के ज़रिए रिकॉर्ड किया गया डेटा हमेशा के लिए और सुरक्षित रूप से मिटा दिया जाएगा. मिटाने के बाद अपने फ़ोन को अनलॉक करने, ऐप्लिकेशन में साइन इन करने और भुगतान की पुष्टि करने के लिए आपको पिन, पैटर्न या पासवर्ड की ज़रूरत होगी."</string>
<string name="security_settings_fingerprint_preference_title" msgid="4177132225930582928">"उंगली की छाप"</string>
@@ -495,7 +495,7 @@
<string name="fingerprint_enroll_button_add" msgid="6335782936874996629">"कोई और जोड़ें"</string>
<string name="fingerprint_enroll_button_next" msgid="6419214079104413695">"आगे बढ़ें"</string>
<string name="security_settings_fingerprint_enroll_disclaimer" msgid="5831834311961551423">"अपना फ़ोन अनलॉक करने के साथ-साथ, खरीदारी और ऐप ऐक्सेस को अधिकृत करने के लिए आप अपनी फ़िंगरप्रिंट का भी उपयोग कर सकते हैं. "<annotation id="url">"ज़्यादा जानें"</annotation></string>
- <string name="security_settings_fingerprint_enroll_disclaimer_lockscreen_disabled" msgid="7954742554236652690">" स्क्रीन लॉक विकल्प बंद है. ज़्यादा जानने के लिए, अपने संगठन के एडमिन से संपर्क करें. "<annotation id="admin_details">"ज़्यादा जानकारी{"</annotation>\n\n"आप खरीदारी और ऐप एक्सेस की अनुमति देने के लिए अब भी अपने फ़िंगरप्रिंट का इस्तेमाल कर सकते हैं. "<annotation id="url">"ज़्यादा जानें"</annotation></string>
+ <string name="security_settings_fingerprint_enroll_disclaimer_lockscreen_disabled" msgid="7954742554236652690">" स्क्रीन लॉक विकल्प बंद है. ज़्यादा जानने के लिए, अपने संगठन के एडमिन से संपर्क करें. "<annotation id="admin_details">"ज़्यादा जानकारी{"</annotation>\n\n"आप खरीदारी और ऐप ऐक्सेस की अनुमति देने के लिए अब भी अपने फ़िंगरप्रिंट का इस्तेमाल कर सकते हैं. "<annotation id="url">"ज़्यादा जानें"</annotation></string>
<string name="security_settings_fingerprint_enroll_lift_touch_again" msgid="1670703069782212223">"उंगली उठाएं और सेंसर को फिर छूएं"</string>
<string name="fingerprint_add_max" msgid="2939393314646115661">"आप <xliff:g id="COUNT">%d</xliff:g> फ़िंगरप्रिंट तक जोड़ सकते हैं"</string>
<string name="fingerprint_intro_error_max" msgid="3247720976621039437">"आप अधिकतम संख्या में फ़िंगरप्रिंट जोड़ चुके हैं"</string>
@@ -710,7 +710,7 @@
<string name="lockpattern_tutorial_cancel_label" msgid="450401426127674369">"रद्द करें"</string>
<string name="lockpattern_tutorial_continue_label" msgid="8474690922559443018">"आगे बढ़ें"</string>
<string name="lock_setup" msgid="8710689848703935088">"सेटअप पूरा हुआ."</string>
- <string name="manage_device_admin" msgid="322047441168191695">"डिवाइस के एडमिन ऐप्लिकेशन का एक्सेस"</string>
+ <string name="manage_device_admin" msgid="322047441168191695">"डिवाइस के एडमिन ऐप्लिकेशन का ऐक्सेस"</string>
<string name="number_of_device_admins_none" msgid="8519193548630223132">"कोई भी सक्रिय ऐप्लिकेशन नहीं है"</string>
<plurals name="number_of_device_admins" formatted="false" msgid="6445613288828151224">
<item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> सक्रिय ऐप</item>
@@ -823,7 +823,7 @@
<string name="nfc_quick_toggle_summary" product="tablet" msgid="983451155092850657">"जब टैबलेट अन्य डिवाइस को स्पर्श करे तो डेटा ट्रांसफर करने दें"</string>
<string name="nfc_quick_toggle_summary" product="default" msgid="7141056939052895142">"जब फ़ोन दूसरे डिवाइस को टच करे तो डेटा ट्रांसफर करने दें"</string>
<string name="nfc_disclaimer_title" msgid="4860231267351602970">"NFC चालू करें"</string>
- <string name="nfc_disclaimer_content" msgid="3066113577854565782">"NFC इस डिवाइस और आस-पास के अन्य डिवाइस या लक्ष्यों के बीच डेटा का लेन-देन करता है, जैसे कि भुगतान टर्मिनल, एक्सेस रीडर और सहभागी विज्ञापन या टैग."</string>
+ <string name="nfc_disclaimer_content" msgid="3066113577854565782">"NFC इस डिवाइस और आस-पास के अन्य डिवाइस या लक्ष्यों के बीच डेटा का लेन-देन करता है, जैसे कि भुगतान टर्मिनल, ऐक्सेस रीडर और सहभागी विज्ञापन या टैग."</string>
<string name="nfc_secure_settings_title" msgid="5153751163174916581">"NFC सुरक्षित करें"</string>
<string name="nfc_secure_toggle_summary" product="default" msgid="7631183023440112192">"NFC भुगतान और ट्रांज़िट के इस्तेमाल की अनुमति तभी दें, जब स्क्रीन अनलॉक की गई हो"</string>
<string name="android_beam_settings_title" msgid="3083436415873738389">"Android बीम"</string>
@@ -986,7 +986,7 @@
<string name="wifi_hotspot_title" msgid="2631956539767069385">"कनेक्ट करने के लिए साइन इन करें?"</string>
<string name="wifi_hotspot_message" msgid="6762452611090766607">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए नेटवर्क से कनेक्ट करने से पहले साइन करें."</string>
<string name="wifi_hotspot_connect" msgid="409079339360849653">"कनेक्ट करें"</string>
- <string name="no_internet_access_text" msgid="7093326244145734504">"इस नेटवर्क में कोई इंटरनेट एक्सेस नहीं है. जुड़े रहें?"</string>
+ <string name="no_internet_access_text" msgid="7093326244145734504">"इस नेटवर्क में कोई इंटरनेट ऐक्सेस नहीं है. जुड़े रहें?"</string>
<string name="partial_connectivity_text" msgid="2142157808079235684">"सीमित कनेक्टिविटी की वजह से हो सकता है कुछ ऐप्लिकेशन और सेवाएं न काम करें. फिर भी इस्तेमाल करें?"</string>
<string name="no_internet_access_remember" msgid="1368137189939004202">"इस नेटवर्क के लिए फिर से ना पूछें"</string>
<string name="lost_internet_access_title" msgid="1061916948695946130">"वाई-फ़ाई इंटरनेट से नहीं जुड़ा है"</string>
@@ -1519,8 +1519,8 @@
<string name="storage_wizard_ready_v2_internal_moved_body" msgid="4133133596316768033">"आपकी सामग्री <xliff:g id="NAME_0">^1</xliff:g> में ले जाई जा चुकी है. \n\nइस <xliff:g id="NAME_1">^2</xliff:g> को प्रबंधित करने के लिए, "<b>"सेटिंग > मेमोरी में जाएं"</b>"."</string>
<string name="battery_status_title" msgid="8731200319740671905">"बैटरी स्थिति"</string>
<string name="battery_level_title" msgid="5207775387973771646">"बैटरी स्तर"</string>
- <string name="apn_settings" msgid="8130776653826271664">"एक्सेस पॉइंट नाम"</string>
- <string name="apn_edit" msgid="4350571070853305357">"एक्सेस पॉइंट में बदलाव करें"</string>
+ <string name="apn_settings" msgid="8130776653826271664">"ऐक्सेस पॉइंट नाम"</string>
+ <string name="apn_edit" msgid="4350571070853305357">"ऐक्सेस पॉइंट में बदलाव करें"</string>
<string name="apn_not_set" msgid="5344235604466825691">"सेट नहीं है"</string>
<string name="apn_name" msgid="8431432886706852226">"नाम"</string>
<string name="apn_apn" msgid="190519449579357696">"APN"</string>
@@ -1644,10 +1644,10 @@
<string name="location_app_level_permissions" msgid="1298041503927632960">"ऐप्लिकेशन की अनुमति"</string>
<string name="location_app_permission_summary_location_off" msgid="541372845344796336">"जगह की जानकारी बंद है"</string>
<plurals name="location_app_permission_summary_location_on" formatted="false" msgid="7904821382328758218">
- <item quantity="one"> <xliff:g id="TOTAL_LOCATION_APP_COUNT_3">%2$d</xliff:g> में से <xliff:g id="BACKGROUND_LOCATION_APP_COUNT_2">%1$d</xliff:g> ऐप्लिकेशन के पास असीमित एक्सेस है</item>
- <item quantity="other"> <xliff:g id="TOTAL_LOCATION_APP_COUNT_3">%2$d</xliff:g> में से <xliff:g id="BACKGROUND_LOCATION_APP_COUNT_2">%1$d</xliff:g> ऐप्लिकेशन के पास असीमित एक्सेस है</item>
+ <item quantity="one"> <xliff:g id="TOTAL_LOCATION_APP_COUNT_3">%2$d</xliff:g> में से <xliff:g id="BACKGROUND_LOCATION_APP_COUNT_2">%1$d</xliff:g> ऐप्लिकेशन के पास असीमित ऐक्सेस है</item>
+ <item quantity="other"> <xliff:g id="TOTAL_LOCATION_APP_COUNT_3">%2$d</xliff:g> में से <xliff:g id="BACKGROUND_LOCATION_APP_COUNT_2">%1$d</xliff:g> ऐप्लिकेशन के पास असीमित ऐक्सेस है</item>
</plurals>
- <string name="location_category_recent_location_access" msgid="286059523360285026">"हाल ही में एक्सेस की गई जगह की जानकारी"</string>
+ <string name="location_category_recent_location_access" msgid="286059523360285026">"हाल ही में ऐक्सेस की गई जगह की जानकारी"</string>
<string name="location_recent_location_access_view_details" msgid="2051602261436245905">"जानकारी देखें"</string>
<string name="location_no_recent_apps" msgid="77502059586413278">"किसी भी ऐप ने हाल में जगह का अनुरोध नहीं किया है"</string>
<string name="location_no_recent_accesses" msgid="6289916310397279890">"किसी भी ऐप्लिकेशन ने हाल ही में जगह की जानकारी का इस्तेमाल नहीं किया"</string>
@@ -1665,12 +1665,12 @@
<string name="location_gps" msgid="688049341158297763">"GPS उपग्रह"</string>
<string name="location_street_level" product="tablet" msgid="4459804798444296650">"आपकी जगह का पता लगाने के लिए, ऐप को आपके टैबलेट पर जीपीएस का इस्तेमाल करने दें"</string>
<string name="location_street_level" product="default" msgid="7407688345675450051">"आपकी जगह का पता लगाने के लिए, ऐप को आपके फ़ोन पर जीपीएस का इस्तेमाल करने दें"</string>
- <string name="assisted_gps" msgid="5411780261117055175">"सहायता प्राप्त GPS का उपयोग करें"</string>
+ <string name="assisted_gps" msgid="5411780261117055175">"सहायता पाए हुए GPS का उपयोग करें"</string>
<string name="assisted_gps_enabled" msgid="2561022181775725369">"GPS की सहायता के लिए सर्वर का उपयोग करें (नेटवर्क उपयोग कम करने के लिए अनचेक करें)"</string>
<string name="assisted_gps_disabled" msgid="6448758788217415937">"GPS की सहायता के लिए सर्वर का उपयोग करें (GPS निष्पादन बेहतर बनाने के लिए अनचेक करें)"</string>
<string name="use_location_title" msgid="7724788634359496634">"जगह और Google सर्च"</string>
<string name="use_location_summary" msgid="7396716606067400283">"सर्च नतीजों और अन्य सेवाओं में सुधार के लिए Google को आपकी जगह का इस्तेमाल करने दें"</string>
- <string name="location_access_title" msgid="8587974819606800029">"मेरी जगह को एक्सेस करें"</string>
+ <string name="location_access_title" msgid="8587974819606800029">"मेरी जगह को ऐक्सेस करें"</string>
<string name="location_access_summary" msgid="6919495149026354355">"जिन ऐप ने आपसे अनुमति मांगी है उन्हें अपने जगह की जानकारी का इस्तेमाल करने दें"</string>
<string name="location_sources_heading" msgid="8526658357120282741">"स्थानीय स्रोत"</string>
<string name="about_settings" product="tablet" msgid="4869626690708456341">"टैबलेट के बारे में"</string>
@@ -1804,7 +1804,7 @@
<item quantity="one">%d आइटम</item>
<item quantity="other">%d आइटम</item>
</plurals>
- <string name="clear_uri_btn_text" msgid="3528618179883855727">"एक्सेस साफ़ करें"</string>
+ <string name="clear_uri_btn_text" msgid="3528618179883855727">"ऐक्सेस साफ़ करें"</string>
<string name="controls_label" msgid="5609285071259457221">"नियंत्रण"</string>
<string name="force_stop" msgid="9213858124674772386">"ज़बरदस्ती रोकें"</string>
<string name="total_size_label" msgid="3929917501176594692">"सम्पूर्ण जगह"</string>
@@ -2372,10 +2372,10 @@
<string name="usage_type_phone" product="tablet" msgid="4279605085824633501">"टैबलेट"</string>
<string name="usage_type_phone" product="default" msgid="3901842461077646153">"फ़ोन"</string>
<string name="usage_type_data_send" msgid="6339880867171142725">"मोबाइल पैकेट भेजे गए"</string>
- <string name="usage_type_data_recv" msgid="2099757621601333453">"मोबाइल पैकेट प्राप्त हुए"</string>
+ <string name="usage_type_data_recv" msgid="2099757621601333453">"मोबाइल पैकेट मिले"</string>
<string name="usage_type_radio_active" msgid="4123481281606636561">"मोबाइल रेडियो सक्रिय"</string>
<string name="usage_type_data_wifi_send" msgid="4457097885099163617">"वाई-फ़ाई पैकेट भेजे गए"</string>
- <string name="usage_type_data_wifi_recv" msgid="6629526425662663926">"वाई-फ़ाई पैकेट प्राप्त हुए"</string>
+ <string name="usage_type_data_wifi_recv" msgid="6629526425662663926">"वाई-फ़ाई पैकेट मिले"</string>
<string name="usage_type_audio" msgid="510459400845396879">"ऑडियो"</string>
<string name="usage_type_video" msgid="8161701367674306793">"वीडियो"</string>
<string name="usage_type_camera" msgid="2276450385733155264">"कैमरा"</string>
@@ -2536,7 +2536,7 @@
<string name="credentials_reset_hint" msgid="3484350477764088169">"सभी सामग्री हटाएं?"</string>
<string name="credentials_erased" msgid="7287088033523869085">"प्रमाणिकता मेमोरी मिटा दिया गया है."</string>
<string name="credentials_not_erased" msgid="9137227570738627637">"प्रमाणिकता मेमोरी मिटाया नहीं जा सका."</string>
- <string name="usage_access_title" msgid="7981321142726540574">"उपयोग के एक्सेस वाले ऐप्लिकेशन"</string>
+ <string name="usage_access_title" msgid="7981321142726540574">"उपयोग के ऐक्सेस वाले ऐप्लिकेशन"</string>
<string name="emergency_tone_title" msgid="130211364025984428">"आपातकालीन डायलिंग सिग्नल"</string>
<string name="emergency_tone_summary" msgid="8035940153401622240">"आपातकालीन कॉल करने के दौरान व्यवहार सेट करें"</string>
<string name="privacy_settings_title" msgid="3573891462732375772">"बैकअप लें"</string>
@@ -2566,7 +2566,7 @@
<string name="no_device_admins" msgid="4129231900385977460">"कोई भी डिवाइस व्यवस्थापक ऐप्लिकेशन उपलब्ध नहीं है"</string>
<string name="personal_device_admin_title" msgid="759440849188565661">"व्यक्तिगत"</string>
<string name="managed_device_admin_title" msgid="8021522755492551726">"दफ़्तर"</string>
- <string name="sms_access_restriction_enabled" msgid="3006320256764718303">"मैसेज (एसएमएस) और कॉल लॉग एक्सेस प्रतिबंधित करें"</string>
+ <string name="sms_access_restriction_enabled" msgid="3006320256764718303">"मैसेज (एसएमएस) और कॉल लॉग ऐक्सेस प्रतिबंधित करें"</string>
<string name="sms_access_restriction_enabled_summary" msgid="9011946580977780063">"सिर्फ़ डिफ़ॉल्ट फ़ोन और मैसेज-सेवा देने वाले ऐप्लिकेशन के पास मैसेज (एसएमएस) और कॉल लॉग की अनुमतियां होती हैं"</string>
<string name="no_trust_agents" msgid="5757792915019113084">"कोई ट्रस्ट एजेंट उपलब्ध नहीं"</string>
<string name="add_device_admin_msg" msgid="3573765823476931173">"इस डिवाइस एडमिन ऐप्लिकेशन को चालू करें?"</string>
@@ -2596,7 +2596,7 @@
<string name="work_mode_off_summary" msgid="1688885392211178315">"ऐप्लिकेशन और सूचनाएं बंद हैं"</string>
<string name="remove_managed_profile_label" msgid="4625542553784793536">"वर्क प्रोफ़ाइल निकालें"</string>
<string name="background_data" msgid="8275750862371471171">"पृष्ठभूमि डेटा"</string>
- <string name="background_data_summary" msgid="799640633948841990">"ऐप्लिकेशन किसी भी समय डेटा समन्वयित, भेज और प्राप्त कर सकते हैं"</string>
+ <string name="background_data_summary" msgid="799640633948841990">"ऐप्लिकेशन किसी भी समय डेटा सिंक करना, भेज, और पा सकते हैं"</string>
<string name="background_data_dialog_title" msgid="8306650658158895976">"पृष्ठभू. डेटा अक्षम करें?"</string>
<string name="background_data_dialog_message" msgid="8126774244911656527">"बैकग्राउंड डेटा को बंद करने से बैटरी ज़्यादा चलती है और डेटा कम खर्च होता है. हो सकता है कि कुछ ऐप अब भी बैकग्राउंड में डेटा इस्तेमाल कर रहे हों."</string>
<string name="sync_automatically" msgid="5746117156896468099">"ऐप डेटा अपने आप सिंक करें"</string>
@@ -2717,7 +2717,7 @@
<string name="data_usage_sweep_limit" msgid="6101105504557548269"><font size="18">"<xliff:g id="NUMBER">^1</xliff:g>"</font>" "<font size="9">"<xliff:g id="UNIT">^2</xliff:g>"</font>\n<font size="12">"सीमा"</font></string>
<string name="data_usage_uninstalled_apps" msgid="4152786786140875769">"निकाले गए ऐप्लिकेशन"</string>
<string name="data_usage_uninstalled_apps_users" msgid="61092462416505112">"ऐप्लिकेशन और उपयोगकर्ताओं को निकालें"</string>
- <string name="data_usage_received_sent" msgid="5532467049487334656">"<xliff:g id="RECEIVED">%1$s</xliff:g> प्राप्त, <xliff:g id="SENT">%2$s</xliff:g> भेजा"</string>
+ <string name="data_usage_received_sent" msgid="5532467049487334656">"<xliff:g id="RECEIVED">%1$s</xliff:g> पाया, <xliff:g id="SENT">%2$s</xliff:g> भेजा"</string>
<string name="data_usage_total_during_range" msgid="7307562900020512747">"<xliff:g id="RANGE">%2$s</xliff:g>: करीब <xliff:g id="TOTAL">%1$s</xliff:g> का उपयोग किया गया."</string>
<string name="data_usage_total_during_range_mobile" product="tablet" msgid="366118962920532455">"<xliff:g id="RANGE">%2$s</xliff:g>: आपके टैबलेट के द्वारा मापे जाने के अनुसार, करीब <xliff:g id="TOTAL">%1$s</xliff:g> का उपयोग किया गया. आपके कैरियर की डेटा गणना अलग हो सकती है."</string>
<string name="data_usage_total_during_range_mobile" product="default" msgid="3504412681869806383">"<xliff:g id="RANGE">%2$s</xliff:g>: आपके फ़ोन के द्वारा मापे जाने के अनुसार, करीब <xliff:g id="TOTAL">%1$s</xliff:g> का उपयोग किया गया. आपके कैरियर की डेटा गणना अलग हो सकती है."</string>
@@ -2751,7 +2751,7 @@
<string name="vpn_save_login" msgid="6215503139606646915">"खाते की जानकारी सेव करें"</string>
<string name="vpn_not_used" msgid="2889520789132261454">"(उपयोग नहीं किया)"</string>
<string name="vpn_no_ca_cert" msgid="486605757354800838">"(सर्वर सत्यापित न करें)"</string>
- <string name="vpn_no_server_cert" msgid="679622228649855629">"(सर्वर से प्राप्त)"</string>
+ <string name="vpn_no_server_cert" msgid="679622228649855629">"(सर्वर से मिला)"</string>
<string name="vpn_always_on_invalid_reason_type" msgid="165810330614905489">"यह वीपीएन प्रकार हमेशा कनेक्ट नहीं रह सकता"</string>
<string name="vpn_always_on_invalid_reason_server" msgid="3864424127328210700">"हमेशा-चालू VPN सिर्फ़ संख्या वाले सर्वर पतों का समर्थन करता है"</string>
<string name="vpn_always_on_invalid_reason_no_dns" msgid="3814114757059738225">"हमेशा-चालू VPN के लिए एक DNS सर्वर तय किया जाना चाहिए"</string>
@@ -2937,7 +2937,7 @@
<string name="severe_threats_title" msgid="1987698359027211862">"गंभीर धमकियां"</string>
<string name="severe_threats_summary" msgid="1148147804181873835">"जान और माल के गंभीर खतरों के लिए अलर्ट पाएं"</string>
<string name="amber_alerts_title" msgid="8274651933750533271">"AMBER अलर्ट"</string>
- <string name="amber_alerts_summary" msgid="7570943549000256418">"बाल अपहरणों के बारे में बुलेटिन प्राप्त करें"</string>
+ <string name="amber_alerts_summary" msgid="7570943549000256418">"बाल अपहरणों के बारे में बुलेटिन पाएं"</string>
<string name="repeat_title" msgid="507090203366188931">"दोहराएं"</string>
<string name="call_manager_enable_title" msgid="6345443572463650308">"कॉल प्रबंधक चालू करें"</string>
<string name="call_manager_enable_summary" msgid="6998536841827752058">"इस सेवा को कॉल करने का आपका तरीका प्रबंधित करने दें."</string>
@@ -2946,7 +2946,7 @@
<skip />
<string name="cell_broadcast_settings" msgid="5750066270993255966">"इमरजेंसी के समय सूचनाएं"</string>
<string name="network_operators_settings" msgid="7822337582828465633">"नेटवर्क ऑपरेटर"</string>
- <string name="access_point_names" msgid="7992382237358800596">"एक्सेस पॉइंट का नाम"</string>
+ <string name="access_point_names" msgid="7992382237358800596">"ऐक्सेस पॉइंट का नाम"</string>
<string name="enhanced_4g_lte_mode_title" msgid="1624079276378568594">"VoLTE"</string>
<string name="enhanced_4g_lte_mode_title_advanced_calling" msgid="5155507161065290507">"बेहतर कॉलिंग"</string>
<string name="enhanced_4g_lte_mode_title_4g_calling" msgid="1262729135500839141">"4G कॉलिंग"</string>
@@ -3300,7 +3300,7 @@
<string name="hide_silent_icons_summary" msgid="2624346914488256888">"स्थिति बार में बिना आवाज़ की सूचनाओं के आइकॉन छिपाएं"</string>
<string name="notification_badging_title" msgid="6311699476970264712">"सूचना बिंदुओं की अनुमति दें"</string>
<string name="notification_bubbles_title" msgid="9196562435741861317">"बबल"</string>
- <string name="notification_bubbles_summary" msgid="4624512775901949578">"फ़्लोटिंग शॉर्टकट का इस्तेमाल करके ऐप्लिकेशन की सामग्री कहीं से भी फटाफट एक्सेस करें"</string>
+ <string name="notification_bubbles_summary" msgid="4624512775901949578">"फ़्लोटिंग शॉर्टकट का इस्तेमाल करके ऐप्लिकेशन की सामग्री कहीं से भी फटाफट ऐक्सेस करें"</string>
<string name="bubbles_feature_education" msgid="8979109826818881018">"कुछ सूचनाएं और दूसरी सामग्री स्क्रीन पर बबल के रूप में दिखाई दे सकती हैं. बबल खोलने के लिए इस पर टैप करें. इसे खारिज करने के लिए इसे खींचकर स्क्रीन पर नीचे की ओर ले जाएं."</string>
<string name="bubbles_app_toggle_title" msgid="6401217027603326439">"बबल"</string>
<string name="bubbles_app_toggle_summary" msgid="7707611139796553855">"<xliff:g id="APP_NAME">%1$s</xliff:g> को कुछ सूचनाएं बबल के तौर पर दिखाने की अनुमति दें"</string>
@@ -3353,7 +3353,7 @@
<string name="notifications_sent_daily" msgid="6874886521964822824">"करीब <xliff:g id="NUMBER">%1$s</xliff:g> सूचनाएं हर दिन"</string>
<string name="notifications_sent_weekly" msgid="5859675428990259432">"करीब <xliff:g id="NUMBER">%1$s</xliff:g> सूचनाएं हर हफ़्ते"</string>
<string name="notifications_sent_never" msgid="237997329598144638">"कभी नहीं"</string>
- <string name="manage_notification_access_title" msgid="5348743662189787547">"सूचना का एक्सेस"</string>
+ <string name="manage_notification_access_title" msgid="5348743662189787547">"सूचना का ऐक्सेस"</string>
<string name="work_profile_notification_access_blocked_summary" msgid="8148871282484870576">"वर्क प्रोफ़ाइल सूचना की पहुंच रोक दी गई है"</string>
<string name="manage_notification_access_summary_zero" msgid="236809421271593016">"ऐप सूचनाएं नहीं पढ़ सकते"</string>
<plurals name="manage_notification_access_summary_nonzero" formatted="false" msgid="8496218948429646792">
@@ -3362,12 +3362,12 @@
</plurals>
<string name="notification_assistant_title" msgid="8216604031352764011">"सूचना सहायक"</string>
<string name="no_notification_assistant" msgid="9140123568386413264">"किसी सहायक की सुविधा नहीं है"</string>
- <string name="no_notification_listeners" msgid="1366386609506834717">"इंस्टॉल किए गए किसी भी ऐप ने सूचना के एक्सेस का अनुरोध नहीं किया है."</string>
- <string name="notification_assistant_security_warning_title" msgid="4190584438086738496">"<xliff:g id="SERVICE">%1$s</xliff:g> के लिए सूचना एक्सेस करने की अनुमति दें?"</string>
+ <string name="no_notification_listeners" msgid="1366386609506834717">"इंस्टॉल किए गए किसी भी ऐप ने सूचना के ऐक्सेस का अनुरोध नहीं किया है."</string>
+ <string name="notification_assistant_security_warning_title" msgid="4190584438086738496">"<xliff:g id="SERVICE">%1$s</xliff:g> के लिए सूचना ऐक्सेस करने की अनुमति दें?"</string>
<string name="notification_assistant_security_warning_summary" msgid="6924513399671031930">"<xliff:g id="NOTIFICATION_ASSISTANT_NAME">%1$s</xliff:g> आपकी हर सूचना पढ़ पाएगा. इसमें आपकी निजी जानकारी, जैसे कि संपर्कों के नाम और आपको आने वाले मैसेज में लिखी चीज़ें शामिल हैं. यह सूचनाओं में बदलाव करने, उन्हें खारिज करने या उनमें मौजूद कार्रवाई बटनों को ट्रिगर करने जैसे काम भी कर पाएगा. \n\nइससे यह ऐप्लिकेशन \'परेशान न करें\' सुविधा चालू या बंद कर पाएगा या इससे जुड़ी सेटिंग बदल पाएगा."</string>
- <string name="notification_listener_security_warning_title" msgid="4902253246428777797">"<xliff:g id="SERVICE">%1$s</xliff:g> के लिए सूचना को एक्सेस करने की अनुमति दें?"</string>
+ <string name="notification_listener_security_warning_title" msgid="4902253246428777797">"<xliff:g id="SERVICE">%1$s</xliff:g> के लिए सूचना को ऐक्सेस करने की अनुमति दें?"</string>
<string name="notification_listener_security_warning_summary" msgid="4454702907350100288">"<xliff:g id="NOTIFICATION_LISTENER_NAME">%1$s</xliff:g> संपर्क नामों और आपको मिलने वाले मैसेज जैसी निजी जानकारी सहित, सभी सूचनाएं पढ़ सकता है. वह सूचना खारिज कर सकेगा और उनमें शामिल कार्रवाई बटनों को ट्रिगर भी कर सकेगा. \n\nइससे ऐप \'परेशान न करें\' सुविधा को चालू या बंद कर सकता है और उससे जुड़ी सेटिंग को भी बदल सकता है"</string>
- <string name="notification_listener_disable_warning_summary" msgid="162165151519082978">"अगर आप <xliff:g id="NOTIFICATION_LISTENER_NAME">%1$s</xliff:g> के लिए सूचना का एक्सेस बंद करते हैं, तो \'परेशान न करें\' सेवा का एक्सेस भी बंद हो सकता है."</string>
+ <string name="notification_listener_disable_warning_summary" msgid="162165151519082978">"अगर आप <xliff:g id="NOTIFICATION_LISTENER_NAME">%1$s</xliff:g> के लिए सूचना का ऐक्सेस बंद करते हैं, तो \'परेशान न करें\' सेवा का ऐक्सेस भी बंद हो सकता है."</string>
<string name="notification_listener_disable_warning_confirm" msgid="7863495391671154188">"बंद करें"</string>
<string name="notification_listener_disable_warning_cancel" msgid="6264631825225298458">"रद्द करें"</string>
<string name="vr_listeners_title" msgid="511483902408792832">"VR सहायक सेवाएं"</string>
@@ -3383,7 +3383,7 @@
<string name="picture_in_picture_app_detail_title" msgid="3916189052657425936">"पिक्चर में पिक्चर"</string>
<string name="picture_in_picture_app_detail_switch" msgid="747422998967185418">"पिक्चर में पिक्चर बनाने की अनुमति दें"</string>
<string name="picture_in_picture_app_detail_summary" msgid="918632751775525347">"ऐप के खुले होने पर या आपके उसे छोड़ देने के बाद, उस ऐप को पिक्चर में पिक्चर बनाने की अनुमति दें (उदाहरण के लिए, कोई वीडियो देखते रहने के लिए). यह विंडो उन दूसरे ऐप्लिकेशन के ऊपर दिखाई देती है जिनका आप उपयोग कर रहे हैं."</string>
- <string name="manage_zen_access_title" msgid="3058206309728524196">"परेशान न करें सुविधा का एक्सेस"</string>
+ <string name="manage_zen_access_title" msgid="3058206309728524196">"परेशान न करें सुविधा का ऐक्सेस"</string>
<string name="zen_access_detail_switch" msgid="8706332327904974500">"\'परेशान न करें\' सुविधा चालू करें"</string>
<string name="zen_access_empty_text" msgid="7667538993781607731">"इंस्टॉल किए गए किसी भी ऐप ने परेशान ना करें सुविधा के इस्तेमाल का अनुरोध नहीं किया है"</string>
<string name="loading_notification_apps" msgid="1978345231934072091">"ऐप्लिकेशन लोड हो रहे हैं..."</string>
@@ -3671,7 +3671,7 @@
<string name="system_app" msgid="4111402206594443265">"(सिस्टम)"</string>
<string name="system_default_app" msgid="1454719098589351197">"(सिस्टम डिफ़ॉल्ट)"</string>
<string name="apps_storage" msgid="5658466038269046038">"ऐप्लिकेशन मेमोरी"</string>
- <string name="usage_access" msgid="2023443456361489516">"इस्तेमाल का एक्सेस"</string>
+ <string name="usage_access" msgid="2023443456361489516">"इस्तेमाल का ऐक्सेस"</string>
<string name="permit_usage_access" msgid="3321727608629752758">"\'डेटा खर्च\' देखने की इजाज़त दें"</string>
<string name="app_usage_preference" msgid="5691545073101551727">"ऐप उपयोग की प्राथमिकताएं"</string>
<string name="time_spent_in_app_pref_title" msgid="2803186835902798451">"स्क्रीन समय"</string>
@@ -3750,13 +3750,13 @@
<string name="usb_summary_photo_transfers_power" msgid="4424106272137720464">"पीटीपी और पावर देना"</string>
<string name="usb_summary_MIDI_power" msgid="7685597621357005180">"एमआईडीआई (मिडी) और पावर देना"</string>
<string name="background_check_pref" msgid="664081406854758392">"बैकग्राउंड की जॉंच"</string>
- <string name="background_check_title" msgid="4136736684290307970">"पूरे बैकग्राउंड की एक्सेस"</string>
+ <string name="background_check_title" msgid="4136736684290307970">"पूरे बैकग्राउंड की ऐक्सेस"</string>
<string name="assist_access_context_title" msgid="2274614501747710439">"स्क्रीन के लेख का उपयोग करना"</string>
- <string name="assist_access_context_summary" msgid="5867997494395842785">"सहायक ऐप्लिकेशन को स्क्रीन पर मौजूद सामग्री को लेख के रूप में एक्सेस करने दें"</string>
+ <string name="assist_access_context_summary" msgid="5867997494395842785">"सहायक ऐप्लिकेशन को स्क्रीन पर मौजूद सामग्री को लेख के रूप में ऐक्सेस करने दें"</string>
<string name="assist_access_screenshot_title" msgid="1991014038776117688">"स्क्रीनशॉट का उपयोग करना"</string>
<string name="assist_access_screenshot_summary" msgid="3010943864000489424">"सहायक ऐप्लिकेशन को स्क्रीन की इमेज तक पहुंचने दें"</string>
<string name="assist_flash_title" msgid="8852484250748551092">"स्क्रीन फ़्लैश करें"</string>
- <string name="assist_flash_summary" msgid="6697095786317559129">"जब सहायक ऐप्लिकेशन स्क्रीन पर मौजूद लेख या स्क्रीनशॉट को एक्सेस करे तो स्क्रीन के किनारों पर रोशनी चमकाएं"</string>
+ <string name="assist_flash_summary" msgid="6697095786317559129">"जब सहायक ऐप्लिकेशन स्क्रीन पर मौजूद लेख या स्क्रीनशॉट को ऐक्सेस करे तो स्क्रीन के किनारों पर रोशनी चमकाएं"</string>
<string name="assist_footer" msgid="7030121180457472165">"आप जो स्क्रीन देख रहे हैं, उसकी जानकारी के आधार पर सहायक ऐप्लिकेशन आपकी मदद कर सकते हैं. कुछ ऐप्लिकेशन पर, आपकी पूरी मदद करने के लिए लॉन्चर और बोलकर फ़ोन को निर्देश देना, ये दोनों सेवाएं काम करती हैं."</string>
<string name="average_memory_use" msgid="5333366040118953945">"औसत मेमोरी उपयोग"</string>
<string name="maximum_memory_use" msgid="6509872438499846077">"अधिकतम मेमोरी उपयोग"</string>
@@ -3781,7 +3781,7 @@
<string name="no_data_usage" msgid="903383745620135746">"किसी डेटा का उपयोग नहीं किया गया"</string>
<string name="zen_access_warning_dialog_title" msgid="7704910289810337055">"<xliff:g id="APP">%1$s</xliff:g> के लिए परेशान न करें की ऐक्सेस की अनुमति दें?"</string>
<string name="zen_access_warning_dialog_summary" msgid="2717755746850874577">"यह ऐप, परेशान न करें को चालू/बंद कर सकेगा और संबंधित सेटिंग में बदलाव कर सकेगा."</string>
- <string name="zen_access_disabled_package_warning" msgid="7086237569177576966">"इसे चालू रखें क्योंकि सूचना का एक्सेस चालू है"</string>
+ <string name="zen_access_disabled_package_warning" msgid="7086237569177576966">"इसे चालू रखें क्योंकि सूचना का ऐक्सेस चालू है"</string>
<string name="zen_access_revoke_warning_dialog_title" msgid="6850994585577513299">"<xliff:g id="APP">%1$s</xliff:g> के लिए परेशान न करें की पहुंच रद्द करें?"</string>
<string name="zen_access_revoke_warning_dialog_summary" msgid="3487422193181311403">"इस ऐप के द्वारा, परेशान न करें के लिए बनाए गए सभी नियम निकाल दिए जाएंगे."</string>
<string name="ignore_optimizations_on" msgid="4373971641328943551">"ऑप्टिमाइज़ ना करें"</string>
@@ -3790,7 +3790,7 @@
<string name="ignore_optimizations_off_desc" msgid="5598702251817814289">"बेहतर बैटरी जीवनकाल के लिए सुझाया गया"</string>
<string name="ignore_optimizations_title" msgid="7924345545276166305">"<xliff:g id="APP">%s</xliff:g> को बैटरी ऑप्टिमाइज़ेशन को अनदेखा करने की अनुमति दें?"</string>
<string name="app_list_preference_none" msgid="7100409177446935028">"कोई नहीं"</string>
- <string name="work_profile_usage_access_warning" msgid="403208064382097510">"इस ऐप के इस्तेमाल का एक्सेस बंद करने के बाद भी आपका एडमिन आपकी वर्क प्रोफ़ाइल के ऐप का डेटा खर्च ट्रैक कर सकते हैं"</string>
+ <string name="work_profile_usage_access_warning" msgid="403208064382097510">"इस ऐप के इस्तेमाल का ऐक्सेस बंद करने के बाद भी आपका एडमिन आपकी वर्क प्रोफ़ाइल के ऐप का डेटा खर्च ट्रैक कर सकते हैं"</string>
<string name="accessibility_lock_screen_progress" msgid="8242917828598820049">"<xliff:g id="COUNT_1">%2$d</xliff:g> में से <xliff:g id="COUNT_0">%1$d</xliff:g> वर्णों का उपयोग किया गया"</string>
<string name="draw_overlay" msgid="2878665072530660668">"दूसरे ऐप के ऊपर दिखाएं"</string>
<string name="system_alert_window_settings" msgid="3024330223417646567">"दूसरे ऐप के ऊपर दिखाएं"</string>
@@ -3809,7 +3809,7 @@
<string name="write_settings" msgid="9009040811145552108">"सिस्टम सेटिंग बदलें"</string>
<string name="keywords_write_settings" msgid="3450405263390246293">"सिस्टम सेटिंग में बदलाव करें लिखें"</string>
<string name="write_settings_summary" msgid="4650251358459404247">"<xliff:g id="COUNT_1">%2$d</xliff:g> में से <xliff:g id="COUNT_0">%1$d</xliff:g> ऐप्लिकेशन को सिस्टम सेटिंग बदलने की अनुमति दी गई"</string>
- <string name="financial_apps_sms_access_title" msgid="3422655018008259655">"वित्तीय ऐप्लिकेशन मैसेज (एसएमएस) एक्सेस"</string>
+ <string name="financial_apps_sms_access_title" msgid="3422655018008259655">"वित्तीय ऐप्लिकेशन मैसेज (एसएमएस) ऐक्सेस"</string>
<string name="filter_install_sources_apps" msgid="4519839764020866701">"अन्य ऐप्लिकेशन इंस्टॉल कर सकते हैं"</string>
<string name="filter_write_settings_apps" msgid="6864144615530081121">"सिस्टम सेटिंग को बदल सकते हैं"</string>
<string name="write_settings_title" msgid="5852614614193830632">"सिस्टम सेटिंग को बदल सकते हैं"</string>
@@ -4045,7 +4045,7 @@
<string name="display_cutout_emulation_keywords" msgid="6795671536772871439">"डिसप्ले कटआउट, नॉच"</string>
<string name="overlay_option_device_default" msgid="165508753381657697">"डिवाइस की डिफ़ॉल्ट सेटिंग"</string>
<string name="overlay_toast_failed_to_apply" msgid="5692251825129250040">"ओवरले लागू नहीं किया जा सका"</string>
- <string name="special_access" msgid="1453926335914696206">"ऐप्लिकेशन के लिए खास एक्सेस"</string>
+ <string name="special_access" msgid="1453926335914696206">"ऐप्लिकेशन के लिए खास ऐक्सेस"</string>
<plurals name="special_access_summary" formatted="false" msgid="5182092345063909346">
<item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ऐप्लिकेशन बिना पाबंदी के डेटा का उपयोग कर सकते हैं</item>
<item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ऐप्लिकेशन बिना पाबंदी के डेटा का उपयोग कर सकते हैं</item>
@@ -4062,7 +4062,7 @@
<string name="developer_smallest_width" msgid="2603134476228805075">"सबसे कम चौड़ाई की स्क्रीन सेट करें"</string>
<string name="premium_sms_none" msgid="940723020871007898">"इंस्टॉल किए गए किसी भी ऐप ने प्रीमियम मैसेज (एसएमएस) की पहुंच का अनुरोध नहीं किया है"</string>
<string name="premium_sms_warning" msgid="7604011651486294515">"प्रीमियम मैसेज (एसएमएस) के लिए आपको पैसे देने पड़ सकते हैं और इससे आपकी मोबाइल और इंटरनेट सेवा देने वाली कंपनी का बिल बढ़ जाएगा. अगर आप किसी ऐप के लिए अनुमति देते हैं, तो आप उस ऐप का इस्तेमाल करके प्रीमियम मैसेज (एसएमएस) भेज सकते हैं."</string>
- <string name="premium_sms_access" msgid="4550027460595822851">"प्रीमियम मैसेज (एसएमएस) का एक्सेस"</string>
+ <string name="premium_sms_access" msgid="4550027460595822851">"प्रीमियम मैसेज (एसएमएस) का ऐक्सेस"</string>
<string name="bluetooth_disabled" msgid="6588102116819268238">"बंद"</string>
<string name="bluetooth_connected_summary" msgid="439920840053965217">"<xliff:g id="ID_1">%1$s</xliff:g> से कनेक्ट है"</string>
<string name="bluetooth_connected_multiple_devices_summary" msgid="596205630653123250">"कई डिवाइस से कनेक्ट है"</string>
@@ -4079,7 +4079,7 @@
<string name="managed_profile_contact_search_summary" msgid="7278267480246726951">"कॉल करने वालों (कॉलर) और संपर्कों की पहचान करने के लिए अपने संगठन को संपर्क खोजने दें"</string>
<string name="cross_profile_calendar_title" msgid="2351605904015067145">"क्रॉस-प्रोफ़ाइल कैलेंडर"</string>
<string name="cross_profile_calendar_summary" msgid="3196258680438896098">"निजी कैलेंडर पर काम से जुड़े इवेंट दिखाएं"</string>
- <string name="cross_profile_calendar_restricted_summary" msgid="6892589892357409107">"आपका संगठन निजी ऐप्लिकेशन को आपके काम से जुड़े कैलेंडर का एक्सेस करने की अनुमति नहीं देता"</string>
+ <string name="cross_profile_calendar_restricted_summary" msgid="6892589892357409107">"आपका संगठन निजी ऐप्लिकेशन को आपके काम से जुड़े कैलेंडर का ऐक्सेस करने की अनुमति नहीं देता"</string>
<plurals name="hours" formatted="false" msgid="135936773984899873">
<item quantity="one"><xliff:g id="NUMBER">%s</xliff:g> घंटे</item>
<item quantity="other"><xliff:g id="NUMBER">%s</xliff:g> घंटे</item>
@@ -4376,7 +4376,7 @@
<string name="carrier_settings_title" msgid="7989949967020825268">"मोबाइल और इंटरनेट सेवा देने वाली कंपनी से जुड़ी सेटिंग"</string>
<string name="cdma_lte_data_service" msgid="8996857851150069339">"डेटा सेवा सेट अप करें"</string>
<string name="mobile_data_settings_title" msgid="3439626666647519547">"मोबाइल डेटा"</string>
- <string name="mobile_data_settings_summary" msgid="6492798151325636912">"मोबाइल नेटवर्क का इस्तेमाल करके डेटा एक्सेस करें"</string>
+ <string name="mobile_data_settings_summary" msgid="6492798151325636912">"मोबाइल नेटवर्क का इस्तेमाल करके डेटा ऐक्सेस करें"</string>
<string name="mobile_data_settings_summary_auto_switch" msgid="3665863214578471494">"नेटवर्क होने पर फ़ोन अपने आप इस कैरियर पर आ जाएगा"</string>
<string name="calls_preference" msgid="2076353032705811243">"कॉल की प्राथमिकता"</string>
<string name="sms_preference" msgid="8449270011976880">"मैसेज (एसएमएस) की प्राथमिकता"</string>
@@ -4434,7 +4434,7 @@
<string name="roaming_check_price_warning" msgid="5883499714594419439">"कीमतों की जानकारी के लिए आपको नेटवर्क सेवा देने वाली कंपनी से संपर्क करें."</string>
<string name="mobile_data_usage_title" msgid="2376358672434990037">"ऐप्लिकेशन का डेटा इस्तेमाल"</string>
<string name="mobile_network_mode_error" msgid="6818434186286086554">"गलत नेटवर्क मोड <xliff:g id="NETWORKMODEID">%1$d</xliff:g>. अनदेखा करें."</string>
- <string name="mobile_network_apn_title" msgid="5628635067747404382">"एक्सेस पॉइंट नाम"</string>
+ <string name="mobile_network_apn_title" msgid="5628635067747404382">"ऐक्सेस पॉइंट नाम"</string>
<string name="manual_mode_disallowed_summary" msgid="799800630000340665">"<xliff:g id="CARRIER">%1$s</xliff:g> से कनेक्ट होने पर उपलब्ध नहीं है"</string>
<string name="emergency_info_contextual_card_summary" msgid="5541444321969803486">"चिकित्सा से जुड़ी जानकारी, आपातकालीन संपर्क"</string>
<string name="see_more" msgid="7463940160389802632">"ज़्यादा देखें"</string>
@@ -4482,8 +4482,8 @@
</plurals>
<string name="accessibility_usage_title" msgid="3920601240120963611">"सुलभता सुविधाओं का इस्तेमाल"</string>
<plurals name="accessibility_usage_summary" formatted="false" msgid="2604152087205501644">
- <item quantity="one"><xliff:g id="SERVICE_COUNT">%1$d</xliff:g> ऐप्लिकेशन के पास आपके डिवाइस का पूरा एक्सेस है</item>
- <item quantity="other"><xliff:g id="SERVICE_COUNT">%1$d</xliff:g> ऐप्लिकेशन के पास आपके डिवाइस का पूरा एक्सेस है</item>
+ <item quantity="one"><xliff:g id="SERVICE_COUNT">%1$d</xliff:g> ऐप्लिकेशन के पास आपके डिवाइस का पूरा ऐक्सेस है</item>
+ <item quantity="other"><xliff:g id="SERVICE_COUNT">%1$d</xliff:g> ऐप्लिकेशन के पास आपके डिवाइस का पूरा ऐक्सेस है</item>
</plurals>
<string name="manage_app_notification" msgid="9072118910762792295">"<xliff:g id="APP_NAME">%1$s</xliff:g> की सूचनाएं प्रबंधित करें"</string>
<string name="no_suggested_app" msgid="509257628685025383">"कोई भी सुझाया गया ऐप्लिकेशन नहीं है"</string>
@@ -4500,7 +4500,7 @@
<string name="wfc_disclaimer_disagree_text" msgid="908289420390194127">"नहीं, धन्यवाद"</string>
<string name="wfc_disclaimer_location_title_text" msgid="5696194250838686019">"जगह"</string>
<string name="wfc_disclaimer_location_desc_text" msgid="3879710366995108723">"इस सेवा को उपलब्ध कराने के लिए मोबाइल नेटवर्क की सुविधा उपलब्ध कराने वाली कंपनी आपकी जगह की जानकारी इकट्ठा कर सकती है.\n\nकृपया कंपनी की निजता नीति को ध्यान से पढ़ें."</string>
- <string name="forget_passpoint_dialog_message" msgid="3337626966248310367">"आप बचे हुए समय या डेटा का एक्सेस खो सकते हैं. हटाने से पहले अपनी सेवा देने वाली कंपनी से पुष्टि कर लें."</string>
+ <string name="forget_passpoint_dialog_message" msgid="3337626966248310367">"आप बचे हुए समय या डेटा का ऐक्सेस खो सकते हैं. हटाने से पहले अपनी सेवा देने वाली कंपनी से पुष्टि कर लें."</string>
<string name="keywords_content_capture" msgid="5401877823529928976">"सामग्री कैप्चर, स्मार्ट सुझाव"</string>
<string name="content_capture" msgid="1709538093513983279">"स्मार्ट सुझाव"</string>
<string name="content_capture_summary" msgid="2675659095218714681">"Android को आपकी स्क्रीन पर दिखाई दे रही जानकारी, वीडियो या ऑडियो में सुनाई दे रही सामग्री सेव करने की अनुमति दें. Android आपके डिवाइस की गतिविधि के मुताबिक काम आने वाले सुझाव देता है."</string>
diff --git a/tests/CarDeveloperOptions/res/values-hr/strings.xml b/tests/CarDeveloperOptions/res/values-hr/strings.xml
index 9709c6f..801003e 100644
--- a/tests/CarDeveloperOptions/res/values-hr/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-hr/strings.xml
@@ -4170,13 +4170,13 @@
<string name="deletion_helper_manual_title" msgid="1011785013431162078">"Priručnik"</string>
<string name="deletion_helper_preference_title" msgid="797270307034242206">"Oslobodi prostor odmah"</string>
<string name="gesture_preference_title" msgid="583646591518373785">"Pokreti"</string>
- <string name="gesture_preference_summary" product="default" msgid="2990736567599191163">"Brzi pokreti za upravljanje telefonom"</string>
- <string name="gesture_preference_summary" product="tablet" msgid="8303793594714075580">"Brzi pokreti za upravljanje tabletom"</string>
- <string name="gesture_preference_summary" product="device" msgid="7792199669106960922">"Brzi pokreti za upravljanje uređajem"</string>
+ <string name="gesture_preference_summary" product="default" msgid="2990736567599191163">"Brze kretnje za upravljanje telefonom"</string>
+ <string name="gesture_preference_summary" product="tablet" msgid="8303793594714075580">"Brze kretnje za upravljanje tabletom"</string>
+ <string name="gesture_preference_summary" product="device" msgid="7792199669106960922">"Brze kretnje za upravljanje uređajem"</string>
<string name="double_tap_power_for_camera_title" msgid="5480829329052517484">"Otvaranje fotoaparata"</string>
<string name="double_tap_power_for_camera_summary" msgid="6591026425496323965">"Da biste brzo otvorili fotoaparat, dvaput pritisnite tipku za uključivanje/isključivanje. Funkcionira na svim zaslonima."</string>
<string name="double_tap_power_for_camera_suggestion_title" msgid="509078029429865036">"Brzo otvaranje fotoaparata"</string>
- <string name="double_twist_for_camera_mode_title" msgid="2606032140297556018">"Prebacivanje fotoaparata"</string>
+ <string name="double_twist_for_camera_mode_title" msgid="2606032140297556018">"Promjena fotoaparata"</string>
<string name="double_twist_for_camera_mode_summary" msgid="8979914206876018137"></string>
<string name="double_twist_for_camera_suggestion_title" msgid="5932411386316771246">"Brže snimanje selfieja"</string>
<string name="swipe_up_to_switch_apps_summary" msgid="4644068184114154787">"Da biste promijenili aplikaciju, prijeđite prstom prema gore po gumbu početnog zaslona. Ponovo prijeđite prstom prema gore da biste vidjeli sve aplikacije. Funkcionira na svim zaslonima. Više nećete imati gumb Pregled u donjem desnom kutu zaslona."</string>
diff --git a/tests/CarDeveloperOptions/res/values-hu/strings.xml b/tests/CarDeveloperOptions/res/values-hu/strings.xml
index cd36ce2..6a4d697 100644
--- a/tests/CarDeveloperOptions/res/values-hu/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-hu/strings.xml
@@ -1194,7 +1194,7 @@
<string name="auto_brightness_very_high_title" msgid="6649896560889239565">"Nagyon magas"</string>
<string name="auto_brightness_subtitle" msgid="8516999348793100665">"Előnyben részesített fényerőszint"</string>
<string name="auto_brightness_off_summary" msgid="6162650416289359104">"Ne módosuljon a rendelkezésre álló fény alapján"</string>
- <string name="auto_brightness_very_high_summary" msgid="7202032980509583918">"Megnövekedett akkumulátorhasználat"</string>
+ <string name="auto_brightness_very_high_summary" msgid="7202032980509583918">"Növeli az akkumulátorhasználatot"</string>
<string name="auto_brightness_disclaimer" msgid="5416696351199148809">"A fényerőt a rendelkezésre álló fényhez optimalizálja. Átmenetileg továbbra is módosíthatja a fényerőt, ha be van kapcsolva a funkció."</string>
<string name="auto_brightness_description" msgid="8209140379089535411">"A képernyő fényerőssége automatikusan alkalmazkodik a környezethez és az adott tevékenységhez. A csúszka manuális mozgatásával segít az alkalmazkodó fényerő funkciónak az Ön személyes preferenciáinak megtanulásában."</string>
<string name="display_white_balance_title" msgid="5747260735311935143">"Kijelző fehéregyensúlya"</string>
@@ -1257,7 +1257,7 @@
<string name="doze_title" msgid="235269029233857546">"Új értesítések"</string>
<string name="doze_summary" msgid="6762274282827831706">"Képernyő felébresztése értesítés érkezésekor"</string>
<string name="doze_always_on_title" msgid="8555184965031789941">"Mindig bekapcsolva"</string>
- <string name="doze_always_on_summary" msgid="7654436900436328950">"Az idő, az értesítési ikonok és egyéb információk megjelenítése. Megnövekedett akkumulátorhasználat."</string>
+ <string name="doze_always_on_summary" msgid="7654436900436328950">"Az idő, az értesítési ikonok és egyéb információk megjelenítése. Növeli az akkumulátorhasználatot."</string>
<string name="title_font_size" msgid="5021464556860010851">"Betűméret"</string>
<string name="short_summary_font_size" msgid="4141077908728522946">"Szöveg nagyítása és kicsinyítése"</string>
<string name="sim_lock_settings" msgid="1986924650622642189">"SIM-kártya lezárási beállításai"</string>
@@ -4124,7 +4124,7 @@
<string name="ambient_display_pickup_summary" product="default" msgid="8798915340594367449">"Az idő, az értesítések és egyéb információk megtekintéséhez vegye kezébe telefonját."</string>
<string name="ambient_display_pickup_summary" product="tablet" msgid="1077745287100012928">"Az idő, az értesítések és egyéb információk megtekintéséhez vegye a kezébe táblagépét."</string>
<string name="ambient_display_pickup_summary" product="device" msgid="404199660076598026">"Az idő, az értesítések és egyéb információk megtekintéséhez vegye kezébe eszközét."</string>
- <string name="ambient_display_tap_screen_title" product="default" msgid="2784322628239960695">"Koppintson a telefon megtekintéséhez"</string>
+ <string name="ambient_display_tap_screen_title" product="default" msgid="2784322628239960695">"Koppintás a telefon megtekintéséhez"</string>
<string name="ambient_display_tap_screen_title" product="tablet" msgid="6434521782016864148">"Koppintson a táblagép megtekintéséhez"</string>
<string name="ambient_display_tap_screen_title" product="device" msgid="4396793721852647356">"Koppintson az eszköz megtekintéséhez"</string>
<string name="ambient_display_tap_screen_summary" msgid="7869039870571925213">"Az idő, az értesítések és egyéb információk megtekintéséhez koppintson a képernyőre."</string>
diff --git a/tests/CarDeveloperOptions/res/values-hy/strings.xml b/tests/CarDeveloperOptions/res/values-hy/strings.xml
index 97158d9..15425d5 100644
--- a/tests/CarDeveloperOptions/res/values-hy/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-hy/strings.xml
@@ -370,7 +370,7 @@
<string name="Accounts_settings_title" msgid="7901374987121953746">"Հաշիվներ"</string>
<string name="location_settings_title" msgid="2707201457572301030">"Տեղադրություն"</string>
<string name="location_settings_master_switch_title" msgid="3108016866082816733">"Օգտագործել տեղորոշումը"</string>
- <string name="location_settings_summary_location_off" msgid="5563530256978372978">"Անջատած է"</string>
+ <string name="location_settings_summary_location_off" msgid="5563530256978372978">"Անջատված է"</string>
<plurals name="location_settings_summary_location_on" formatted="false" msgid="7893342914540884818">
<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>
@@ -561,7 +561,7 @@
<string name="unlock_set_unlock_launch_picker_title" msgid="2731152716948003853">"Էկրանի կողպում"</string>
<string name="unlock_set_unlock_launch_picker_summary_lock_immediately" msgid="5596186270725220642">"<xliff:g id="UNLOCK_METHOD">%1$s</xliff:g> / Անմիջապես քնից հետո"</string>
<string name="unlock_set_unlock_launch_picker_summary_lock_after_timeout" msgid="3861167251234952373">"<xliff:g id="UNLOCK_METHOD">%1$s</xliff:g> / <xliff:g id="TIMEOUT_STRING">%2$s</xliff:g> քնից հետո"</string>
- <string name="unlock_set_unlock_launch_picker_title_profile" msgid="7976345264630422921">"Աշխատանքային պրոֆիլի փական"</string>
+ <string name="unlock_set_unlock_launch_picker_title_profile" msgid="7976345264630422921">"Աշխ․ պրոֆիլի կողպում"</string>
<string name="unlock_set_unlock_launch_picker_change_title" msgid="32310692507029407">"Փոխել էկրանի կողպումը"</string>
<string name="unlock_set_unlock_launch_picker_change_summary" msgid="2072792784866320522">"Փոխել կամ կասեցնել նախշը, PIN-ը կամ գաղտնաբառի անվտանգությունը"</string>
<string name="unlock_set_unlock_launch_picker_enable_summary" msgid="9070847611379078795">"Ընտրել էկրանի կողպման եղանակը"</string>
@@ -828,7 +828,7 @@
<string name="nfc_secure_toggle_summary" product="default" msgid="7631183023440112192">"Թույլատրել NFC-ի միջոցով վճարումներն ու տվյալների փոխանցումը միայն, երբ էկրանն ապակողպված է"</string>
<string name="android_beam_settings_title" msgid="3083436415873738389">"Android Beam"</string>
<string name="android_beam_on_summary" msgid="8068287225180474199">"Տվյալների փոխանակում NFC-ով"</string>
- <string name="android_beam_off_summary" msgid="7365818039159364600">"Անջատած է"</string>
+ <string name="android_beam_off_summary" msgid="7365818039159364600">"Անջատված է"</string>
<string name="nfc_disabled_summary" msgid="2181777971122724361">"Անհասանելի է, քանի որ NFC-ն անջատված է"</string>
<string name="android_beam_label" msgid="5340299879556025708">"Android Beam"</string>
<string name="android_beam_explained" msgid="4501176353247859329">"Այս գործառույթը թույլ է տալիս մեկ սարքից մյուսին փոխանցել տարբեր տեսակի բովանդակություն (այդ թվում կոնտակտներ, վեբ էջեր և տեսանյութեր)՝ սարքերը միմյանց մոտ պահելով:\n\nՊարզապես մոտեցրեք սարքերը միմյանց (հիմնականում հետևի մասերով իրար) և հպեք ձեր էկրանին: Հավելվածը կորոշի, թե ինչ տվյալներ փոխանցել։"</string>
@@ -1213,7 +1213,7 @@
<string name="night_display_end_time_title" msgid="2760793157124245911">"Ավարտ"</string>
<string name="night_display_status_title" msgid="1727020934735770319">"Կարգավիճակ"</string>
<string name="night_display_temperature_title" msgid="8375126629902616296">"Ինտենսիվություն"</string>
- <string name="night_display_summary_off" msgid="8850539785332228069">"Անջատած է / <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="night_display_summary_off" msgid="8850539785332228069">"Անջատված է / <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="night_display_summary_off_auto_mode_never" msgid="8618824386434992487">"Ավտոմատ չի միանա"</string>
<string name="night_display_summary_off_auto_mode_custom" msgid="596847003171394411">"Ավտոմատ կմիանա <xliff:g id="ID_1">%1$s</xliff:g>-ին"</string>
<string name="night_display_summary_off_auto_mode_twilight" msgid="4071750976585359952">"Ավտոմատ կմիանա մայրամուտին"</string>
@@ -1459,7 +1459,7 @@
<string name="storage_wizard_init_internal_title" msgid="8750856962785644870">"Օգտագործել որպես ներքին հիշողություն"</string>
<string name="storage_wizard_init_internal_summary" msgid="4510546464921608029">"Հավելվածները, լուսանկարները և այլ բաներ միայն այս սարքի վրա պահեստավորելու համար: Հարկավոր է ձևաչափում, որի արդյունքում այն չի աշխատի այլ սարքերի վրա:"</string>
<string name="storage_wizard_format_confirm_title" msgid="7785358616068633439">"Ձևաչափել որպես ներքին պահեստ"</string>
- <string name="storage_wizard_format_confirm_body" msgid="4107762933332992624">"<xliff:g id="NAME_0">^1</xliff:g>-ի անվտանգությունը ապահովելու համար այն պետք է ձևաչափել: \n\nՈրից հետո այս <xliff:g id="NAME_1">^1</xliff:g>-ը կաշխատի միայն այս սարքի վրա: \n\n"<b>"Ձևաչափումից հետո <xliff:g id="NAME_2">^1</xliff:g>-ի վրա պահեստավորված բոլոր տվյալները կջնջվեն:"</b>" Տվյալները չկորցնելու համար չմոռանաք նախ պահուստավորել դրանք:"</string>
+ <string name="storage_wizard_format_confirm_body" msgid="4107762933332992624">"<xliff:g id="NAME_0">^1</xliff:g>-ի անվտանգությունը ապահովելու համար այն պետք է ձևաչափել: \n\nԴրանից հետո այս <xliff:g id="NAME_1">^1</xliff:g>-ը կաշխատի միայն այս սարքի վրա: \n\n"<b>"Ձևաչափումից հետո <xliff:g id="NAME_2">^1</xliff:g>-ի վրա պահեստավորված բոլոր տվյալները կջնջվեն:"</b>" Տվյալները չկորցնելու համար չմոռանաք նախ պահուստավորել դրանք:"</string>
<string name="storage_wizard_format_confirm_public_title" msgid="5866830103788091426">"Ձևաչափել որպես կրիչ"</string>
<string name="storage_wizard_format_confirm_public_body" msgid="1451308701654703353">"Հարկավոր է ձևաչափել <xliff:g id="NAME_0">^1</xliff:g>-ը: \n\n"<b>"Ձևաչափման արդյունքում <xliff:g id="NAME_1">^1</xliff:g>-ի վրա պահեստավորած բոլոր տվյալները կջնջվեն:"</b>" Եթե չեք ցանկանում կորցնել տվյալները, նախապես պահուստավորեք դրանք:"</string>
<string name="storage_wizard_format_confirm_next" msgid="236947984802247625">"Ջնջել և ձևաչափել"</string>
@@ -2103,7 +2103,7 @@
<item quantity="other"><xliff:g id="NUMBER_DEVICE_COUNT_1">%1$d</xliff:g> պահված լսողական ապարատներ</item>
</plurals>
<string name="accessibility_summary_state_enabled" msgid="7357731696603247963">"Միացված է"</string>
- <string name="accessibility_summary_state_disabled" msgid="9197369047683087620">"Անջատած է"</string>
+ <string name="accessibility_summary_state_disabled" msgid="9197369047683087620">"Անջատված է"</string>
<string name="accessibility_summary_state_stopped" msgid="3170264683616172746">"Չի աշխատում: Տեղեկությունների համար հպեք:"</string>
<string name="accessibility_description_state_stopped" msgid="7666178628053039493">"Այս ծառայությունը նորմալ չի աշխատում:"</string>
<string name="enable_quick_setting" msgid="1580451877998661255">"Ցույց տալ Արագ կարգավորումներում"</string>
@@ -2329,7 +2329,7 @@
<string name="battery_auto_restriction_title" msgid="488905332794794076">"Օգտագործել մարտկոցի կառավարիչը"</string>
<string name="battery_auto_restriction_summary" msgid="1638072655581821837">"Հայտնաբերել հավելվածները, որոնք արագ սպառում են մարտկոցի լիցքը"</string>
<string name="battery_manager_on" msgid="5626982529932239656">"Միացված է – Մարտկոցի լիցքն արագ սպառող հավելվածների հայտնաբերում"</string>
- <string name="battery_manager_off" msgid="9114027524232450371">"Անջատած է"</string>
+ <string name="battery_manager_off" msgid="9114027524232450371">"Անջատված է"</string>
<plurals name="battery_manager_app_restricted" formatted="false" msgid="6721813588142691216">
<item quantity="one">Սահմանափակված է %1$d հավելված</item>
<item quantity="other">Սահմանափակված է %1$d հավելված</item>
@@ -3234,7 +3234,7 @@
<string name="zen_interruption_level_priority" msgid="9178419297408319234">"Միայն կարևորները"</string>
<string name="zen_mode_and_condition" msgid="4123722186007123567">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>։ <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
<string name="zen_mode_sound_summary_on_with_info" msgid="2539952366467518398">"Միացված է/<xliff:g id="ID_1">%1$s</xliff:g>"</string>
- <string name="zen_mode_sound_summary_off_with_info" msgid="3910718455243440265">"Անջատած է/<xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="zen_mode_sound_summary_off_with_info" msgid="3910718455243440265">"Անջատված է/<xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="zen_mode_sound_summary_off" msgid="2800265178411749309">"Անջատված է"</string>
<string name="zen_mode_sound_summary_on" msgid="6964666541479146310">"Միացված է"</string>
<string name="zen_mode_duration_summary_always_prompt" msgid="7642321938427056823">"Հարցնել ամեն անգամ (եթե ավտոմատ չմիանա)"</string>
@@ -3400,8 +3400,8 @@
<string name="app_settings_link" msgid="8465287765715790984">"Հավելվածի լրացուցիչ կարգավորումները"</string>
<string name="app_notification_listing_summary_zero" msgid="4047782719487686699">"Միացված է բոլոր հավելվածների համար"</string>
<plurals name="app_notification_listing_summary_others" formatted="false" msgid="1161774065480666519">
- <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_1">%d</xliff:g> հավելվածի համար</item>
+ <item quantity="other">Անջատված է <xliff:g id="COUNT_1">%d</xliff:g> հավելվածի համար</item>
</plurals>
<plurals name="deleted_channels" formatted="false" msgid="7741359084299446208">
<item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> categories deleted</item>
@@ -3996,7 +3996,7 @@
<string name="suggestion_additional_fingerprints_summary" msgid="1916547587832484196">"Ապակողպում այլ մատով"</string>
<string name="battery_saver_on_summary" msgid="6841062406467435672">"Միացված է"</string>
<string name="battery_saver_off_scheduled_summary" msgid="3740414764069188669">"Միանում է լիցքի <xliff:g id="BATTERY_PERCENTAGE">%1$s</xliff:g>-ի դեպքում"</string>
- <string name="battery_saver_off_summary" msgid="8736555723004299721">"Անջատած է"</string>
+ <string name="battery_saver_off_summary" msgid="8736555723004299721">"Անջատված է"</string>
<string name="battery_saver_button_turn_on" msgid="3748696527267573793">"Միացնել հիմա"</string>
<string name="battery_saver_button_turn_off" msgid="2912950982503267828">"Անջատել հիմա"</string>
<string name="not_battery_optimizing" msgid="2616044774307734160">"Մարտկոցի օպտիմալացումը չի օգտագործվում"</string>
@@ -4329,7 +4329,7 @@
<string name="homepage_all_settings" msgid="3201220879559136116">"Բոլոր կարգավորումները"</string>
<string name="homepage_personal_settings" msgid="7472638597249114564">"Հուշումներ"</string>
<string name="choose_network_title" msgid="3213314359630522396">"Ընտրել ցանց"</string>
- <string name="network_disconnected" msgid="8677203031237141594">"Անջատած է"</string>
+ <string name="network_disconnected" msgid="8677203031237141594">"Անջատված է"</string>
<string name="network_connected" msgid="8197627827976712053">"Միացած է"</string>
<string name="network_connecting" msgid="8798611458457547110">"Միացում…"</string>
<string name="network_could_not_connect" msgid="552874922030763713">"Չհաջողվեց միանալ"</string>
diff --git a/tests/CarDeveloperOptions/res/values-in/strings.xml b/tests/CarDeveloperOptions/res/values-in/strings.xml
index a0b6804..d7e79d6 100644
--- a/tests/CarDeveloperOptions/res/values-in/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-in/strings.xml
@@ -3088,7 +3088,7 @@
<string name="keywords_profile_challenge" msgid="8653718001253979611">"tantangan kerja, kerja, profil"</string>
<string name="keywords_unification" msgid="2020759909366983593">"profil kerja, profil yang dikelola, menyatukan, penyatuan, kerja, profil"</string>
<string name="keywords_gesture" msgid="5031323247529869644">"gestur"</string>
- <string name="keywords_payment_settings" msgid="4745023716567666052">"bayar, tap, pembayaran"</string>
+ <string name="keywords_payment_settings" msgid="4745023716567666052">"bayar, ketuk, pembayaran"</string>
<string name="keywords_backup" msgid="7433356270034921627">"backup, back up"</string>
<string name="keywords_assist_gesture_launch" msgid="2711433664837843513">"gestur"</string>
<string name="keywords_face_unlock" msgid="651615819291927262">"wajah, buka kunci, autentikasi, login"</string>
@@ -4104,7 +4104,7 @@
<string name="gesture_preference_summary" product="default" msgid="2990736567599191163">"Isyarat cepat untuk mengontrol ponsel"</string>
<string name="gesture_preference_summary" product="tablet" msgid="8303793594714075580">"Isyarat cepat untuk mengontrol tablet"</string>
<string name="gesture_preference_summary" product="device" msgid="7792199669106960922">"Isyarat cepat untuk mengontrol perangkat"</string>
- <string name="double_tap_power_for_camera_title" msgid="5480829329052517484">"Beralih ke kamera"</string>
+ <string name="double_tap_power_for_camera_title" msgid="5480829329052517484">"Buka kamera"</string>
<string name="double_tap_power_for_camera_summary" msgid="6591026425496323965">"Untuk membuka kamera dengan cepat, tekan tombol power 2 kali. Berfungsi di layar mana pun."</string>
<string name="double_tap_power_for_camera_suggestion_title" msgid="509078029429865036">"Buka kamera dengan cepat"</string>
<string name="double_twist_for_camera_mode_title" msgid="2606032140297556018">"Balik kamera"</string>
diff --git a/tests/CarDeveloperOptions/res/values-ja/strings.xml b/tests/CarDeveloperOptions/res/values-ja/strings.xml
index bb47e1d..7f8bea3 100644
--- a/tests/CarDeveloperOptions/res/values-ja/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-ja/strings.xml
@@ -390,7 +390,7 @@
<string name="security_passwords_title" msgid="6853942836045862315">"プライバシー"</string>
<string name="disabled_by_administrator_summary" msgid="6099821045360491127">"管理者により無効にされています"</string>
<string name="security_status_title" msgid="1261960357751754428">"セキュリティ ステータス"</string>
- <string name="security_dashboard_summary_face" msgid="2536136110153593745">"画面ロック、フェイス アンロック"</string>
+ <string name="security_dashboard_summary_face" msgid="2536136110153593745">"画面ロック、顔認証"</string>
<string name="security_dashboard_summary" msgid="4048877125766167227">"画面ロック、指紋"</string>
<string name="security_dashboard_summary_no_fingerprint" msgid="8861903321053490658">"画面ロック"</string>
<string name="security_settings_face_preference_summary" msgid="4437701024542221434">"顔を追加しました"</string>
@@ -427,7 +427,7 @@
<string name="security_settings_face_settings_remove_face_data" msgid="2821359954483136239">"顔認証データを削除"</string>
<string name="security_settings_face_settings_footer" msgid="4627175759990550715">"顔認証でデバイスのロックを解除したり、アプリにアクセスしたりできます。"<annotation id="url">"詳細"</annotation></string>
<string name="security_settings_face_settings_remove_dialog_title" msgid="5675319895815271094">"顔認証データを削除しますか?"</string>
- <string name="security_settings_face_settings_remove_dialog_details" msgid="3754494807169276107">"フェイスアンロックによって記録されたデータは安全かつ完全に削除されます。削除後に、スマートフォンのロック解除、アプリへのログイン、お支払いの確認を行うには、PIN、パターン、パスワードのいずれかが必要になります。"</string>
+ <string name="security_settings_face_settings_remove_dialog_details" msgid="3754494807169276107">"顔認証によって記録されたデータは安全かつ完全に削除されます。削除後に、スマートフォンのロック解除、アプリへのログイン、お支払いの確認を行うには、PIN、パターン、パスワードのいずれかが必要になります。"</string>
<string name="security_settings_fingerprint_preference_title" msgid="4177132225930582928">"指紋"</string>
<string name="fingerprint_manage_category_title" msgid="1463406696801542090">"指紋の管理"</string>
<string name="fingerprint_usage_category_title" msgid="7298369141954599706">"指紋の用途"</string>
@@ -3087,11 +3087,11 @@
<string name="keywords_lockscreen" msgid="4936846554280830394">"スライドでロック解除、パスワード、パターン、PIN"</string>
<string name="keywords_profile_challenge" msgid="8653718001253979611">"ワーク チャレンジ, 仕事用, プロファイル"</string>
<string name="keywords_unification" msgid="2020759909366983593">"仕事用プロファイル, 管理対象プロファイル, 統合する, 統合, 仕事, プロファイル"</string>
- <string name="keywords_gesture" msgid="5031323247529869644">"操作"</string>
+ <string name="keywords_gesture" msgid="5031323247529869644">"ジェスチャー"</string>
<string name="keywords_payment_settings" msgid="4745023716567666052">"支払い, タップ, ペイメント"</string>
<string name="keywords_backup" msgid="7433356270034921627">"バックアップ, バック アップ"</string>
<string name="keywords_assist_gesture_launch" msgid="2711433664837843513">"操作"</string>
- <string name="keywords_face_unlock" msgid="651615819291927262">"顔, フェイス, ロック解除, アンロック, 認証, ログイン"</string>
+ <string name="keywords_face_unlock" msgid="651615819291927262">"顔, フェイス, ロック解除, アンロック, 認証, ログイン, 顔認証"</string>
<string name="keywords_imei_info" msgid="4325847870422053408">"IMEI, MEID, MIN, PRL バージョン, IMEI SV"</string>
<string name="keywords_sim_status" msgid="3852088576719874387">"ネットワーク, モバイル ネットワークの状態, サービスの状態, 電波強度, モバイル ネットワークの種類, ローミング, ICCID"</string>
<string name="keywords_model_and_hardware" msgid="2743197096210895251">"シリアル番号, ハードウェア バージョン"</string>
@@ -4100,7 +4100,7 @@
<string name="deletion_helper_automatic_title" msgid="4370975149425263205">"自動"</string>
<string name="deletion_helper_manual_title" msgid="1011785013431162078">"手動"</string>
<string name="deletion_helper_preference_title" msgid="797270307034242206">"今すぐ空き容量を増やす"</string>
- <string name="gesture_preference_title" msgid="583646591518373785">"操作"</string>
+ <string name="gesture_preference_title" msgid="583646591518373785">"ジェスチャー"</string>
<string name="gesture_preference_summary" product="default" msgid="2990736567599191163">"簡単な操作でスマートフォンを管理できます"</string>
<string name="gesture_preference_summary" product="tablet" msgid="8303793594714075580">"簡単な操作でタブレットを管理できます"</string>
<string name="gesture_preference_summary" product="device" msgid="7792199669106960922">"簡単な操作でデバイスを管理できます"</string>
diff --git a/tests/CarDeveloperOptions/res/values-kn/strings.xml b/tests/CarDeveloperOptions/res/values-kn/strings.xml
index b9b14d4..a361d01 100644
--- a/tests/CarDeveloperOptions/res/values-kn/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-kn/strings.xml
@@ -505,7 +505,7 @@
<string name="fingerprint_delete_message" msgid="5895802741486967970">"ನೀವು ಈ ಫಿಂಗರ್ ಫ್ರಿಂಟ್ ಅಳಿಸಲು ಬಯಸುವಿರಾ?"</string>
<string name="fingerprint_last_delete_message" msgid="3346252479778971442">"ನಿಮ್ಮ ಫೋನ್ ಅನ್ಲಾಕ್ ಮಾಡಲು, ಖರೀದಿಗಳನ್ನು ದೃಢೀಕರಿಸಲು ಅಥವಾ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗೆ ಸೈನ್ ಇನ್ ಮಾಡಲು ನಿಮ್ಮ ಫಿಂಗರ್ ಪ್ರಿಂಟ್ಗಳನ್ನು ಬಳಸಲು ನಿಮಗೆ ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ."</string>
<string name="fingerprint_last_delete_message_profile_challenge" msgid="5385095150532247025">"ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್ ಅನ್ಲಾಕ್ ಮಾಡಲು, ಖರೀದಿಗಳನ್ನು ದೃಢೀಕರಿಸಲು ಅಥವಾ ಕೆಲಸದ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗೆ ಸೈನ್ ಇನ್ ಮಾಡಲು ನಿಮ್ಮ ಫಿಂಗರ್ ಪ್ರಿಂಟ್ಗಳನ್ನು ಬಳಸಲು ನಿಮಗೆ ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ."</string>
- <string name="fingerprint_last_delete_confirm" msgid="7984595457589664004">"ಹೌದು, ತೆಗೆದುಹಾಕು"</string>
+ <string name="fingerprint_last_delete_confirm" msgid="7984595457589664004">"ಹೌದು, ತೆಗೆದುಹಾಕಿ"</string>
<string name="crypt_keeper_settings_title" msgid="839783588093862748">"ಎನ್ಕ್ರಿಪ್ಷನ್"</string>
<string name="crypt_keeper_encrypt_title" product="tablet" msgid="2292129135369853167">"ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡು"</string>
<string name="crypt_keeper_encrypt_title" product="default" msgid="3110852053238357832">"ಫೋನ್ ಎನ್ಕ್ರಿಪ್ಟ್"</string>
@@ -629,7 +629,7 @@
<string name="unlock_disable_frp_warning_content_unknown_fingerprint_profile" msgid="1201259228331105948">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಇಲ್ಲದೆ ಪ್ರೊಫೈಲ್ ರಕ್ಷಣೆ ವೈಶಿಷ್ಟ್ಯಗಳು ಕಾರ್ಯನಿರ್ವಹಿಸುವುದಿಲ್ಲ.<xliff:g id="EMPTY_LINE">
</xliff:g>ಈ ಪ್ರೊಫೈಲ್ನಿಂದ ನಿಮ್ಮ ಉಳಿಸಲಾದ ಫಿಂಗರ್ಪ್ರಿಂಟ್ಗಳನ್ನು ಸಹ ತೆಗೆದುಹಾಕಲಾಗುವುದು ಮತ್ತು ನಿಮ್ಮ ಫೋನ್ ಅನ್ಲಾಕ್ ಮಾಡಲು, ಖರೀದಿಗಳನ್ನು ದೃಢೀಕರಿಸಲು ಅಥವಾ ಅವುಗಳ ಮೂಲಕ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗೆ ಸೈನ್ ಇನ್ ಮಾಡಲು ನಿಮಗೆ ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ."</string>
- <string name="unlock_disable_frp_warning_ok" msgid="2373890505202766456">"ಹೌದು, ತೆಗೆದುಹಾಕು"</string>
+ <string name="unlock_disable_frp_warning_ok" msgid="2373890505202766456">"ಹೌದು, ತೆಗೆದುಹಾಕಿ"</string>
<string name="unlock_change_lock_pattern_title" msgid="7622476883851319877">"ಅನ್ಲಾಕ್ ನಮೂನೆಯನ್ನು ಬದಲಾಯಿಸಿ"</string>
<string name="unlock_change_lock_pin_title" msgid="6671224158800812238">"ಅನ್ಲಾಕ್ ಪಿನ್ ಬದಲಾಯಿಸಿ"</string>
<string name="unlock_change_lock_password_title" msgid="7886432065775170719">"ಅನ್ಲಾಕ್ ಪಾಸ್ವರ್ಡ್ ಬದಲಾಯಿಸಿ"</string>
@@ -1265,14 +1265,14 @@
<string name="sim_lock_settings_summary_off" msgid="348656447968142307">"ಆಫ್"</string>
<string name="sim_lock_settings_summary_on" msgid="3440707542514810045">"ಲಾಕ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="sim_lock_settings_title" msgid="877336472752342977">"ಸಿಮ್ ಕಾರ್ಡ್ ಲಾಕ್"</string>
- <string name="sim_pin_toggle" msgid="2026507420678167488">"ಸಿಮ್ ಕಾರ್ಡ್ ಲಾಕ್ ಮಾಡು"</string>
+ <string name="sim_pin_toggle" msgid="2026507420678167488">"ಸಿಮ್ ಕಾರ್ಡ್ ಲಾಕ್ ಮಾಡಿ"</string>
<string name="sim_lock_on" product="tablet" msgid="3917977767884071323">"ಟ್ಯಾಬ್ಲೆಟ್ ಬಳಸಲು ಪಿನ್ ಅಗತ್ಯವಿದೆ"</string>
<string name="sim_lock_on" product="default" msgid="1363159192182487883">"ಫೋನ್ ಬಳಸಲು ಪಿನ್ ಅಗತ್ಯವಿದೆ"</string>
<string name="sim_lock_off" product="tablet" msgid="8428566346685080195">"ಟ್ಯಾಬ್ಲೆಟ್ ಬಳಸಲು ಪಿನ್ ಅಗತ್ಯವಿದೆ"</string>
<string name="sim_lock_off" product="default" msgid="5873747770983496755">"ಫೋನ್ ಬಳಸಲು ಪಿನ್ ಅಗತ್ಯವಿದೆ"</string>
<string name="sim_pin_change" msgid="5615972926944053213">"ಸಿಮ್ ಪಿನ್ ಬದಲಾಯಿಸು"</string>
<string name="sim_enter_pin" msgid="149201344579560481">"ಸಿಮ್ ಪಿನ್"</string>
- <string name="sim_enable_sim_lock" msgid="4478794975656337476">"ಸಿಮ್ ಕಾರ್ಡ್ ಲಾಕ್ ಮಾಡು"</string>
+ <string name="sim_enable_sim_lock" msgid="4478794975656337476">"ಸಿಮ್ ಕಾರ್ಡ್ ಲಾಕ್ ಮಾಡಿ"</string>
<string name="sim_disable_sim_lock" msgid="394864376519820956">"ಸಿಮ್ ಕಾರ್ಡ್ ಅನ್ಲಾಕ್ ಮಾಡು"</string>
<string name="sim_enter_old" msgid="8984991229691526849">"ಹಳೆಯ ಸಿಮ್ ಪಿನ್"</string>
<string name="sim_enter_new" msgid="1720792957661107585">"ಹೊಸ ಸಿಮ್ ಪಿನ್"</string>
@@ -3785,7 +3785,7 @@
<string name="zen_access_revoke_warning_dialog_title" msgid="6850994585577513299">"<xliff:g id="APP">%1$s</xliff:g> ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅಡಚಣೆ ಮಾಡಬೇಡಿಗೆ ಪ್ರವೇಶವನ್ನು ಹಿಂತೆಗೆದುಕೊಳ್ಳುವುದೇ?"</string>
<string name="zen_access_revoke_warning_dialog_summary" msgid="3487422193181311403">"ಈ ಅಪ್ಲಿಕೇಶನ್ ರಚಿಸಿರುವಂತಹ ಎಲ್ಲ ಅಡಚಣೆ ಮಾಡಬೇಡಿ ನಿಯಮಗಳನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ."</string>
<string name="ignore_optimizations_on" msgid="4373971641328943551">"ಆಪ್ಟಿಮೈಸ್ ಮಾಡಬೇಡಿ"</string>
- <string name="ignore_optimizations_off" msgid="4372289432580282870">"ಆಪ್ಟಿಮೈಸ್ ಮಾಡು"</string>
+ <string name="ignore_optimizations_off" msgid="4372289432580282870">"ಆಪ್ಟಿಮೈಸ್ ಮಾಡಿ"</string>
<string name="ignore_optimizations_on_desc" msgid="2904484569799521559">"ನಿಮ್ಮ ಬ್ಯಾಟರಿಯನ್ನು ತ್ವರಿತವಾಗಿ ಬರಿದಾಗಿಸಬಹುದು. ಹಿನ್ನೆಲೆ ಬ್ಯಾಟರಿ ಬಳಸದಂತೆ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಇನ್ನು ಮುಂದೆ ನಿರ್ಬಂಧಿಸಲಾಗುವುದಿಲ್ಲ."</string>
<string name="ignore_optimizations_off_desc" msgid="5598702251817814289">"ಉತ್ತಮ ಬ್ಯಾಟರಿ ಬಾಳಿಕೆಗೆ ಶಿಫಾರಸು ಮಾಡಲಾಗಿದೆ"</string>
<string name="ignore_optimizations_title" msgid="7924345545276166305">"ಬ್ಯಾಟರಿ ಆಪ್ಟಿಮೈಸೇಶನ್ಗಳನ್ನು ಕಡೆಗಣಿಸಲು <xliff:g id="APP">%s</xliff:g> ಗೆ ಅನುಮತಿಸುವುದೇ?"</string>
diff --git a/tests/CarDeveloperOptions/res/values-ky/strings.xml b/tests/CarDeveloperOptions/res/values-ky/strings.xml
index 842eeae..0335fbd 100644
--- a/tests/CarDeveloperOptions/res/values-ky/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-ky/strings.xml
@@ -4123,9 +4123,9 @@
<string name="ambient_display_pickup_summary" product="default" msgid="8798915340594367449">"Убакытты, билдирмелерди жана башка маалыматты көрүү үчүн телефонуңузду колуңузга алыңыз."</string>
<string name="ambient_display_pickup_summary" product="tablet" msgid="1077745287100012928">"Убакытты, билдирмелерди жана башка маалыматты көрүү үчүн планшетиңизди колуңузга алыңыз."</string>
<string name="ambient_display_pickup_summary" product="device" msgid="404199660076598026">"Убакытты, билдирмелерди жана башка маалыматты көрүү үчүн түзмөгүңүздү колуңузга алыңыз."</string>
- <string name="ambient_display_tap_screen_title" product="default" msgid="2784322628239960695">"Телефонду текшерүү үчүн таптап коюңуз"</string>
- <string name="ambient_display_tap_screen_title" product="tablet" msgid="6434521782016864148">"Планшетти текшерүү үчүн таптап коюңуз"</string>
- <string name="ambient_display_tap_screen_title" product="device" msgid="4396793721852647356">"Түзмөктү текшерүү үчүн таптап коюңуз"</string>
+ <string name="ambient_display_tap_screen_title" product="default" msgid="2784322628239960695">"Телефонду текшерүү үчүн басып коюу"</string>
+ <string name="ambient_display_tap_screen_title" product="tablet" msgid="6434521782016864148">"Планшетти текшерүү үчүн басып коюу"</string>
+ <string name="ambient_display_tap_screen_title" product="device" msgid="4396793721852647356">"Түзмөктү текшерүү үчүн басып коюу"</string>
<string name="ambient_display_tap_screen_summary" msgid="7869039870571925213">"Убакытты, билдирмелерди жана башка маалыматты көрүү үчүн экранды таптап коюңуз."</string>
<string name="fingerprint_swipe_for_notifications_title" msgid="3676002930672489760">"Билдирмелерди манжа изинин сенсору менен көрүү"</string>
<string name="fingerprint_gesture_screen_title" msgid="8638932855807473479">"Манжа изинин сканери"</string>
diff --git a/tests/CarDeveloperOptions/res/values-lt/strings.xml b/tests/CarDeveloperOptions/res/values-lt/strings.xml
index 223ed52..55db92b 100644
--- a/tests/CarDeveloperOptions/res/values-lt/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-lt/strings.xml
@@ -4262,7 +4262,7 @@
<string name="ambient_display_pickup_summary" product="default" msgid="8798915340594367449">"Norėdami sužinoti laiką, peržiūrėti pranešimus ir kitą informaciją, paimkite telefoną."</string>
<string name="ambient_display_pickup_summary" product="tablet" msgid="1077745287100012928">"Norėdami sužinoti laiką, peržiūrėti pranešimus ir kitą informaciją, paimkite planšetinį kompiuterį."</string>
<string name="ambient_display_pickup_summary" product="device" msgid="404199660076598026">"Norėdami sužinoti laiką, peržiūrėti pranešimus ir kitą informaciją, paimkite įrenginį."</string>
- <string name="ambient_display_tap_screen_title" product="default" msgid="2784322628239960695">"Palieskite, kad patikrintumėte telefoną"</string>
+ <string name="ambient_display_tap_screen_title" product="default" msgid="2784322628239960695">"Telefono tikrinimas palietus"</string>
<string name="ambient_display_tap_screen_title" product="tablet" msgid="6434521782016864148">"Palieskite, kad patikrintumėte planšetinį kompiuterį"</string>
<string name="ambient_display_tap_screen_title" product="device" msgid="4396793721852647356">"Palieskite, kad patikrintumėte įrenginį"</string>
<string name="ambient_display_tap_screen_summary" msgid="7869039870571925213">"Norėdami sužinoti laiką, peržiūrėti pranešimus ir kitą informaciją, palieskite ekraną."</string>
diff --git a/tests/CarDeveloperOptions/res/values-my/strings.xml b/tests/CarDeveloperOptions/res/values-my/strings.xml
index 172be49..0b152fe 100644
--- a/tests/CarDeveloperOptions/res/values-my/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-my/strings.xml
@@ -383,7 +383,7 @@
<string name="decryption_settings_summary" product="default" msgid="7401802133199522441">"ဖုန်းကို အသွင်ဝှက်မထားပါ"</string>
<string name="encryption_and_credential_settings_summary" product="tablet" msgid="8170667308598998791">"စက်ပစ္စည်းကို အသွင်ဝှက်ထားသည်"</string>
<string name="decryption_settings_summary" product="tablet" msgid="7524119945312453569">"စက်ပစ္စည်းကို အသွင်ဝှက်မထားပါ"</string>
- <string name="lockscreen_settings_title" msgid="1221505938891948413">"လော့ခ်ချထားချိန် မျက်နှာပြင်ပြသမှု"</string>
+ <string name="lockscreen_settings_title" msgid="1221505938891948413">"လော့ခ်ချထားချိန် ဖန်သားပြင်ပြသမှု"</string>
<string name="lockscreen_settings_what_to_show_category" msgid="3133378945821488654">"ပြသမည့်အရာ"</string>
<string name="security_settings_summary" msgid="5210109100643223686">"ကျွန်ုပ်၏တည်နေရာ စကရင်ကိုသော့ဖွင့်ခြင်း ဆင်းမ်ကဒ်သော့ချခြင်း ယုံကြည်စိတ်ချရသောသိုလှောင်ရာနေရာတို့ကို သတ်မှတ်မည်"</string>
<string name="cdma_security_settings_summary" msgid="1783066617800041869">"ကျွန်ုပ်၏တည်နေရာ၊ စကရင်ပြန်ဖွင့်ခြင်း၊ ယုံကြည်စိတ်ချရသောသိုလှောင်ရာနေရာတို့အား သတ်မှတ်မည်"</string>
diff --git a/tests/CarDeveloperOptions/res/values-or/strings.xml b/tests/CarDeveloperOptions/res/values-or/strings.xml
index bc44cca..df6b193 100644
--- a/tests/CarDeveloperOptions/res/values-or/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-or/strings.xml
@@ -2395,7 +2395,7 @@
<string name="battery_desc_standby" product="default" msgid="8889482616564520287">"ନିଷ୍କ୍ରିୟ ଫୋନରେ ବ୍ୟବହୃତ ବ୍ୟାଟେରୀ"</string>
<string name="battery_desc_radio" msgid="5119078473833865414">"ସେଲ୍ ରେଡିଓ ଦ୍ୱାରା ବ୍ୟବହୃତ ବ୍ୟାଟେରୀ"</string>
<string name="battery_sugg_radio" msgid="3616364509738133415">"ସେଲ୍ କଭରେଜ୍ ନଥିବା ଅଞ୍ଚଳରେ ପାୱାର୍ ବଞ୍ଚାଇବାକୁ ବିମାନ ମୋଡ୍କୁ ଯାଆନ୍ତୁ"</string>
- <string name="battery_desc_flashlight" msgid="4574819522143720917">"ଫ୍ଲାଶଲାଇଟ୍ ଦ୍ୱାରା ବ୍ୟବହୃତ ବ୍ୟାଟେରୀ"</string>
+ <string name="battery_desc_flashlight" msgid="4574819522143720917">"ଫ୍ଲାସଲାଇଟ୍ ଦ୍ୱାରା ବ୍ୟବହୃତ ବ୍ୟାଟେରୀ"</string>
<string name="battery_desc_camera" msgid="517966830222999462">"କ୍ୟାମେରା ଦ୍ୱାରା ବ୍ୟବହୃତ ବ୍ୟାଟେରୀ"</string>
<string name="battery_desc_display" msgid="6701005808894183097">"ଡିସ୍ପ୍ଲେ ଓ ବ୍ୟାକ୍ଲାଇଟ୍ ଦ୍ୱାରା ବ୍ୟବହୃତ ବ୍ୟାଟେରୀ"</string>
<string name="battery_sugg_display" msgid="6366790848514389990">"ସ୍କ୍ରୀନ୍ ଉଜ୍ଜ୍ୱଳତା ଏବଂ/କିମ୍ବା ସ୍କ୍ରୀନ୍ ସମୟ ସମାପ୍ତି କମ କରନ୍ତୁ"</string>
diff --git a/tests/CarDeveloperOptions/res/values-pl/strings.xml b/tests/CarDeveloperOptions/res/values-pl/strings.xml
index 40df7f2..93804cd 100644
--- a/tests/CarDeveloperOptions/res/values-pl/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-pl/strings.xml
@@ -4239,9 +4239,9 @@
<string name="deletion_helper_manual_title" msgid="1011785013431162078">"Instrukcja"</string>
<string name="deletion_helper_preference_title" msgid="797270307034242206">"Zwolnij miejsce teraz"</string>
<string name="gesture_preference_title" msgid="583646591518373785">"Gesty"</string>
- <string name="gesture_preference_summary" product="default" msgid="2990736567599191163">"Sterowanie telefonem za pomocą krótkich gestów"</string>
- <string name="gesture_preference_summary" product="tablet" msgid="8303793594714075580">"Sterowanie tabletem za pomocą krótkich gestów"</string>
- <string name="gesture_preference_summary" product="device" msgid="7792199669106960922">"Sterowanie urządzeniem za pomocą krótkich gestów"</string>
+ <string name="gesture_preference_summary" product="default" msgid="2990736567599191163">"Sterowanie telefonem za pomocą gestów"</string>
+ <string name="gesture_preference_summary" product="tablet" msgid="8303793594714075580">"Sterowanie tabletem za pomocą gestów"</string>
+ <string name="gesture_preference_summary" product="device" msgid="7792199669106960922">"Sterowanie urządzeniem za pomocą gestów"</string>
<string name="double_tap_power_for_camera_title" msgid="5480829329052517484">"Uruchamianie aparatu"</string>
<string name="double_tap_power_for_camera_summary" msgid="6591026425496323965">"Aby szybko uruchomić aparat, naciśnij dwukrotnie przycisk zasilania. Możesz to zrobić na dowolnym ekranie."</string>
<string name="double_tap_power_for_camera_suggestion_title" msgid="509078029429865036">"Szybkie uruchamianie aparatu"</string>
diff --git a/tests/CarDeveloperOptions/res/values-ru/strings.xml b/tests/CarDeveloperOptions/res/values-ru/strings.xml
index 7f3df1e..0d0dbc2 100644
--- a/tests/CarDeveloperOptions/res/values-ru/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-ru/strings.xml
@@ -359,7 +359,7 @@
<string name="owner_info_settings_title" msgid="2537966178998339896">"Текст на экране"</string>
<string name="security_enable_widgets_title" msgid="1701510007926738088">"Включить виджеты"</string>
<string name="security_enable_widgets_disabled_summary" msgid="4408176087132339331">"Отключено администратором"</string>
- <string name="lockdown_settings_title" msgid="4534779922580115990">"Добавить функцию блокировки входа"</string>
+ <string name="lockdown_settings_title" msgid="4534779922580115990">"Добавить кнопку блокировки"</string>
<string name="lockdown_settings_summary" msgid="7270756909878256174">"Добавить в меню кнопки питания функцию, которая позволяет отключить Smart Lock, разблокировку по отпечатку пальца и уведомления на заблокированном экране"</string>
<string name="trust_agents_extend_unlock_title" msgid="3582017561316089951">"Агенты доверия откладывают блокировку"</string>
<string name="trust_agents_extend_unlock_summary" msgid="3543997596586078084">"Если параметр включен, агенты доверия могут увеличивать время, в течение которого устройство остается разблокированным, но не могут разблокировать его"</string>
diff --git a/tests/CarDeveloperOptions/res/values-sr/strings.xml b/tests/CarDeveloperOptions/res/values-sr/strings.xml
index effa3b4..1fea34f 100644
--- a/tests/CarDeveloperOptions/res/values-sr/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-sr/strings.xml
@@ -2880,9 +2880,9 @@
<item quantity="other">Провери сертификате</item>
</plurals>
<string name="user_settings_title" msgid="7917598650933179545">"Више корисника"</string>
- <string name="user_settings_footer_text" product="device" msgid="4573858247439190545">"Делите уређај тако што ћете додати нове кориснике. Сваки корисник има лични простор на уређају за прилагођене почетне екране, налоге, апликације, подешавања и још много тога."</string>
- <string name="user_settings_footer_text" product="tablet" msgid="780018221428132918">"Делите таблет тако што ћете додати нове кориснике. Сваки корисник има лични простор на таблету за прилагођене почетне екране, налоге, апликације, подешавања и још много тога."</string>
- <string name="user_settings_footer_text" product="default" msgid="1470859614968237491">"Делите телефон тако што ћете додати нове кориснике. Сваки корисник има лични простор на телефону за прилагођене почетне екране, налоге, апликације, подешавања и још много тога."</string>
+ <string name="user_settings_footer_text" product="device" msgid="4573858247439190545">"Делите уређај тако што ћете додати нове кориснике. Сваки корисник има лични простор на уређају за прилагођене почетне екране, налоге, апликације, подешавања и друго."</string>
+ <string name="user_settings_footer_text" product="tablet" msgid="780018221428132918">"Делите таблет тако што ћете додати нове кориснике. Сваки корисник има лични простор на таблету за прилагођене почетне екране, налоге, апликације, подешавања и друго."</string>
+ <string name="user_settings_footer_text" product="default" msgid="1470859614968237491">"Делите телефон тако што ћете додати нове кориснике. Сваки корисник има лични простор на телефону за прилагођене почетне екране, налоге, апликације, подешавања и друго."</string>
<string name="user_list_title" msgid="6670258645246192324">"Корисници и профили"</string>
<string name="user_add_user_or_profile_menu" msgid="4220679989900149336">"Додај корисника или профил"</string>
<string name="user_add_user_menu" msgid="9006572936456324794">"Додај корисника"</string>
diff --git a/tests/CarDeveloperOptions/res/values-sw/strings.xml b/tests/CarDeveloperOptions/res/values-sw/strings.xml
index b9ac01b..4a1d403 100644
--- a/tests/CarDeveloperOptions/res/values-sw/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-sw/strings.xml
@@ -1403,9 +1403,9 @@
<string name="storage_menu_rename" msgid="3731682449294417745">"Badilisha jina"</string>
<string name="storage_menu_mount" msgid="6395893560780365473">"Pachika"</string>
<string name="storage_menu_unmount" msgid="5041360076873514189">"Ondoa"</string>
- <string name="storage_menu_format" msgid="4285487419855632896">"Umbiza"</string>
- <string name="storage_menu_format_public" msgid="5361388353980722971">"Umbiza kama hifadhi inayohamishika"</string>
- <string name="storage_menu_format_private" msgid="5288599205435858720">"Umbiza kama hifadhi ya ndani"</string>
+ <string name="storage_menu_format" msgid="4285487419855632896">"Rekebisha muundo"</string>
+ <string name="storage_menu_format_public" msgid="5361388353980722971">"Weka muundo uwe inahamishika"</string>
+ <string name="storage_menu_format_private" msgid="5288599205435858720">"Weka muundo wa hifadhi ya ndani"</string>
<string name="storage_menu_migrate" msgid="1885806122515759703">"Hamisha data"</string>
<string name="storage_menu_forget" msgid="4345021250834642640">"Sahau"</string>
<string name="storage_menu_set_up" msgid="2849170579745958513">"Weka mipangilio"</string>
@@ -1498,7 +1498,7 @@
<string name="storage_wizard_init_v2_later" msgid="2605006907172213466">"Weka mipangilio baadaye"</string>
<string name="storage_wizard_format_confirm_v2_title" msgid="1884699177320256159">"Ungependa kuumbiza <xliff:g id="NAME">^1</xliff:g>?"</string>
<string name="storage_wizard_format_confirm_v2_body" msgid="977657376082074305">"Unatakiwa uratibu <xliff:g id="NAME_0">^1</xliff:g> ili ihifadhi programu, faili na maudhui. \n\nHatua ya kuratibu itafuta maudhui yote yaliyo katika <xliff:g id="NAME_1">^2</xliff:g>. Ili usipoteze maudhui, hifadhi nakala kwenye <xliff:g id="NAME_2">^3</xliff:g> au kifaa kingine."</string>
- <string name="storage_wizard_format_confirm_v2_action" msgid="5576917958786300415">"Umbiza <xliff:g id="NAME">^1</xliff:g>"</string>
+ <string name="storage_wizard_format_confirm_v2_action" msgid="5576917958786300415">"Rekebisha muundo: <xliff:g id="NAME">^1</xliff:g>"</string>
<string name="storage_wizard_migrate_v2_title" msgid="6728034411587320249">"Utahamishia maudhu kwenye <xliff:g id="NAME">^1</xliff:g>?"</string>
<string name="storage_wizard_migrate_v2_body" product="tablet" msgid="6943007011251294950">"Unaweza kuhamishia faili, maudhui na baadhi ya programu kwenye <xliff:g id="NAME">^1</xliff:g>. \n\nHatua hii itafuta vipengee ili upate nafasi ya <xliff:g id="SIZE">^2</xliff:g> kwenye hifadhi ya kompyuta yako kibao na inaweza kuchukua takribani <xliff:g id="DURATION">^3</xliff:g>."</string>
<string name="storage_wizard_migrate_v2_body" product="default" msgid="3211214309775524554">"Unaweza kuhamishia faili, maudhui na baadhi ya programu kwenye <xliff:g id="NAME">^1</xliff:g>. \n\nHatua hii itafuta vipengee ili upate nafasi ya <xliff:g id="SIZE">^2</xliff:g> kwenye hifadhi ya simu yako na inaweza kuchukua takribani <xliff:g id="DURATION">^3</xliff:g>."</string>
@@ -2628,14 +2628,14 @@
<string name="remove_account_failed" msgid="491458185327106966">"Mabadiliko haya hayaruhusiwi na msimamizi wako"</string>
<string name="cant_sync_dialog_title" msgid="5483419398223189881">"Huwezi kusawazisha mwenyewe"</string>
<string name="cant_sync_dialog_message" msgid="3467126947262857534">"Kwa sasa usawazishaji wa kipengee hiki umezimwa. Kubadilisha mpangilio huu, washa kwa muda data ya usuli na usawazishaji kiotomatiki."</string>
- <string name="enter_password" msgid="2963496904625715235">"Ili uanzishe Android, weka nenosiri lako"</string>
- <string name="enter_pin" msgid="7140938268709546890">"Ili uanzishe Android, weka PIN yako"</string>
- <string name="enter_pattern" msgid="1653841963422825336">"Ili uanzishe Android, chora mchoro wako"</string>
+ <string name="enter_password" msgid="2963496904625715235">"Ili uwashe Android, weka nenosiri lako"</string>
+ <string name="enter_pin" msgid="7140938268709546890">"Ili uwashe Android, weka PIN yako"</string>
+ <string name="enter_pattern" msgid="1653841963422825336">"Ili uwashe Android, chora mchoro wako"</string>
<string name="cryptkeeper_wrong_pattern" msgid="4580105105385125467">"Mchoro huo si sahihi"</string>
<string name="cryptkeeper_wrong_password" msgid="1709534330303983166">"Nenosiri Lisilo sahihi"</string>
<string name="cryptkeeper_wrong_pin" msgid="857757190077859245">"Nambari ya PIN si sahihi"</string>
<string name="checking_decryption" msgid="5927759912073053101">"Inakagua..."</string>
- <string name="starting_android" msgid="4774187626261253089">"Inaanzisha Android..."</string>
+ <string name="starting_android" msgid="4774187626261253089">"Inawasha Android..."</string>
<string name="delete" msgid="2325292565700865366">"Futa"</string>
<string name="misc_files" msgid="1012397035001764693">"Faili Nyinginezo"</string>
<string name="misc_files_selected_count" msgid="1434146080729502726">"Imechaguliwa <xliff:g id="NUMBER">%1$d</xliff:g> juu ya <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
@@ -4315,7 +4315,7 @@
<string name="battery_suggestion_title" product="device" msgid="765005476863631528">"Boresha muda wa matumizi ya betri ya kifaa"</string>
<string name="battery_suggestion_title" product="default" msgid="3295786171830183688">"Boresha muda wa matumizi ya betri ya simu yako"</string>
<string name="battery_suggestion_summary" msgid="2669070349482656490"></string>
- <string name="gesture_prevent_ringing_screen_title" msgid="4173494225145223638">"Zuia mlio wa simu"</string>
+ <string name="gesture_prevent_ringing_screen_title" msgid="4173494225145223638">"Zuia simu isilie"</string>
<string name="gesture_prevent_ringing_title" msgid="8827963588425673557">"Bonyeza vitufe vya Kuwasha na Kuongeza Sauti kwa pamoja ili"</string>
<string name="gesture_prevent_ringing_sound_title" msgid="8642330448721033641">"Njia ya mkato ya kuzuia mlio"</string>
<string name="prevent_ringing_option_vibrate" msgid="6456505293904544108">"Tetema"</string>
diff --git a/tests/CarDeveloperOptions/res/values-ta/strings.xml b/tests/CarDeveloperOptions/res/values-ta/strings.xml
index 28fbe26..8841aca 100644
--- a/tests/CarDeveloperOptions/res/values-ta/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-ta/strings.xml
@@ -1257,7 +1257,7 @@
<string name="doze_title" msgid="235269029233857546">"புதிய அறிவிப்புகள்"</string>
<string name="doze_summary" msgid="6762274282827831706">"அறிவிப்புகளைப் பெறும் போது திரையை இயக்கு"</string>
<string name="doze_always_on_title" msgid="8555184965031789941">"எப்போதும் இயக்கத்தில் வை"</string>
- <string name="doze_always_on_summary" msgid="7654436900436328950">"நேரம், அறிவிப்பு ஐகான்கள் மற்றும் பிற தகவலைக் காட்டு. அதே நேரத்தில் பேட்டரியை அதிகமாகப் பயன்படுத்தும்."</string>
+ <string name="doze_always_on_summary" msgid="7654436900436328950">"நேரம், அறிவிப்பு ஐகான்கள் மற்றும் பிற தகவல்களைக் காட்டும். பேட்டரியை அதிகமாகப் பயன்படுத்தும்."</string>
<string name="title_font_size" msgid="5021464556860010851">"எழுத்துரு அளவு"</string>
<string name="short_summary_font_size" msgid="4141077908728522946">"உரையைப் பெரிதாக்கும் அல்லது சிறிதாக்கும்"</string>
<string name="sim_lock_settings" msgid="1986924650622642189">"சிம் கார்டின் பூட்டு அமைப்பு"</string>
@@ -1783,7 +1783,7 @@
<string name="applications_settings_summary" msgid="8888258399577123906">"அமைப்புகளை நிர்வகிக்கும், விரைவு துவக்கத்திற்கான குறுக்குவழிகளை அமைக்கும்"</string>
<string name="applications_settings_header" msgid="3766501606045211098">"ஆப்ஸ் அமைப்பு"</string>
<string name="install_applications" msgid="7745902974984889179">"அறியப்படாத மூலங்கள்"</string>
- <string name="install_applications_title" msgid="8164828577588659496">"எல்லா பயன்பாட்டு ஆதாரங்களையும் அனுமதி"</string>
+ <string name="install_applications_title" msgid="8164828577588659496">"எல்லா ஆப்ஸ் ஆதாரங்களையும் அனுமதி"</string>
<string name="recent_app_category_title" msgid="7688788038277126727">"சமீபத்தில் திறந்தவை"</string>
<string name="see_all_apps_title" msgid="6435061912110347474">"<xliff:g id="COUNT">%1$d</xliff:g> பயன்பாடுகளையும் காட்டு"</string>
<string name="install_all_warning" product="tablet" msgid="4580699862358542727">"அறியப்படாத பயன்பாடுகளால் உங்கள் டேப்லெட்டும் தனிப்பட்ட தரவும் அதிகம் பாதிப்பிற்கு உள்ளாகும். இந்த மூலத்திலிருந்து பயன்பாடுகளை நிறுவுவதால், அவற்றைப் பயன்படுத்தும் போது உங்கள் டேப்லெட்டுக்கு ஏதேனும் சேதம் ஏற்பட்டாலோ அல்லது தரவை இழந்தாலோ, அதற்கு நீங்கள்தான் பொறுப்பாவீர்கள் என்பதை ஏற்கிறீர்கள்."</string>
@@ -1925,7 +1925,7 @@
<string name="service_manage" msgid="7045214643721276662">"அமைப்பு"</string>
<string name="service_stop_description" msgid="4184180745938573707">"இந்த ஆப்ஸ் ஏற்கனவே இதன் பயன்பாட்டால் தொடங்கப்பட்டது. இதை நிறுத்துவதால் ஆப்ஸ் தோல்வியடையலாம்."</string>
<string name="heavy_weight_stop_description" msgid="7444148811046611463">"பயன்பாட்டைப் பாதுகாப்பாக நிறுத்த முடியாது. இதை நிறுத்தினால், நீங்கள் நடப்பு செயல்கள் சிலவற்றை இழக்க நேரிடலாம்."</string>
- <string name="background_process_stop_description" msgid="8971810208873038109">"இது பழைய பயன்பாட்டு செயல்முறையாகும், மீண்டும் தேவைப்பட்டால் வழங்குவதற்காக இன்னமும் தொடர்ந்து செயல்படுத்தப்படுகிறது. பொதுவாக அதை நிறுத்துவதற்கு எந்தக் காரணமும் இல்லை."</string>
+ <string name="background_process_stop_description" msgid="8971810208873038109">"இது பழைய ஆப்ஸ் செயல்முறையாகும், மீண்டும் தேவைப்பட்டால் வழங்குவதற்காக இன்னமும் தொடர்ந்து செயல்படுத்தப்படுகிறது. பொதுவாக அதை நிறுத்துவதற்கு எந்தக் காரணமும் இல்லை."</string>
<string name="service_manage_description" msgid="8058123524402833082">"<xliff:g id="CLIENT_NAME">%1$s</xliff:g>: தற்போது பயன்பாட்டில் உள்ளது. அதைக் கட்டுப்படுத்த, அமைப்புகளைத் தட்டவும்."</string>
<string name="main_running_process_description" msgid="7733268956566861797">"முக்கிய செயல்முறை பயன்பாட்டில் உள்ளது."</string>
<string name="process_service_in_use_description" msgid="2253782391122637651">"<xliff:g id="COMP_NAME">%1$s</xliff:g> இன் சேவை பயன்பாட்டில் உள்ளது."</string>
@@ -2060,7 +2060,7 @@
<string name="accessibility_shortcut_description" msgid="1427049334225166395">"ஷார்ட்கட் இயக்கப்பட்டிருக்கும் போது, அணுகல்தன்மை அம்சத்தைத் தொடங்க, 3 வினாடிகளுக்கு இரண்டு ஒலியளவு விசைகளையும் அழுத்தவும்."</string>
<string name="accessibility_toggle_high_text_contrast_preference_title" msgid="5652244684961877255">"உரையின் உயர் மாறுபாடு"</string>
<string name="accessibility_toggle_screen_magnification_auto_update_preference_title" msgid="2466317284195934003">"திரை உருப்பெருக்கத்தைத் தானாகப் புதுப்பி"</string>
- <string name="accessibility_toggle_screen_magnification_auto_update_preference_summary" msgid="6625473745911276917">"பயன்பாட்டு மாற்றங்களில் திரை உருப்பெருக்கத்தைப் புதுப்பிக்கவும்"</string>
+ <string name="accessibility_toggle_screen_magnification_auto_update_preference_summary" msgid="6625473745911276917">"ஆப்ஸ் மாற்றங்களில் திரை உருப்பெருக்கத்தைப் புதுப்பிக்கவும்"</string>
<string name="accessibility_power_button_ends_call_prerefence_title" msgid="6172987104538172869">"பவர் பட்டன் அழைப்பை நிறுத்தும்"</string>
<string name="accessibility_toggle_large_pointer_icon_title" msgid="9127905775116570565">"பெரிய மவுஸ் பாயிண்டர்"</string>
<string name="accessibility_disable_animations" msgid="8378441317115710009">"அனிமேஷன்களை அகற்று"</string>
@@ -2615,7 +2615,7 @@
<string name="sync_calendar" msgid="6573708019827519372">"கேலெண்டர்"</string>
<string name="sync_contacts" msgid="5687434785723746534">"தொடர்புகள்"</string>
<string name="sync_plug" msgid="6703804441408427257"><font fgcolor="#ffffffff">"Google ஒத்திசைவுக்கு வரவேற்கிறோம்!"</font>" \nநீங்கள் எங்கிருந்தாலும் உங்கள் தொடர்புகள், சந்திப்புகள் மற்றும் பலவற்றுக்கான அணுகலை அனுமதிப்பதற்காக Google தரவை ஒத்திசைக்கிறது."</string>
- <string name="header_application_sync_settings" msgid="4581847153669774489">"பயன்பாட்டு ஒத்திசைவு அமைப்பு"</string>
+ <string name="header_application_sync_settings" msgid="4581847153669774489">"ஆப்ஸ் ஒத்திசைவு அமைப்பு"</string>
<string name="header_data_and_synchronization" msgid="400831816068697286">"தரவு & ஒத்திசைத்தல்"</string>
<string name="preference_change_password_title" msgid="7243527448378789274">"கடவுச்சொல்லை மாற்று"</string>
<string name="header_account_settings" msgid="8586173964125512219">"கணக்கு அமைப்பு"</string>
@@ -3673,7 +3673,7 @@
<string name="apps_storage" msgid="5658466038269046038">"ஆப்ஸ் சேமிப்பகம்"</string>
<string name="usage_access" msgid="2023443456361489516">"உபயோக அணுகல்"</string>
<string name="permit_usage_access" msgid="3321727608629752758">"உபயோக அணுகல் அனுமதி"</string>
- <string name="app_usage_preference" msgid="5691545073101551727">"பயன்பாட்டு உபயோக விருப்பத்தேர்வுகள்"</string>
+ <string name="app_usage_preference" msgid="5691545073101551727">"ஆப்ஸ் உபயோக விருப்பத்தேர்வுகள்"</string>
<string name="time_spent_in_app_pref_title" msgid="2803186835902798451">"பயன்படுத்திய நேரம்"</string>
<string name="usage_access_description" msgid="2178083292760305207">"உபயோக அணுகலானது, நீங்கள் வேறு எந்தெந்த ஆப்ஸை எவ்வளவு அடிக்கடி பயன்படுத்துகிறீர்கள் என்று அறியும் அனுமதியை ஒரு ஆப்ஸுக்கு வழங்குகிறது. உங்கள் மொபைல் நிறுவனம், மொழி அமைப்புகள் மற்றும் பிற விவரங்களையும் அறிந்து கொள்ளும் அனுமதியும் இதில் அடங்கும்."</string>
<string name="memory_settings_title" msgid="7867148522014070721">"நினைவகம்"</string>
diff --git a/tests/CarDeveloperOptions/res/values-te/strings.xml b/tests/CarDeveloperOptions/res/values-te/strings.xml
index 9f09c49..dd7b366 100644
--- a/tests/CarDeveloperOptions/res/values-te/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-te/strings.xml
@@ -1303,7 +1303,7 @@
<string name="system_update_settings_list_item_title" msgid="1907497454722790033">"సిస్టమ్ అప్డేట్లు"</string>
<string name="system_update_settings_list_item_summary" msgid="3497456690691907873"></string>
<string name="firmware_version" msgid="547095584029938749">"Android వెర్షన్"</string>
- <string name="security_patch" msgid="483709031051932208">"Android భద్రతా అతికింపు స్థాయి"</string>
+ <string name="security_patch" msgid="483709031051932208">"Android భద్రతా ప్యాచ్ స్థాయి"</string>
<string name="model_info" msgid="1729765474260797594">"మోడల్"</string>
<string name="model_summary" msgid="8781425868254352168">"మోడల్: %1$s"</string>
<string name="hardware_info" msgid="174270144950621815">"మోడల్ & హార్డ్వేర్"</string>
@@ -2459,7 +2459,7 @@
<string name="battery_saver_turn_on_automatically_never" msgid="2623381258359775227">"ఎప్పటికీ వద్దు"</string>
<string name="battery_saver_turn_on_automatically_pct" msgid="434270432432390307">"<xliff:g id="PERCENT">%1$s</xliff:g> బ్యాటరీ ఉన్నప్పుడు"</string>
<string name="battery_percentage" msgid="7782252476471033843">"బ్యాటరీ పవర్ శాతం"</string>
- <string name="battery_percentage_description" msgid="9219875229166700610">"స్థితి బార్లో బ్యాటరీ పవర్ శాతాన్ని చూపు"</string>
+ <string name="battery_percentage_description" msgid="9219875229166700610">"స్టేటస్ బార్లో బ్యాటరీ పవర్ శాతాన్ని చూపుతుంది"</string>
<string name="process_stats_summary_title" msgid="9189588417488537954">"ప్రాసెస్ గణాంకాలు"</string>
<string name="process_stats_summary" msgid="8077998499161221885">"అమలవుతున్న ప్రాసెస్ల గురించి అసాధారణమైన గణాంకాలు"</string>
<string name="app_memory_use" msgid="5126237308545653706">"మెమరీ వినియోగం"</string>
@@ -2519,13 +2519,13 @@
<string name="credentials_install" product="nosdcard" msgid="8509362500537206883">"నిల్వ నుండి ఇన్స్టాల్ చేయండి"</string>
<string name="credentials_install" product="default" msgid="8997183776710118353">"SD కార్డు నుండి ఇన్స్టాల్ చేయండి"</string>
<string name="credentials_install_summary" product="nosdcard" msgid="3426661965567059596">"నిల్వ నుండి సర్టిఫికెట్లను ఇన్స్టాల్ చేయండి"</string>
- <string name="credentials_install_summary" product="default" msgid="4943897416156671633">"SD కార్డు నుండి ప్రమాణపత్రాలను ఇన్స్టాల్ చేయండి"</string>
+ <string name="credentials_install_summary" product="default" msgid="4943897416156671633">"SD కార్డు నుండి సర్టిఫికెట్లను ఇన్స్టాల్ చేయండి"</string>
<string name="credentials_reset" msgid="355080737664731678">"ఆధారాలను క్లియర్ చేయండి"</string>
<string name="credentials_reset_summary" msgid="7622528359699428555">"అన్ని సర్టిఫికెట్లను తీసివేయండి"</string>
<string name="trusted_credentials" msgid="6989242522455395200">"విశ్వసనీయ ఆధారాలు"</string>
- <string name="trusted_credentials_summary" msgid="7411781319056251582">"విశ్వసనీయ CA సర్టిఫికెట్లను ప్రదర్శించు"</string>
+ <string name="trusted_credentials_summary" msgid="7411781319056251582">"విశ్వసనీయ CA సర్టిఫికెట్లను ప్రదర్శిస్తుంది"</string>
<string name="user_credentials" msgid="8365731467650306757">"వినియోగదారు ఆధారాలు"</string>
- <string name="user_credentials_summary" msgid="7350223899317423252">"నిల్వ చేసిన ఆధారాలను వీక్షించండి మరియు సవరించండి"</string>
+ <string name="user_credentials_summary" msgid="7350223899317423252">"నిల్వ ఉన్న ఆధారాలను చూడండి, వాటిని సవరించండి"</string>
<string name="advanced_security_title" msgid="286883005673855845">"అధునాతనం"</string>
<string name="credential_storage_type" msgid="2585337320206095255">"నిల్వ రకం"</string>
<string name="credential_storage_type_hardware" msgid="5054143224259023600">"హార్డ్వేర్ మద్దతు"</string>
@@ -3397,7 +3397,7 @@
<item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> వర్గం</item>
</plurals>
<string name="no_channels" msgid="8884254729302501652">"ఈ యాప్ ఏ నోటిఫికేషన్లను పోస్ట్ చేయలేదు"</string>
- <string name="app_settings_link" msgid="8465287765715790984">"యాప్లో అదనపు సెట్టింగ్లు"</string>
+ <string name="app_settings_link" msgid="8465287765715790984">"యాప్లోని అదనపు సెట్టింగ్లు"</string>
<string name="app_notification_listing_summary_zero" msgid="4047782719487686699">"అన్ని యాప్లలో ఆన్ చేయబడ్డాయి"</string>
<plurals name="app_notification_listing_summary_others" formatted="false" msgid="1161774065480666519">
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> యాప్లలో ఆఫ్ చేయబడింది</item>
@@ -3443,9 +3443,9 @@
<string name="zen_mode_unknown_app_set_behavior" msgid="5666462954329932302">"ఈ సెట్టింగ్లు ప్రస్తుతం మార్చబడవు. ఒక యాప్ అనుకూల ప్రవర్తనతో స్వయంచాలకంగా అంతరాయం కలిగించవద్దుని ఆన్ చేసింది."</string>
<string name="zen_mode_qs_set_behavior" msgid="788646569296973998">"ఈ సెట్టింగ్లు ప్రస్తుతం మార్చబడవు. అనుకూల ప్రవర్తనతో అంతరాయం కలిగించవద్దు మాన్యువల్గా ఆన్ చేయబడింది."</string>
<string name="zen_schedule_rule_type_name" msgid="4516851728113801329">"సమయం"</string>
- <string name="zen_schedule_rule_enabled_toast" msgid="1742354493045049048">"పేర్కొన్న సమయాల్లో అంతరాయం కలిగించవద్దు ఆన్ అయ్యేలా స్వయంచాలక నిబంధన సెట్ చేయబడింది"</string>
+ <string name="zen_schedule_rule_enabled_toast" msgid="1742354493045049048">"నిర్దేశిత సమయాల్లో \'అంతరాయం కలిగించవద్దు\' ఆన్ అయ్యేలా ఆటోమేటిక్ నిబంధన సెట్ చేయబడింది"</string>
<string name="zen_event_rule_type_name" msgid="7467729997336583342">"ఈవెంట్"</string>
- <string name="zen_event_rule_enabled_toast" msgid="7087368268966855976">"పేర్కొన్న సందర్భాల్లో అంతరాయం కలిగించవద్దు ఆన్ అయ్యేలా స్వయంచాలక నిబంధన సెట్ చేయబడింది"</string>
+ <string name="zen_event_rule_enabled_toast" msgid="7087368268966855976">"నిర్దిష్ట సందర్భాల్లో \'అంతరాయం కలిగించవద్దు\' ఆన్ అయ్యేలా ఆటోమేటిక్ నిబంధన సెట్ చేయబడింది"</string>
<string name="zen_mode_event_rule_calendar" msgid="6088077103908487442">"వీటి సంబంధిత ఈవెంట్ల సమయంలో"</string>
<string name="zen_mode_event_rule_summary_calendar_template" msgid="4027207992040792657">"<xliff:g id="CALENDAR">%1$s</xliff:g> సంబంధిత ఈవెంట్ల సమయంలో"</string>
<string name="zen_mode_event_rule_summary_any_calendar" msgid="7590085295784895885">"ఏదైనా క్యాలెండర్"</string>
@@ -3701,10 +3701,10 @@
<item quantity="other">యాప్ల కారణంగా బ్యాటరీ ఖాళీ అవుతోంది</item>
<item quantity="one"><xliff:g id="APP">%1$s</xliff:g> కారణంగా బ్యాటరీ ఖాళీ అవుతోంది</item>
</plurals>
- <string name="high_power_filter_on" msgid="5294209328473386403">"అనుకూలీకరించనివి"</string>
+ <string name="high_power_filter_on" msgid="5294209328473386403">"ఆప్టిమైజ్ చేయనివి"</string>
<string name="high_power_on" msgid="3573501822510580334">"అనుకూలీకరించబడలేదు"</string>
<string name="high_power_off" msgid="5906679734326490426">"బ్యాటరీ వినియోగాన్ని ఆప్టిమైజ్ చేస్తోంది"</string>
- <string name="high_power_system" msgid="739584574711292753">"బ్యాటరీ అనుకూలీకరణ అందుబాటులో లేదు"</string>
+ <string name="high_power_system" msgid="739584574711292753">"బ్యాటరీ ఆప్టిమైజేషన్ అందుబాటులో లేదు"</string>
<string name="high_power_desc" msgid="333756885680362741">"బ్యాటరీ అనుకూలీకరణను వర్తింపజేయదు. మీ బ్యాటరీ మరింత శీఘ్రంగా వినియోగించబడవచ్చు."</string>
<string name="high_power_prompt_title" msgid="2805745781720454052">"ఎల్లప్పుడూ నేపథ్యంలో అమలు కావడానికి అనువర్తనాన్ని అనుమతించాలా?"</string>
<string name="high_power_prompt_body" msgid="8067395096053552289">"ఎల్లప్పుడూ నేపథ్యంలో అమలు కావడానికి <xliff:g id="APP_NAME">%1$s</xliff:g>ని అనుమతిస్తే బ్యాటరీ జీవితకాలం తగ్గిపోవచ్చు. \n\nమీరు తర్వాత సెట్టింగ్లు > యాప్లు & నోటిఫికేషన్లలోకి వెళ్లి దీనిని మార్చవచ్చు."</string>
@@ -3864,7 +3864,7 @@
<string name="users_summary" msgid="6693338169439092387">"<xliff:g id="USER_NAME">%1$s</xliff:g>గా సైన్ ఇన్ చేసారు"</string>
<string name="payment_summary" msgid="1381646849276543242">"<xliff:g id="APP_NAME">%1$s</xliff:g> డిఫాల్ట్గా ఉంది"</string>
<string name="backup_disabled" msgid="6941165814784765643">"బ్యాకప్ నిలిపివేయబడింది"</string>
- <string name="android_version_summary" msgid="2192751442789395445">"Android <xliff:g id="VERSION">%1$s</xliff:g>కి అప్డేట్ చేయబడింది"</string>
+ <string name="android_version_summary" msgid="2192751442789395445">"Android <xliff:g id="VERSION">%1$s</xliff:g>కు అప్డేట్ చేయబడింది"</string>
<string name="android_version_pending_update_summary" msgid="3554543810520655076">"అప్డేట్ అందుబాటులో ఉంది"</string>
<string name="disabled_by_policy_title" msgid="1238318274952958846">"చర్య అనుమతించబడదు"</string>
<string name="disabled_by_policy_title_adjust_volume" msgid="7094547090629203316">"వాల్యూమ్ని మార్చలేరు"</string>
diff --git a/tests/CarDeveloperOptions/res/values-th/strings.xml b/tests/CarDeveloperOptions/res/values-th/strings.xml
index 0455a58..32f93b9 100644
--- a/tests/CarDeveloperOptions/res/values-th/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-th/strings.xml
@@ -3521,7 +3521,7 @@
<string name="zen_mode_when" msgid="7835420687948416255">"เปิดโดยอัตโนมัติ"</string>
<string name="zen_mode_when_never" msgid="4506296396609224524">"ไม่ใช้"</string>
<string name="zen_mode_when_every_night" msgid="3942151668791426194">"ทุกคืน"</string>
- <string name="zen_mode_when_weeknights" msgid="2412709309122408474">"คืนวันจันทร์-ศุกร์"</string>
+ <string name="zen_mode_when_weeknights" msgid="2412709309122408474">"คืนวันธรรมดา"</string>
<string name="zen_mode_start_time" msgid="5979122139937561731">"เวลาเริ่มต้น"</string>
<string name="zen_mode_end_time" msgid="3188578493250909972">"เวลาสิ้นสุด"</string>
<string name="zen_mode_end_time_next_day_summary_format" msgid="1598612215612648214">"<xliff:g id="FORMATTED_TIME">%s</xliff:g> วันถัดไป"</string>
diff --git a/tests/CarDeveloperOptions/res/values-tr/strings.xml b/tests/CarDeveloperOptions/res/values-tr/strings.xml
index f28ea00..d2bcaf3 100644
--- a/tests/CarDeveloperOptions/res/values-tr/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-tr/strings.xml
@@ -4124,7 +4124,7 @@
<string name="ambient_display_pickup_summary" product="default" msgid="8798915340594367449">"Saati, bildirimleri ve diğer bilgileri kontrol etmek için telefonunuzu elinize alın."</string>
<string name="ambient_display_pickup_summary" product="tablet" msgid="1077745287100012928">"Saati, bildirimleri ve diğer bilgileri kontrol etmek için tabletinizi elinize alın."</string>
<string name="ambient_display_pickup_summary" product="device" msgid="404199660076598026">"Saati, bildirimleri ve diğer bilgileri kontrol etmek için cihazınızı elinize alın."</string>
- <string name="ambient_display_tap_screen_title" product="default" msgid="2784322628239960695">"Telefonu kontrol etmek için dokunun"</string>
+ <string name="ambient_display_tap_screen_title" product="default" msgid="2784322628239960695">"Telefonu kontrol etmek için dokun"</string>
<string name="ambient_display_tap_screen_title" product="tablet" msgid="6434521782016864148">"Tableti kontrol etmek için dokunun"</string>
<string name="ambient_display_tap_screen_title" product="device" msgid="4396793721852647356">"Cihazı kontrol etmek için dokunun"</string>
<string name="ambient_display_tap_screen_summary" msgid="7869039870571925213">"Saati, bildirimleri ve diğer bilgileri kontrol etmek için ekranınıza dokunun."</string>
diff --git a/tests/CarDeveloperOptions/res/values-uk/strings.xml b/tests/CarDeveloperOptions/res/values-uk/strings.xml
index 626dd5f..f1f88f7 100644
--- a/tests/CarDeveloperOptions/res/values-uk/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-uk/strings.xml
@@ -389,7 +389,7 @@
<string name="decryption_settings_summary" product="default" msgid="7401802133199522441">"Телефон не зашифровано"</string>
<string name="encryption_and_credential_settings_summary" product="tablet" msgid="8170667308598998791">"Пристрій зашифровано"</string>
<string name="decryption_settings_summary" product="tablet" msgid="7524119945312453569">"Пристрій не зашифровано"</string>
- <string name="lockscreen_settings_title" msgid="1221505938891948413">"Дисплей заблокованого екрана"</string>
+ <string name="lockscreen_settings_title" msgid="1221505938891948413">"Заблокований екран"</string>
<string name="lockscreen_settings_what_to_show_category" msgid="3133378945821488654">"Що показувати"</string>
<string name="security_settings_summary" msgid="5210109100643223686">"Устан. Моє місцезн., розблок. екрана, блок. SIM-карти, сховища обл. даних"</string>
<string name="cdma_security_settings_summary" msgid="1783066617800041869">"Устан. Моє місцезн., розбл. екрана, блок. схов. обл. даних"</string>
diff --git a/tests/CarDeveloperOptions/res/values-ur/strings.xml b/tests/CarDeveloperOptions/res/values-ur/strings.xml
index 3c8fbc5..d93758c 100644
--- a/tests/CarDeveloperOptions/res/values-ur/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-ur/strings.xml
@@ -1237,7 +1237,7 @@
<string name="wallpaper_settings_summary_custom" msgid="8950504698015331202">"حسب ضرورت"</string>
<string name="wallpaper_suggestion_title" msgid="3012130414886743201">"وال پیپر تبدیل کریں"</string>
<string name="wallpaper_suggestion_summary" msgid="4247262938988875842">"اپنی اسکرین کو ذاتی نوعیت کا بنائیں"</string>
- <string name="wallpaper_settings_fragment_title" msgid="1503701065297188901">"وال پیپر منتخب کریں منجانب"</string>
+ <string name="wallpaper_settings_fragment_title" msgid="1503701065297188901">"وال پیپر منتخب کریں"</string>
<string name="screensaver_settings_title" msgid="7720091234133721021">"اسکرین سیور"</string>
<string name="screensaver_settings_summary_either_long" msgid="6078038506795498288">"ڈاک سے منسلک یا چارج ہونے کے دوران"</string>
<string name="screensaver_settings_summary_either_short" msgid="2453772128682850053">"دونوں صورتوں میں"</string>
@@ -3164,7 +3164,7 @@
<string name="zen_mode_behavior_settings_title" msgid="423125904296667490">"مستثنیات"</string>
<string name="zen_mode_duration_settings_title" msgid="5522668871014735728">"ڈیفالٹ دورانیہ"</string>
<string name="zen_mode_behavior_allow_title" msgid="2440627647424280842">"اس سے آوازیں اور وائبریشنز کی اجازت دیں"</string>
- <string name="zen_mode_behavior_no_sound" msgid="7290387625018248748">"کوئی آواز نہیں ہے"</string>
+ <string name="zen_mode_behavior_no_sound" msgid="7290387625018248748">"کوئی آواز نہیں"</string>
<string name="zen_mode_behavior_total_silence" msgid="371498357539257671">"مکمل خاموشی"</string>
<string name="zen_mode_behavior_no_sound_except" msgid="8894465423364103198">"<xliff:g id="CATEGORIES">%1$s</xliff:g> کے سوا کوئی آواز نہیں ہے"</string>
<string name="zen_mode_behavior_alarms_only" msgid="8406622989983047562">"الارمز اور میڈیا کے علاوہ کوئی آواز نہیں ہے"</string>
diff --git a/tests/CarDeveloperOptions/res/values-uz/strings.xml b/tests/CarDeveloperOptions/res/values-uz/strings.xml
index 0f54e7a..6fbad28 100644
--- a/tests/CarDeveloperOptions/res/values-uz/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-uz/strings.xml
@@ -355,7 +355,7 @@
<string name="owner_info_settings_title" msgid="2537966178998339896">"Qulflangan ekran ustidagi matn"</string>
<string name="security_enable_widgets_title" msgid="1701510007926738088">"Vidjetlarni yoqish"</string>
<string name="security_enable_widgets_disabled_summary" msgid="4408176087132339331">"Administrator tomonidan o‘chirilgan"</string>
- <string name="lockdown_settings_title" msgid="4534779922580115990">"Qulflash funksiyasini ko‘rsatish"</string>
+ <string name="lockdown_settings_title" msgid="4534779922580115990">"Qulflash tugmasini chiqarish"</string>
<string name="lockdown_settings_summary" msgid="7270756909878256174">"Smart Lock, barmoq izi bilan qulfni ochish va ekran qulfidagi bildirishnomalarni faolsizlantiradigan quvvat tugmasi funksiyasini ko‘rsatish."</string>
<string name="trust_agents_extend_unlock_title" msgid="3582017561316089951">"Ishonch agentlari qulf ochishni sura oladi"</string>
<string name="trust_agents_extend_unlock_summary" msgid="3543997596586078084">"Bu parametr yoqilsa, ishonch agentlari uzoq vaqt qulfsiz saqlaydi, lekin qulflangan qurilmani qulfdan chiqara olmaydi."</string>
diff --git a/tests/CarDeveloperOptions/res/values-vi/strings.xml b/tests/CarDeveloperOptions/res/values-vi/strings.xml
index 731fd69..879fecb 100644
--- a/tests/CarDeveloperOptions/res/values-vi/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-vi/strings.xml
@@ -355,8 +355,8 @@
<string name="owner_info_settings_title" msgid="2537966178998339896">"Thông điệp trên màn hình khóa"</string>
<string name="security_enable_widgets_title" msgid="1701510007926738088">"Bật tiện ích"</string>
<string name="security_enable_widgets_disabled_summary" msgid="4408176087132339331">"Bị quản trị viên vô hiệu hóa"</string>
- <string name="lockdown_settings_title" msgid="4534779922580115990">"Tùy chọn hiển thị khóa"</string>
- <string name="lockdown_settings_summary" msgid="7270756909878256174">"Tùy chọn hiển thị nút nguồn sẽ tắt tính năng Smart Lock, tính năng mở khóa bằng vân tay và thông báo trên màn hình khóa"</string>
+ <string name="lockdown_settings_title" msgid="4534779922580115990">"Hiển thị tùy chọn khóa"</string>
+ <string name="lockdown_settings_summary" msgid="7270756909878256174">"Hiển thị tùy chọn nút nguồn để tắt tính năng Smart Lock, mở khóa bằng vân tay, và thông báo trên màn hình khóa"</string>
<string name="trust_agents_extend_unlock_title" msgid="3582017561316089951">"Tác nhân tin cậy chỉ kéo dài thời gian mở khóa"</string>
<string name="trust_agents_extend_unlock_summary" msgid="3543997596586078084">"Nếu bạn bật, các tác nhân tin cậy sẽ kéo dài thời gian mở khóa, nhưng không thể mở khóa thiết bị bị khóa nữa."</string>
<string name="trust_lost_locks_screen_title" msgid="3094736590690459372">"Khóa màn hình khi mất đi sự tin cậy"</string>
diff --git a/tests/CarDeveloperOptions/res/values-zh-rCN/strings.xml b/tests/CarDeveloperOptions/res/values-zh-rCN/strings.xml
index 7f0fbd3..7c1e237 100644
--- a/tests/CarDeveloperOptions/res/values-zh-rCN/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-zh-rCN/strings.xml
@@ -845,7 +845,7 @@
<string name="wifi_error" msgid="5605801874484465557">"出错"</string>
<string name="wifi_sap_no_channel_error" msgid="6881796988574851628">"在此国家/地区无法使用 5 GHz 频段"</string>
<string name="wifi_in_airplane_mode" msgid="4729571191578262246">"正处于飞行模式下"</string>
- <string name="wifi_notify_open_networks" msgid="4782239203624619655">"打开网络通知"</string>
+ <string name="wifi_notify_open_networks" msgid="4782239203624619655">"开放网络通知"</string>
<string name="wifi_notify_open_networks_summary" msgid="1383681260705466715">"有可用的高品质公共网络时通知我"</string>
<string name="wifi_wakeup" msgid="4963732992164721548">"自动开启 WLAN"</string>
<string name="wifi_wakeup_summary" msgid="1152699417411690">"位于已保存的高品质网络(例如您的家庭网络)附近时自动重新开启 WLAN"</string>
@@ -2078,7 +2078,7 @@
<string name="accessibility_control_timeout_preference_title" msgid="2771808346038759474">"操作执行时长"</string>
<string name="accessibility_content_timeout_preference_summary" msgid="853829064617918179">"请选择您需要阅读的消息的显示时间(只会暂时显示)。\n\n只有部分应用支持这项设置。"</string>
<string name="accessibility_control_timeout_preference_summary" msgid="8582212299606932160">"请选择提示您执行操作的消息的显示时间(只会暂时显示)。\n\n部分应用可能不支持这项设置。"</string>
- <string name="accessibility_long_press_timeout_preference_title" msgid="5029685114164868477">"触摸和按住延迟"</string>
+ <string name="accessibility_long_press_timeout_preference_title" msgid="5029685114164868477">"轻触并按住的延迟时间"</string>
<string name="accessibility_display_inversion_preference_title" msgid="3852635518618938998">"颜色反转"</string>
<string name="accessibility_display_inversion_preference_subtitle" msgid="69291255322175323">"可能会影响性能"</string>
<string name="accessibility_autoclick_preference_title" msgid="9164599088410340405">"停留时间"</string>
@@ -3096,7 +3096,7 @@
<string name="keywords_sim_status" msgid="3852088576719874387">"网络, 移动网络状态, 服务状态, 信号强度, 移动网络类型, 漫游, ICCID"</string>
<string name="keywords_model_and_hardware" msgid="2743197096210895251">"序列号, 硬件版本"</string>
<string name="keywords_android_version" msgid="4842749998088987740">"Android 安全补丁程序级别, 基带版本, 内核版本"</string>
- <string name="keywords_dark_ui_mode" msgid="1027966176887770318">"主题背景, 浅色, 夜间, 模式"</string>
+ <string name="keywords_dark_ui_mode" msgid="1027966176887770318">"主题背景, 光亮, 暗黑, 模式"</string>
<string name="keywords_financial_apps_sms_access" msgid="3236014691838121857">"财经应用,短信,权限"</string>
<string name="keywords_systemui_theme" msgid="9150908170417305866">"深色主题背景"</string>
<string name="keywords_device_feedback" msgid="6948977907405738490">"错误"</string>
diff --git a/tests/CarDeveloperOptions/res/values-zh-rHK/strings.xml b/tests/CarDeveloperOptions/res/values-zh-rHK/strings.xml
index 3584151..74a45ec 100644
--- a/tests/CarDeveloperOptions/res/values-zh-rHK/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-zh-rHK/strings.xml
@@ -845,7 +845,7 @@
<string name="wifi_error" msgid="5605801874484465557">"錯誤"</string>
<string name="wifi_sap_no_channel_error" msgid="6881796988574851628">"此國家/地區無法使用 5 GHz 頻譜"</string>
<string name="wifi_in_airplane_mode" msgid="4729571191578262246">"處於飛行模式"</string>
- <string name="wifi_notify_open_networks" msgid="4782239203624619655">"開啟網絡通知"</string>
+ <string name="wifi_notify_open_networks" msgid="4782239203624619655">"開放網絡通知"</string>
<string name="wifi_notify_open_networks_summary" msgid="1383681260705466715">"有高品質的公共網絡時通知我"</string>
<string name="wifi_wakeup" msgid="4963732992164721548">"自動開啟 Wi‑Fi"</string>
<string name="wifi_wakeup_summary" msgid="1152699417411690">"附近有已儲存的高品質網絡 (例如家用網絡) 時會開啟 Wi-Fi"</string>
diff --git a/tests/CarDeveloperOptions/res/values-zh-rTW/arrays.xml b/tests/CarDeveloperOptions/res/values-zh-rTW/arrays.xml
index 12d0899..8b9e3bc 100644
--- a/tests/CarDeveloperOptions/res/values-zh-rTW/arrays.xml
+++ b/tests/CarDeveloperOptions/res/values-zh-rTW/arrays.xml
@@ -204,7 +204,7 @@
<item msgid="8357907018938895462">"啟用 VPN"</item>
<item msgid="8143812849911310973">"寫入桌布"</item>
<item msgid="6266277260961066535">"輔助結構"</item>
- <item msgid="7715498149883482300">"輔助螢幕擷取畫面"</item>
+ <item msgid="7715498149883482300">"輔助螢幕截圖"</item>
<item msgid="4046679376726313293">"讀取手機狀態"</item>
<item msgid="6329507266039719587">"新增語音留言"</item>
<item msgid="7692440726415391408">"使用 SIP"</item>
@@ -232,7 +232,7 @@
<item msgid="3597797992398484655">"讀取日曆"</item>
<item msgid="2705975774250907343">"修改日曆"</item>
<item msgid="4668747371441932697">"定位"</item>
- <item msgid="1487578921720243646">"發佈通知"</item>
+ <item msgid="1487578921720243646">"發布通知"</item>
<item msgid="4636080349724146638">"位置"</item>
<item msgid="673510900286463926">"撥打電話"</item>
<item msgid="542083422784609790">"讀取簡訊/MMS"</item>
@@ -271,7 +271,7 @@
<item msgid="5117506254221861929">"啟用 VPN"</item>
<item msgid="8291198322681891160">"寫入桌布"</item>
<item msgid="7106921284621230961">"輔助結構"</item>
- <item msgid="4496533640894624799">"輔助螢幕擷取畫面"</item>
+ <item msgid="4496533640894624799">"輔助螢幕截圖"</item>
<item msgid="2598847264853993611">"讀取手機狀態"</item>
<item msgid="9215610846802973353">"新增語音留言"</item>
<item msgid="9186411956086478261">"使用 SIP"</item>
diff --git a/tests/CarDeveloperOptions/res/values-zh-rTW/strings.xml b/tests/CarDeveloperOptions/res/values-zh-rTW/strings.xml
index 24abb0a..0b7e7a0 100644
--- a/tests/CarDeveloperOptions/res/values-zh-rTW/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-zh-rTW/strings.xml
@@ -845,7 +845,7 @@
<string name="wifi_error" msgid="5605801874484465557">"錯誤"</string>
<string name="wifi_sap_no_channel_error" msgid="6881796988574851628">"5 GHz 頻帶在這個國家/地區不受支援"</string>
<string name="wifi_in_airplane_mode" msgid="4729571191578262246">"處於飛行模式時"</string>
- <string name="wifi_notify_open_networks" msgid="4782239203624619655">"開啟網路通知"</string>
+ <string name="wifi_notify_open_networks" msgid="4782239203624619655">"開放式網路通知"</string>
<string name="wifi_notify_open_networks_summary" msgid="1383681260705466715">"有高品質的公用網路時通知我"</string>
<string name="wifi_wakeup" msgid="4963732992164721548">"自動開啟 Wi‑Fi"</string>
<string name="wifi_wakeup_summary" msgid="1152699417411690">"位於已儲存的高品質 Wi‑Fi 網路範圍內 (例如家用網路) 時自動重新開啟 Wi‑Fi"</string>
@@ -3396,7 +3396,7 @@
<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="no_channels" msgid="8884254729302501652">"這個應用程式未發佈任何通知"</string>
+ <string name="no_channels" msgid="8884254729302501652">"這個應用程式未發布任何通知"</string>
<string name="app_settings_link" msgid="8465287765715790984">"應用程式中的其他設定"</string>
<string name="app_notification_listing_summary_zero" msgid="4047782719487686699">"已針對所有應用程式開啟這項設定"</string>
<plurals name="app_notification_listing_summary_others" formatted="false" msgid="1161774065480666519">
@@ -3753,10 +3753,10 @@
<string name="background_check_title" msgid="4136736684290307970">"完整背景存取權"</string>
<string name="assist_access_context_title" msgid="2274614501747710439">"使用畫面中的文字"</string>
<string name="assist_access_context_summary" msgid="5867997494395842785">"允許小幫手應用程式存取畫面中的文字內容"</string>
- <string name="assist_access_screenshot_title" msgid="1991014038776117688">"使用螢幕擷取畫面"</string>
+ <string name="assist_access_screenshot_title" msgid="1991014038776117688">"使用螢幕截圖"</string>
<string name="assist_access_screenshot_summary" msgid="3010943864000489424">"允許小幫手應用程式存取畫面擷圖"</string>
<string name="assist_flash_title" msgid="8852484250748551092">"閃爍螢幕"</string>
- <string name="assist_flash_summary" msgid="6697095786317559129">"小幫手應用程式存取螢幕或螢幕擷取畫面中的文字時,螢幕邊緣會閃爍"</string>
+ <string name="assist_flash_summary" msgid="6697095786317559129">"小幫手應用程式存取螢幕或螢幕截圖中的文字時,螢幕邊緣會閃爍"</string>
<string name="assist_footer" msgid="7030121180457472165">"小幫手應用程式可根據你目前瀏覽的畫面資訊,為你提供協助。部分應用程式同時支援啟動器和語音輸入服務,為你提供更完善的服務。"</string>
<string name="average_memory_use" msgid="5333366040118953945">"記憶體平均用量"</string>
<string name="maximum_memory_use" msgid="6509872438499846077">"記憶體最高用量"</string>
diff --git a/tests/DiagnosticTools/Android.mk b/tests/DiagnosticTools/Android.mk
new file mode 100644
index 0000000..c2453ae
--- /dev/null
+++ b/tests/DiagnosticTools/Android.mk
@@ -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.
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := DiagnosticTools
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+LOCAL_CERTIFICATE := platform
+
+#LOCAL_SDK_VERSION := current
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_STATIC_ANDROID_LIBRARIES := androidx.recyclerview_recyclerview \
+ com.google.android.material_material \
+ androidx-constraintlayout_constraintlayout \
+ androidx.appcompat_appcompat \
+ androidx-constraintlayout_constraintlayout-solver
+
+LOCAL_JAVA_LIBRARIES := android.car
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/DiagnosticTools/AndroidManifest.xml b/tests/DiagnosticTools/AndroidManifest.xml
new file mode 100644
index 0000000..55ee4bc
--- /dev/null
+++ b/tests/DiagnosticTools/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?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"
+ package="com.google.android.car.diagnostictools">
+ <uses-permission android:name="android.car.permission.CAR_DIAGNOSTICS"/>
+ <uses-permission android:name="android.car.permission.CLEAR_CAR_DIAGNOSTICS"/>
+ <application android:label="OBD-II Diagnostic Tools" android:theme="@style/AppTheme">
+ <activity android:name=".ECUListActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <activity android:name=".DTCListActivity"/>
+ <activity android:name=".DTCDetailActivity"/>
+ <activity android:name=".LiveDataActivity"/>
+ </application>
+</manifest>
diff --git a/tests/DiagnosticTools/res/drawable/ic_arrow_back_black_24dp.xml b/tests/DiagnosticTools/res/drawable/ic_arrow_back_black_24dp.xml
new file mode 100644
index 0000000..75ae95c
--- /dev/null
+++ b/tests/DiagnosticTools/res/drawable/ic_arrow_back_black_24dp.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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="#FFFFFF"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0"
+ android:width="24dp">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
+</vector>
diff --git a/tests/DiagnosticTools/res/drawable/ic_delete_sweep_black_24dp.xml b/tests/DiagnosticTools/res/drawable/ic_delete_sweep_black_24dp.xml
new file mode 100644
index 0000000..6c933bf
--- /dev/null
+++ b/tests/DiagnosticTools/res/drawable/ic_delete_sweep_black_24dp.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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="#FFFFFF"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0"
+ android:width="24dp">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M15,16h4v2h-4zM15,8h7v2h-7zM15,12h6v2h-6zM3,18c0,1.1 0.9,2 2,2h6c1.1,0 2,-0.9 2,-2L13,8L3,8v10zM14,5h-3l-1,-1L6,4L5,5L2,5v2h12z"/>
+</vector>
diff --git a/tests/DiagnosticTools/res/drawable/ic_select_all_black_24dp.xml b/tests/DiagnosticTools/res/drawable/ic_select_all_black_24dp.xml
new file mode 100644
index 0000000..5729483
--- /dev/null
+++ b/tests/DiagnosticTools/res/drawable/ic_select_all_black_24dp.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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="#FFFFFF"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0"
+ android:width="24dp">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M3,5h2L5,3c-1.1,0 -2,0.9 -2,2zM3,13h2v-2L3,11v2zM7,21h2v-2L7,19v2zM3,9h2L5,7L3,7v2zM13,3h-2v2h2L13,3zM19,3v2h2c0,-1.1 -0.9,-2 -2,-2zM5,21v-2L3,19c0,1.1 0.9,2 2,2zM3,17h2v-2L3,15v2zM9,3L7,3v2h2L9,3zM11,21h2v-2h-2v2zM19,13h2v-2h-2v2zM19,21c1.1,0 2,-0.9 2,-2h-2v2zM19,9h2L21,7h-2v2zM19,17h2v-2h-2v2zM15,21h2v-2h-2v2zM15,5h2L17,3h-2v2zM7,17h10L17,7L7,7v10zM9,9h6v6L9,15L9,9z"/>
+</vector>
diff --git a/tests/DiagnosticTools/res/drawable/ic_show_chart_black_24dp.xml b/tests/DiagnosticTools/res/drawable/ic_show_chart_black_24dp.xml
new file mode 100644
index 0000000..210ede0
--- /dev/null
+++ b/tests/DiagnosticTools/res/drawable/ic_show_chart_black_24dp.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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="#FFFFFF"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0"
+ android:width="24dp">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M3.5,18.49l6,-6.01 4,4L22,6.92l-1.41,-1.41 -7.09,7.97 -4,-4L2,16.99z"/>
+</vector>
diff --git a/tests/DiagnosticTools/res/layout/activity_dtc_details.xml b/tests/DiagnosticTools/res/layout/activity_dtc_details.xml
new file mode 100644
index 0000000..4feb8c4
--- /dev/null
+++ b/tests/DiagnosticTools/res/layout/activity_dtc_details.xml
@@ -0,0 +1,89 @@
+<?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
+ -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/linearLayout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:id="@+id/freeze_frame_clear"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="16dp"
+ android:onClick="clearFreezeFrameButtonPress"
+ android:text="Clear Freeze Frame Data"
+ app:layout_constraintBottom_toTopOf="@+id/freeze_frame_data"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/dtc_details"/>
+ <ProgressBar
+ android:id="@+id/freeze_frame_loading"
+ style="?android:attr/progressBarStyle"
+ android:layout_width="0dp"
+ android:layout_height="128dp"
+ android:visibility="invisible"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="0.0"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/freeze_frame_title"/>
+ <TextView
+ android:id="@+id/dtc_details"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:text="TextView"
+ android:textSize="24sp"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/toolbar"/>
+ <TextView
+ android:id="@+id/freeze_frame_title"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:text="Freeze Frame:"
+ android:textSize="36sp"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/dtc_details"/>
+ <Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/colorPrimary"
+ android:elevation="4dp"
+ android:theme="@android:attr/actionBarTheme"/>
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/freeze_frame_data"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_marginTop="8dp"
+ android:background="#00FF0000"
+ android:minHeight="72dp"
+ android:visibility="visible"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="@+id/freeze_frame_loading"
+ app:layout_constraintHeight_default="spread"
+ app:layout_constraintHeight_min="300dp"
+ app:layout_constraintStart_toStartOf="@+id/freeze_frame_loading"
+ app:layout_constraintTop_toBottomOf="@+id/freeze_frame_title"/>
+ </androidx.constraintlayout.widget.ConstraintLayout>
+</ScrollView>
\ No newline at end of file
diff --git a/tests/DiagnosticTools/res/layout/activity_dtc_list.xml b/tests/DiagnosticTools/res/layout/activity_dtc_list.xml
new file mode 100644
index 0000000..e5f92a5
--- /dev/null
+++ b/tests/DiagnosticTools/res/layout/activity_dtc_list.xml
@@ -0,0 +1,50 @@
+<?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
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/relativeLayout2"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+ <Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/colorPrimary"
+ android:elevation="4dp"
+ android:theme="@android:attr/actionBarTheme"/>
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/dtc_list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scrollbars="vertical"/>
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
+ android:id="@+id/floatingActionButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="16dp"
+ android:layout_gravity="bottom|end"
+ android:clickable="true"
+ android:onClick="onClickActionButton"
+ android:src="@drawable/ic_delete_sweep_black_24dp"/>
+ </FrameLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/DiagnosticTools/res/layout/activity_live_data.xml b/tests/DiagnosticTools/res/layout/activity_live_data.xml
new file mode 100644
index 0000000..dc085a6
--- /dev/null
+++ b/tests/DiagnosticTools/res/layout/activity_live_data.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
+ -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/colorPrimary"
+ android:elevation="4dp"
+ android:theme="@android:attr/actionBarTheme"/>
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/live_data_list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scrollbars="vertical"/>
+ </LinearLayout>
+</ScrollView>
\ No newline at end of file
diff --git a/tests/DiagnosticTools/res/layout/diagnostic_tools.xml b/tests/DiagnosticTools/res/layout/diagnostic_tools.xml
new file mode 100644
index 0000000..44c6f64
--- /dev/null
+++ b/tests/DiagnosticTools/res/layout/diagnostic_tools.xml
@@ -0,0 +1,56 @@
+<?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
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/colorPrimary"
+ android:elevation="4dp"
+ android:theme="@android:attr/actionBarTheme"/>
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/my_recycler_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scrollbars="vertical"/>
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
+ android:id="@+id/floatingActionButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="true"
+ android:layout_gravity="bottom|end"
+ android:layout_margin="16dp"
+ android:src="@drawable/ic_delete_sweep_black_24dp"
+ android:onClick="onClickActionButton"/>
+ </FrameLayout>
+
+
+</LinearLayout>
+
+
diff --git a/tests/DiagnosticTools/res/layout/row_layout.xml b/tests/DiagnosticTools/res/layout/row_layout.xml
new file mode 100644
index 0000000..62728da
--- /dev/null
+++ b/tests/DiagnosticTools/res/layout/row_layout.xml
@@ -0,0 +1,75 @@
+<?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
+ -->
+
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/relativeLayout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="12dp">
+
+ <CheckBox
+ android:id="@+id/checkBox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp"
+ android:layout_marginEnd="8dp"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent"/>
+
+ <TextView
+ android:id="@+id/firstLine"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignWithParentIfMissing="true"
+ android:gravity="center_vertical"
+ android:text="Example application"
+ android:textSize="32sp"
+ app:layout_constraintBottom_toTopOf="@id/secondLine"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toTopOf="parent"/>
+ <TextView
+ android:id="@+id/dtc_number"
+ android:layout_width="wrap_content"
+ android:layout_height="0dp"
+ android:layout_marginEnd="8dp"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:gravity="center"
+ android:text="TextView"
+ android:textSize="32sp"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/checkBox"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintVertical_bias="0.0"/>
+ <TextView
+ android:id="@+id/secondLine"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="marquee"
+ android:singleLine="true"
+ android:text="Description"
+ android:textSize="24sp"
+ android:visibility="visible"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintStart_toStartOf="parent"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/tests/DiagnosticTools/res/raw/system_dtcs.json b/tests/DiagnosticTools/res/raw/system_dtcs.json
new file mode 100644
index 0000000..c41bd28
--- /dev/null
+++ b/tests/DiagnosticTools/res/raw/system_dtcs.json
@@ -0,0 +1,149 @@
+{
+ "P0008": { "short_description":"Engine Position System Performance - Bank 1", "long_description":"<strong>1. Meaning:<\/strong><br> Bank 1 camshaft and the crankshaft have a variation in mechanical timing. Basically the engine control module (ECM) is experiencing timing issues.<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tDecreased power<br> •\tRough acceleration<br> •\tLower fuel economy<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tTiming chain is experiencing tension<br> •\tTiming chain is stretched<br> •\tCrankshaft reluctor wheel is not referenced to TDC (top dead center)<br> •\tWiring damage<br> •\tWorn out timing components<br> •\tInternal damage to ECM<br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUse an advanced diagnostic tool to pull engine codes<br> •\tVisually inspect the VCT/VVT circuit for open/damaged wires."},
+ "P0010": { "short_description":"Intake Camshaft Position Actuator Circuit / Open (Bank 1)", "long_description":"<strong>1. Meaning:<\/strong><br> Bank 1 camshaft and the crankshaft have a variation in mechanical timing. The problem occurs when the engine experiences high RPM. The ECM doesn’t properly adjust valve lift at high RPM.<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine performs poorly at high RPM<br> •\tCar runs roughly<br> •\tLower fuel economy<br> •\tCar fails emission test<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tSludge in engine oil<br> •\tFaulty OVC (oil control valve)<br> •\tInternal damage to ECM<br> •\tECM timing is out of sync<br> •\tWiring damage<br> •\tMalfunction of crankshaft or camshaft sensor<br> •\tA short in VCT/VVT circuit, or the circuit is open<br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUse an advanced diagnostic tool to pull engine codes<br> •\tInspect the VVT/VCT solenoid system for dirty oil<br> •\tInspect the circuit for wiring problems"},
+ "P0011": { "short_description":"Intake Camshaft Position Timing - Over-Advanced (Bank 1)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe camshaft timing for bank 1 is above and beyond the limit set by the ECM. This causes an over-advanced condition that occurs either during retarding or advancing of the camshaft timing<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tHard starting<br> •\tPoor idle<br> •\tCar may run rough or stall<br> •\tPoor fuel economy<br> •\tCar may fail emission test<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tCamshaft remains advanced despite ECM commanding it to retard<br> •\tBank 1 oil control solenoid may be clogged or stuck<br> •\tOil may be too thick and is thus blocking passages in bank 1<br> •\tWiring problems in VCT/VVT<br> •\tOil continuously flows to VCT piston chamber<br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck that engine oil is clean and has the recommended viscosity<br> •\tVisually inspect wiring in the CVT system<br> •\tPull engine codes and live data using advanced diagnostic tool"},
+ "P0012": { "short_description":"Intake Camshaft Position Timing - Over-Retarded (Bank 1)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tBank 1 is having an over-retarded timing condition that occurs either during retarding or advancing<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tHard starting<br> •\tPoor fuel economy<br> •\tCar may run rough or stall<br> •\tCar may fail emission test<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tCamshaft timing is incorrect<br> •\tWiring problems in VCT/VVT<br> •\tOil continuously flows to VCT piston chamber<br> •\tTiming valve solenoid control has failed and is stuck in open position<br> •\tOil may be too thick and is thus blocking passages in bank 1<br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck that engine oil is clean<br> •\tVisually inspect wiring in the CVT system<br> •\tPull engine codes and live data using advanced diagnostic tool<br> •\tUsing bidirectional scanner, command the timing valve solenoid control valve to open and close then see if camshaft timings change. If they change it means the valve is not the problem"},
+ "P0014": { "short_description":"Exhaust Camshaft Position Timing - Over-Advanced (Bank 1)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tBank 1 camshaft is having an over-advanced timing condition that occurs either during retarding or advancing<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tHard starting<br> •\tPoor fuel economy<br> •\tCar may run rough or stall<br> •\tCar may fail emission test<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tCamshaft timing is incorrect<br> •\tWiring problems in VCT/VVT<br> •\tOil continuously flows to VCT piston chamber<br> •\tTiming valve solenoid control has failed and is stuck in open position<br> •\tOil may be too thick and is thus blocking passages in bank 1<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck that engine oil is clean and full in the tank<br> •\tVisually inspect wiring in the CVT system<br> •\tPull engine codes and live data using advanced diagnostic tool<br> •\tUsing bidirectional scanner, command the timing valve solenoid control valve to open and close then see if camshaft timings change. If they change it means the valve is not the problem"},
+ "P0016": { "short_description":"Crankshaft Position Camshaft Position Correlation Bank 1 Sensor A", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe crankshaft and camshaft signals are out of time. Meaning the ECM can detect that the timing of the crankshaft and that of the camshaft do not correlate <br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine may crank but fail to start<br> •\tEngine may continue to run but will record poor performance<br> •\tRattling sound in the harmonic balancer<br> •\tPoor fuel economy<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tTiming chain is overstretched<br> •\tTone ring on camshaft and/or crankshaft is has slipped or broken<br> •\tTiming chain has jumped teeth and put camshaft timing out of position<br> •\tProblems with camshaft phaser and putting the phaser out of position<br> •\tWiring to crank/cam sensor is damaged<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect oil control valve (OCV) for connection or wiring problems<br> •\tCheck that engine oil is clean, full and has correct viscosity<br> •\tPull engine codes and live data using advanced diagnostic tool<br> •\tUsing bidirectional scanner, command the OVC on and off then see if camshaft timings change. If they change it means the valve is not the problem"},
+ "P0021": { "short_description":"Intake Camshaft Position Timing - Over-Advanced (Bank 2)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe camshaft timing for bank 2 is above and beyond the limit set by the ECM. This causes an over-advanced condition that occurs either during retarding or advancing of the camshaft timing<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tHard starting<br> •\tPoor idle<br> •\tCar may run rough or stall<br> •\tPoor fuel economy<br> •\tCar may fail emission test<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tCamshaft remains advanced despite ECM commanding it to retard<br> •\tBank 2 oil control solenoid may be clogged or stuck<br> •\tOil may be too thick and is thus blocking passages in bank 2<br> •\tWiring problems in VCT/VVT<br> •\tOil continuously flows to VCT piston chamber<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck that engine oil is clean and has the recommended viscosity<br> •\tVisually inspect wiring in the CVT system<br> •\tPull engine codes and live data using advanced diagnostic tool"},
+ "P0022": { "short_description":"“A” camshaft position – timing over-retarded (Bank 2)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe camshaft timing for bank 2 is over-retarded<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCar stalls<br> •\tCar hard starts<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tCamshaft remains retarded despite ECM commanding it to advance<br> •\tWiring problems in VCT/VVT<br> •\tOil continuously flows to VCT piston chamber<br> •\tTiming valve controlled solenoid has failed and remains open<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect wiring in the CVT system<br> •\tPull engine codes and live data using advanced diagnostic tool<br> •\tReset the codes. If P0022 returns use a bidirectional tool to check whether VCT solenoid is working"},
+ "P0030": { "short_description":"Heated Oxygen Sensor (H02S) Heater Control Circuit Bank 1 Sensor 1", "long_description":"<strong>1. Meaning:<\/strong><br> •\tBank 1, sensor 1 of the O2 sensor heater circuit is faulty. As such, the engine isn’t achieving closed loop and therefore the car has increased emissions<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tLonger time needed to achieve closed loop<br> •\tDecreased fuel economy<br> •\tEngine may go into fixed fuel mix<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tH02S sensor in bank 1, circuit 1 is not sending the correct signal to ECM<br> •\tDamaged or failed element in heater circuit<br> •\tOpen in O2 sensor heater’s circuit<br> •\tOpen/short in O2 sensor heater’s battery<br> •\tDefective ECM (this is the least likely cause)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect wiring and power to the O2 sensor and ensure there’s no damage/open/short<br> •\tUse code reader to pull engine codes<br> •\tCheck voltage of O2 sensor and ensure it matches manufacturer’s specs<br> •\tReplace O2 sensor if necessary"},
+ "P0031": { "short_description":"Heated Oxygen Sensor (HO2S) Heater Circuit Low Voltage Bank 1 Sensor 1", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe resistance of the heater circuit in bank 1 is too low to heat fuel until it achieves air to fuel ratio of 14:7. The problem is coming from the 1st sensor of bank 1. This code is usually triggered when resistance level is below 0.8A<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tAlthough not always, ECM may enter failsafe mode<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tShort or open in the O2 heater circuit<br> •\tDefective O2 sensor heater<br> •\tThere’s a wiring problem in the circuit leading to the heater. It may be broken or frayed<br> •\tDefective ECM (this is the least likely cause)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect wiring and power to the O2 sensor and ensure there’s no damage/open/short<br> •\tUse code reader to pull engine codes"},
+ "P0037": { "short_description":"Heated Oxygen Sensor (H02S) Heater Control Circuit Bank 1 Sensor 2", "long_description":"<strong>1. Meaning:<\/strong><br> •\tBank 1, sensor 2 of the O2 sensor heater circuit is faulty. As such, the engine isn’t achieving closed loop and therefore the car has increased emissions<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tLonger time needed to achieve closed loop<br> •\tDecreased fuel economy<br> •\tEngine may go into fixed fuel mix<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tH02S sensor in bank 1, circuit 2 is not sending the correct signal to ECM<br> •\tDamaged or failed element in heater circuit<br> •\tOpen in O2 sensor heater’s circuit<br> •\tOpen/short in O2 sensor heater’s battery<br> •\tDefective ECM (this is the least likely cause)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect wiring and power to the O2 sensor and ensure there’s no damage/open/short<br> •\tUse code reader to pull engine codes<br> •\tCheck voltage of O2 sensor and ensure it matches manufacturer’s specs<br> •\tReplace O2 sensor if necessary"},
+ "P0087": { "short_description":"Fuel Rail/System Pressure - Too Low", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe ECM has determined that the pressure of fuel going to the fuel pump module is below the pressure that was commanded by the ECM<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tVehicle may have a rich fuel condition<br> •\tIt may also misfire<br> •\tVehicle may run poorly<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tClogged fuel filter or fuel screen<br> •\tDefective fuel pressure sensor<br> •\tDefective fuel pump<br> •\tFault in fuel line that’s causing a restriction<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUse code reader to pull engine codes<br> •\tVisually inspect fuel tank, fuel filter and fuel lines<br> •\tTake manual readings of fuel pressure and compare with specifications<br> •\tRun a fuel pump test"},
+ "P0102": { "short_description":"Mass or Volume Air Flow Circuit low Input", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe mass airflow (MAF) sensor is not performing within the normal expectation and is therefore sending a lower signal than normal (due to low voltage)<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tExtremely low fuel consumption and thus internal engine problems<br> •\tEngine runs roughly<br> •\tCar idles and stalls frequently<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective MAF sensor<br> •\tPresence of dirt and debris in MAF (restricts airflow)<br> •\tLeaks in air intake system<br> •\tImproper wiring of the circuit to MAF sensor<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUse code reader to pull engine codes <br> •\tVisually inspect MAF sensor wiring and circuit<br> •\tCheck for air leaks in air intake system<br> •\tInspect MAF to see if there’s dirt and debris"},
+ "P0106": { "short_description":"Manifold Absolute Pressure/Barometric Pressure Circuit Range/Performance Problem", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe Powertrain Control Module (PCM) has not detected a change in engine speed, throttle angle and/or exhaust gas recirculation (EGR) despite an increase in manifold absolute pressure (MAP). Increase in MAP indicates increase in engine load<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tPoor fuel economy<br> •\tEngine fails to idle<br> •\tEngine produces black smoke (visible at tailpipe)<br> •\tErratic acceleration<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tFaulty MAP sensor<br> •\tAir intake component is loose, cracked or doesn’t have its plastic fitting<br> •\tWater or dirt affecting connector to MAP sensor<br> •\tCorrosion may be causing poor signal to and from MAP sensor<br> •\tPCM is defective (least likely but not unlikely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUse an advanced scanner to pull engine codes <br> •\tWith that scanner, take the reading of MAP sensor when engine is off but key is on. It should be similar or close to barometric pressure (BARO) reading<br> •\tStart the engine and see if MAP sensor readings drop significantly. If they do the sensor is working properly "},
+ "P0107": { "short_description":"Manifold Absolute Pressure/Barometric Pressure Circuit Low Input", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that the voltage in the MAP sensor is less than .25 volts, which is too low to send a reliable signal<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tVehicle is hard to start<br> •\tPoor fuel economy<br> •\tEngine fails to idle<br> •\tEngine produces black smoke (visible at tailpipe)<br> •\tEngine cranks for long<br> •\tErratic acceleration<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tFaulty MAP sensor<br> •\tOpen or short in signal circuit, 5volt reference circuit or ground circuit<br> •\tPCM is defective (least likely but not unlikely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUse an advanced scanner to pull engine codes <br> •\tWith that scanner, take the voltage of MAP sensor when engine is on and key is on. If it’s less than .5V turn the engine off, remove the MAP sensor and use a volt/ohm meter to check for 5 volts on the 5 volt reference circuit"},
+ "P0108": { "short_description":"Manifold Absolute Pressure/Barometric Pressure Circuit High Input", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that the voltage in the MAP sensor is more than 5 volts or generally more than commanded under the prevailing circumstance<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tPoor fuel economy<br> •\tEngine fails to idle and may not start completely<br> •\tEngine produces black smoke (visible at tailpipe)<br> •\tEngine cranks for long<br> •\tErratic acceleration<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tFaulty MAP sensor<br> •\tOpen or short in signal circuit, 5volt reference circuit or ground circuit<br> •\tLeak in vacuum system, especially in the engine or supply line to MAP sensor<br> •\tPCM is defective (least likely but not unlikely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUse an advanced scanner to pull engine codes <br> •\tWith that scanner, take the reading of MAP sensor when engine is off but key is on. It should be similar or close to barometric pressure (BARO) reading<br> •\tIf the difference between the two readings is more than .5 then you’re looking at a faulty MAP sensor"},
+ "P0113": { "short_description":"Intake Air Temperature Circuit High Input", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe PCM has detected that the signal voltage from the intake air temperature (IAT) is above 5V, which is more than the expected range<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine may run extra lean<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective IAT sensor<br> •\tLoose or faulty wiring at IAT sensor<br> •\tOpen or short in IAT ground circuit, signal circuit or reference circuit<br> •\tPCM is defective (least likely but not unlikely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUse an advanced scanner to pull engine codes.<br> •\tView live data from the IAT sensor. If the reading is less than -30 degrees then the sensor is likely to be faulty. If otherwise then it’s probably an intermittent problem<br> •\tCheck the wiring for opens and loose connections"},
+ "P0116": { "short_description":"Engine Coolant Temperature Circuit Range/Performance Problem", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe PCM has seen a sudden and quick change in engine coolant temperature (ECT) at a time when there shouldn’t be such a change<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tPoor fuel economy<br> •\tEngine fails to idle and may not start completely<br> •\tEngine produces black smoke (visible at tailpipe)<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tThermostat is either missing or open<br> •\tDefective ECT sensor<br> •\tOpen or short in ECT signal or ground circuit<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing an OBD2 scanner, start by diagnosing and resetting any other ECT codes<br> •\tNow, check the ECT reading. When the engine is cold the reading should match ambient temperature reading. If it doesn’t then there’s a problem with the ECT sensor"},
+ "P0118": { "short_description":"Engine Coolant Temperature Circuit High Input", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe PCM has determined that ECT is less than freezing temp yet the engine has been running for several minutes, which shouldn’t happen<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tPoor fuel economy<br> •\tEngine fails to idle and may not start completely<br> •\tEngine produces black smoke (visible at tailpipe)<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective ECT sensor<br> •\tOpen or short in ECT signal or ground circuit<br> •\tPCM is defective (least likely but not unlikely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing an OBD2 scanner, check the reading of ECT. If it’s a logical reading then the problem is intermittent<br> •\tPerform a wiggle test while looking out for drop-outs. If there are any then there’s a bad connection to or from the ECT sensor"},
+ "P0121": { "short_description":"Throttle/Pedal Position Sensor/Switch A Circuit Range/Performance Problem", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe PCM has detected that the throttle position sensor (TPS) voltage is more or less than it should be for the current RPM<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCar produces black smoke (visible at tailpipe)<br> •\tCar stumbles when you accelerate or decelerate<br> •\tEngine may fail to start completely<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective TPS<br> •\tOpen or short in TPS circuit<br> •\tLoose or bad connection to TPS<br> •\tPCM is defective (least likely but not unlikely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to TPS for loose, open or short connections <br> •\tUsing an OBD2 scanner, check for live and freeze frame data from TPS. If it doesn’t read .5 at idle and 4.5 at full throttle the TPS is faulty"},
+ "P0122": { "short_description":"Throttle/Pedal Position Sensor/Switch A Circuit Low Input", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM is reporting that the TPS has recorded a voltage that is lower than the normal minimum limit. The value varies from one car to another but the code may come when the voltage hits .20V or less<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tExtremely high idle<br> •\tRough or low idle<br> •\tCar stalls<br> •\tAcceleration is low or completely lacking<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective TPS<br> •\tOpen or short in TPS circuit<br> •\tImproper mounting of TPS after replacement<br> •\tTPS has loosened<br> •\tPCM is defective (least likely but not unlikely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to TPS for loose, open or short connections<br> •\tCheck that TPS is tightly in position, especially if you recently replaced it"},
+ "P0123": { "short_description":"Throttle/Pedal Position Sensor/Switch A Circuit High Input", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM is reporting that the TPS has recorded a voltage that is higher than the normal maximum limit, usually around 5 volts<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tExtremely high idle<br> •\tRough or low idle<br> •\tFrequent surges<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective TPS<br> •\tOpen or short in TPS circuit<br> •\tImproper mounting of TPS after replacement<br> •\tPCM is defective (least likely but not unlikely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to TPS for loose, open or short connections<br> •\tCheck that TPS is tightly in position, especially if you recently replaced it"},
+ "P0128": { "short_description":"Coolant Thermostat (Coolant Temp Below Thermostat Regulating Temperature)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that the engine has not attained the required temperature despite being on for enough time to attain that temperature<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light MAY come on<br> •\tEngine temp drops when the vehicle is in high speed<br> •\tEngine takes abnormally long to warm<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tMost likely cause is that thermostat is leaking or stuck in open position<br> •\tEngine coolant level is too low<br> •\tDefective IAT sensor<br> •\tDefective ECT sensor<br> •\tDefective cooling fan<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck whether coolant strength and level are in the recommended range<br> •\tCheck whether IAT sensor, ECT sensor and coolant fan are working<br> •\tIf all the above are okay then the thermostat is the problem"},
+ "P0130": { "short_description":"O2 Sensor Circuit Malfunction (Bank 1 Sensor 1)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tECM has determined that the O2 sensor voltage remained lower than normal (below .4v) for too long (20 seconds or more)<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCar produces black smoke (visible at tailpipe)<br> •\tPoor fuel economy<br> •\tEngine may fail to start completely<br> •\tIf it starts it may run rough and/or stumble<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tMostly a problem related to corrosion, loose terminal or burnt wire in the O2 sensor connector<br> •\tDefective O2 sensor<br> •\tOpen or short in wiring to O2 sensor<br> •\tUnmetered oxygen is getting back into exhaust system, most likely from holes in the system<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to O2 sensor for loose, open or short connections<br> •\tUse a wiggle test to determine where the voltage drops out<br> •\tUsing an OBD2 scanner, check whether sensor 1 of bank 1 is switching properly. Normally it should switch evenly between rich and lean in rapid successions"},
+ "P0131": { "short_description":"O2 Sensor Circuit Low Voltage (Bank 1 Sensor 1)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tECM has determined that there’s a low voltage condition in bank 1 sensor 1; i.e. O2 sensor voltage remained too low for longer than 2 minutes<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCar produces black smoke (visible at tailpipe)<br> •\tPoor fuel economy<br> •\tEngine may fail to start completely<br> •\tIf it starts it may run rough and/or stumble<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tMostly a problem related to corrosion, loose terminal or burnt wire in the O2 sensor 1 connector<br> •\tDefective O2 sensor<br> •\tOpen or short in wiring to O2 sensor<br> •\tO2 circuit is experiencing high resistance<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to O2 sensor 1 for loose, open or short connections<br> •\tUse a wiggle test to determine where the voltage drops out<br> •\tUsing an OBD2 scanner, check whether sensor 1 of bank 1 is switching properly."},
+ "P0132": { "short_description":"O2 Sensor Circuit High Voltage (Bank 1 Sensor 1)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe heated O2 sensor in bank 1 sensor 1 is giving a higher voltage reading than it should. For most vehicles the code comes when voltage exceeds 1.5V<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tGenerally doesn’t come with symptoms. However, in some cases the Check Engine Light may come on and fuel economy may reduce<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tFuel temp is excessively high<br> •\tShort, open or broken wire in O2 sensor circuit<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to O2 sensor for loose, open or short connections<br> •\tUse a wiggle test to determine where the voltage drops out<br> •\tUsing an OBD2 scanner, check whether sensor 1 of bank 1 is switching properly."},
+ "P0133": { "short_description":"O2 Sensor Circuit Slow Response (Bank 1 Sensor 1)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tO2 sensor or ECM can’t adjust air to fuel ratio as it’s supposed to even when the engine is running<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tGenerally doesn’t come with symptoms. However, in some cases the Check Engine Light may come on and fuel economy may reduce<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tFirst O2 sensor in bank 1 is faulty<br> •\tShort, open or broken wire in O2 sensor circuit<br> •\tExhaust leak<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to first O2 sensor for loose, open or short connections<br> •\tUse a wiggle test to determine where the voltage drops out<br> •\tVisually check for exhaust leaks or air inlet leaks<br> •\tUsing an OBD2 scanner, check whether sensor 1 of bank 1 is switching properly."},
+ "P0134": { "short_description":"O2 Sensor Circuit No Activity Detected (Bank 1 Sensor 1)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has perceived that first O2 sensor in bank 1 is inactive or open because it has not warmed up after more than 1 minute of the engine running<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCar produces black smoke (visible at tailpipe)<br> •\tPoor fuel economy<br> •\tEngine may run rough and/or stumble<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tFaulty O2 sensor<br> •\tShort, open or broken wire in O2 sensor circuit<br> •\tExhaust leak<br> •\tDefective heater circuit in O2 sensor<br> •\tHeater circuit has blown fuse<br> •\tPCM is defective (least likely but not unlikely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to first O2 sensor (bank 1) for loose, open or short connections<br> •\tUse a wiggle test to determine where the voltage drops out<br> •\tVisually check for exhaust leaks or air inlet leaks"},
+ "P0135": { "short_description":"O2 Sensor Heater Circuit Malfunction (Bank 1 Sensor 1)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tUsually, when O2 heater attains operating temperature, O2 sensor switches based on ambient temp. If ECM determines that the O2 sensor took too long to switch this code is set. It applies to the first sensor of bank 1<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tPoor fuel economy<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tShort, open or broken wire in O2 heating system<br> •\tHigh resistance in O2 heater element or circuit<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to first O2 sensor (bank 1) for loose, open or short connections<br> •\tUse a wiggle test to determine where the voltage drops out<br> •\tIf the code is persistent replace O2 sensor<br> "},
+ "P0136": { "short_description":"O2 Sensor Circuit Malfunction (Bank 1 Sensor 2)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tECM has determined that the there’s a low voltage condition in bank 1 sensor 2; i.e. O2 sensor voltage remained too low for longer than 2 minutes<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCar produces black smoke (visible at tailpipe)<br> •\tPoor fuel economy<br> •\tEngine may fail to start completely<br> •\tIf it starts it may run rough and/or stumble<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tMostly a problem related to corrosion, loose terminal or burnt wire in the O2 sensor 2 connector<br> •\tDefective O2 sensor<br> •\tOpen or short in wiring to O2 sensor<br> •\tO2 circuit is experiencing high resistance<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to O2 sensor 2 for loose, open or short connections<br> •\tUse a wiggle test to determine where the voltage drops out<br> •\tUsing an OBD2 scanner, check whether sensor 2 of bank 1 is switching properly."},
+ "P0137": { "short_description":"O2 Sensor Circuit Low Voltage (Bank 1 Sensor 2)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tBasically same as P0136. The PCM has detected that the O2 sensor may be inactive<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tGenerally doesn’t come with symptoms. However, in some cases the Check Engine Light may come on and fuel economy may reduce<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tFaulty O2 sensor<br> •\tShort, open or broken wire in O2 sensor circuit<br> •\tDefective heater circuit in O2 sensor<br> •\tHigh resistance in O2 heater element or circuit<br> •\tFaulty fuel pump regulator resulting in very high or very low fuel pressure<br> •\tExhaust leak<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to O2 sensor for loose, open or short connections<br> •\tUse a wiggle test to determine where the voltage drops out<br> •\tVisually check for exhaust leaks or air inlet leaks<br> •\tIf the code is persistent replace O2 sensor"},
+ "P0138": { "short_description":"O2 Sensor Circuit High Voltage (Bank 1 Sensor 2)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe heated O2 sensor in bank 1 sensor 2 is giving a higher voltage reading than it should. For most vehicles the code comes when voltage exceeds 1.5V<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tGenerally doesn’t come with symptoms. However, in some cases the Check Engine Light may come on and fuel economy may reduce<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tFuel temp is excessively high<br> •\tShort, open or broken wire in O2 sensor circuit<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to O2 sensor for loose, open or short connections<br> •\tUse a wiggle test to determine where the voltage drops out<br> •\tUsing an OBD2 scanner, check whether sensor 1 of bank 2 is switching properly."},
+ "P0139": { "short_description":"O2 Sensor Circuit Slow Response (Bank 1 Sensor 2)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tO2 sensor or ECM can’t adjust air to fuel ratio as it’s supposed to even when the engine is running<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tGenerally doesn’t come with symptoms. However, in some cases the Check Engine Light may come on and fuel economy may reduce<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tSecond O2 sensor in bank 1 is faulty<br> •\tShort, open or broken wire in O2 sensor circuit<br> •\tExhaust leak<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to second O2 sensor for loose, open or short connections<br> •\tUse a wiggle test to determine where the voltage drops out<br> •\tVisually check for exhaust leaks or air inlet leaks<br> •\tUsing an OBD2 scanner, check whether sensor 2 of bank 1 is switching properly."},
+ "P0140": { "short_description":"O2 Sensor Circuit No Activity Detected (Bank 2 Sensor 2)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has perceived that second O2 sensor in bank 2 is inactive or open because it has not warmed up after more than 1 minute of the engine running<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCar produces black smoke (visible at tailpipe)<br> •\tPoor fuel economy<br> •\tEngine may run rough and/or stumble<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tFaulty O2 sensor<br> •\tShort, open or broken wire in O2 sensor circuit<br> •\tExhaust leak<br> •\tDefective heater circuit in O2 sensor<br> •\tHeater circuit has blown fuse<br> •\tPCM is defective (least likely but not unlikely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to second O2 sensor (in bank 2) for loose, open or short connections<br> •\tUse a wiggle test to determine where the voltage drops out<br> •\tVisually check for exhaust leaks or air inlet leaks"},
+ "P0141": { "short_description":"O2 Sensor Heater Circuit Malfunction (Bank 1 Sensor 2)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tWhen O2 heater attains operating temperature, O2 sensor switches based on ambient temp. If ECM determines that the O2 sensor took too long to switch this code is set. It applies to the second sensor of bank 1<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tPoor fuel economy<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tShort, open or broken wire in O2 heating system<br> •\tHigh resistance in O2 heater element or circuit<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to second O2 sensor (bank 1) for loose, open or short connections<br> •\tUse a wiggle test to determine where the voltage drops out<br> •\tIf the code is persistent replace O2 sensor"},
+ "P0151": { "short_description":"O2 Sensor Circuit Low Voltage (Bank 2 Sensor 1)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tECM has determined that there’s a low voltage condition in bank 2 sensor 1; i.e. O2 sensor voltage remained too low for longer than 2 minutes<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCar produces black smoke (visible at tailpipe)<br> •\tPoor fuel economy<br> •\tEngine may fail to start completely<br> •\tIf it starts it may run rough and/or stumble<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tMostly a problem related to corrosion, loose terminal or burnt wire in the O2 sensor 2 connector<br> •\tDefective O2 sensor<br> •\tOpen or short in wiring to O2 sensor<br> •\tO2 circuit is experiencing high resistance<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to O2 sensor 1 for loose, open or short connections<br> •\tUse a wiggle test to determine where the voltage drops out<br> •\tUsing an OBD2 scanner, check whether sensor 1 of bank 2 is switching properly."},
+ "P0153": { "short_description":"O2 Sensor Circuit Slow Response (Bank 2 Sensor 1)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tO2 sensor or ECM can’t adjust air to fuel ratio as it’s supposed to even when the engine is runningc<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tGenerally doesn’t come with symptoms. However, in some cases the Check Engine Light may come on and fuel economy may reduce<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tFirst O2 sensor in bank 2 is faulty<br> •\tShort, open or broken wire in O2 sensor circuit<br> •\tExhaust leak<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to second O2 sensor for loose, open or short connections<br> •\tUse a wiggle test to determine where the voltage drops out<br> •\tVisually check for exhaust leaks or air inlet leaks<br> •\tUsing an OBD2 scanner, check whether sensor 1 of bank 2 is switching properly."},
+ "P0154": { "short_description":"O2 Sensor Circuit No Activity Detected (Bank 2 Sensor 1)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has perceived that first O2 sensor in bank 2 is inactive or open because it has not warmed up after more than 1 minute of the engine running<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCar produces black smoke (visible at tailpipe)<br> •\tPoor fuel economy<br> •\tEngine may run rough and/or stumble<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tFaulty O2 sensor<br> •\tShort, open or broken wire in O2 sensor circuit<br> •\tExhaust leak<br> •\tDefective heater circuit in O2 sensor<br> •\tHeater circuit has blown fuse<br> •\tPCM is defective (least likely but not unlikely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to first O2 sensor (bank 2) for loose, open or short connections<br> •\tUse a wiggle test to determine where the voltage drops out<br> •\tVisually check for exhaust leaks or air inlet leaks"},
+ "P0157": { "short_description":"O2 Sensor Circuit Low Voltage (Bank 2 Sensor 2)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tECM has determined that there’s a low voltage condition in bank 2 sensor 2; i.e. O2 sensor voltage remained too low for longer than 2 minutes<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCar produces black smoke (visible at tailpipe)<br> •\tPoor fuel economy<br> •\tEngine may fail to start completely<br> •\tIf it starts it may run rough and/or stumble<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tMostly a problem related to corrosion, loose terminal or burnt wire in the O2 sensor 2 connector<br> •\tDefective O2 sensor<br> •\tOpen or short in wiring to O2 sensor<br> •\tO2 circuit is experiencing high resistance<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to O2 sensor 2 for loose, open or short connections<br> •\tUse a wiggle test to determine where the voltage drops out<br> •\tUsing an OBD2 scanner, check whether sensor 2 of bank 2 is switching properly."},
+ "P0161": { "short_description":"O2 Sensor Heater Circuit Malfunction (Bank 2 Sensor 2)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tWhen O2 heater attains operating temperature, O2 sensor switches based on ambient temp. If ECM determines that the O2 sensor took too long to switch this code is set. It applies to the second sensor of bank 2<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tPoor fuel economy<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tShort, open or broken wire in O2 heating system<br> •\tHigh resistance in O2 heater element or circuit<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to second O2 sensor (bank 2) for loose, open or short connections<br> •\tUse a wiggle test to determine where the voltage drops out<br> •\tIf the code is persistent replace O2 sensor"},
+ "P0171": { "short_description":"System Too Lean (Bank 1)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThere’s a lean condition in bank 1; i.e. there’s excess oxygen in the exhaust<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tSignificant decrease in engine power<br> •\tCar hesitates then surges upon acceleration<br> •\tRough idle<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDirty or defective MAF sensor<br> •\tMAF sensor has a vacuum leak<br> •\tPositive Crankcase Ventilation (PCV) valve is stuck in open position<br> •\tLeak either in PCV or vacuum system<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect MAF sensor in bank 1 for dirt and debris<br> •\tCheck whether fuel pressure is correct<br> •\tCheck vacuum and PCV for leaks<br> •\tRun a smog test using OBD2 scanner"},
+ "P0172": { "short_description":"System Too Rich (Bank 1)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThere’s a rich condition in bank 1; i.e. there’s too little oxygen in the exhaust<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tGenerally doesn’t come with symptoms but the Check Engine Light may come on and engine may misfire<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDirty or defective MAF sensor<br> •\tMAF sensor has a vacuum leak<br> •\tProblem relating to fuel pressure or delivery<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect MAF sensor in bank 1 for dirt and debris<br> •\tCheck whether fuel pressure is correct<br> •\tInspect fuel lines and injectors for any leaks/openings and dirt<br> •\tCheck vacuum, PCV and exhaust for leaks<br> •\tRun a smog test using OBD2 scanner"},
+ "P0174": { "short_description":"System Too Lean (Bank 2)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThere’s a lean condition in bank 2; i.e. there’s excess oxygen in the exhaust<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tSignificant decrease in engine power<br> •\tCar hesitates then surges upon acceleration<br> •\tRough idle<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDirty or defective MAF sensor<br> •\tMAF sensor has a vacuum leak<br> •\tPositive Crankcase Ventilation (PCV) valve is stuck in open position<br> •\tLeak either in PCV or vacuum system<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect MAF sensor in bank 2 for dirt and debris<br> •\tCheck whether fuel pressure is correct<br> •\tCheck vacuum and PCV for leaks<br> •\tRun a smog test using OBD2 scanner"},
+ "P0175": { "short_description":"System Too Rich (Bank 2)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThere’s a rich condition in bank 2; i.e. there’s too little oxygen in the exhaust<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tGenerally doesn’t come with symptoms but the Check Engine Light may come on and engine may misfire<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDirty or defective MAF sensor<br> •\tMAF sensor has a vacuum leak<br> •\tProblem relating to fuel pressure or delivery<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect MAF sensor in bank 2 for dirt and debris<br> •\tCheck whether fuel pressure is correct<br> •\tInspect fuel lines and injectors for any leaks/openings and dirt<br> •\tCheck vacuum, PCV and exhaust for leaks<br> •\tRun a smog test using OBD2 scanner"},
+ "P0193": { "short_description":"Fuel Rail Pressure Sensor Circuit High Input", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe PCM has detected that the pressure of fuel is not within the range that’s predetermined by the car manufacturer <br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine cranks but doesn’t start<br> •\tCar hesitates upon acceleration<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective fuel rail pressure (FRP) sensor<br> •\tDefective fuel pump<br> •\tOpen or short in FRP circuit<br> •\tLow or no fuel in tank<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect all wiring and connections in FRP circuit and check for shorts, opens, broken and melted wires<br> •\tCheck for corroded or burnt terminals in connectors<br> •\tUse a scan tool to pull codes and freeze frame data"},
+ "P0300": { "short_description":"Random/Multiple Cylinder Misfire Detected", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that there’s an engine cylinder that’s not firing properly. It could be one or more cylinders. PCM hasn’t specified the exact cylinder<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCheck Engine Light may flash<br> •\tEngine lacks power<br> •\tEngine may be hard to start<br> •\tEngine may stumble and hesitate frequently<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective or worn out spark plugs<br> •\tLow fuel pressure<br> •\tVacuum leak<br> •\tDefective catalytic converter<br> •\tDefective fuel injector<br> •\tDefective coil<br> •\tDefective camshaft position sensor<br> •\tDefective crankshaft sensor<br> •\tProblem with distributor<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing a scan tool, pull codes and see if there are any other besides P0300. Address the others first<br> •\tInspect whether there are loose, open or short wires in ignition coils<br> •\tInspect whether spark plugs and their wires are in good condition<br> •\tCheck that fuel pressure is within the recommended range<br> •\tInspect fuel injectors to see whether they are in good condition"},
+ "P0301": { "short_description":"Cylinder 1 Misfire Detected", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that cylinder #1 is not firing properly<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCheck Engine Light may flash<br> •\tEngine lacks power<br> •\tEngine may be hard to start<br> •\tEngine may stumble and hesitate frequently<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective or worn out spark plugs in cylinder 1<br> •\tLow fuel pressure<br> •\tVacuum leak<br> •\tDefective catalytic converter<br> •\tDefective fuel injector<br> •\tDefective coil<br> •\tDefective camshaft position sensor<br> •\tDefective crankshaft sensor<br> •\tProblem with distributor<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing a scan tool, pull codes and see if there are any other besides P0301. Address the others first<br> •\tInspect whether there are loose, open or short wires in ignition coils in cylinder 1<br> •\tInspect whether cylinder 1 spark plugs and their wires are in good condition<br> •\tCheck that fuel pressure is within the recommended range<br> •\tInspect fuel injectors to see whether they are in good condition"},
+ "P0302": { "short_description":"Cylinder 2 Misfire Detected", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that cylinder #2 is not firing properly<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCheck Engine Light may flash<br> •\tEngine lacks power<br> •\tEngine may be hard to start<br> •\tEngine may stumble and hesitate frequently<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective or worn out spark plugs in cylinder 2<br> •\tLow fuel pressure<br> •\tVacuum leak<br> •\tDefective catalytic converter<br> •\tDefective fuel injector<br> •\tDefective coil<br> •\tDefective camshaft position sensor<br> •\tDefective crankshaft sensor<br> •\tProblem with distributor<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing a scan tool, pull codes and see if there are any other besides P0302. Address the others first<br> •\tInspect whether there are loose, open or short wires in ignition coils in cylinder 2<br> •\tInspect whether cylinder 2 spark plugs and their wires are in good condition<br> •\tCheck that fuel pressure is within the recommended range<br> •\tInspect fuel injectors to see whether they are in good condition"},
+ "P0303": { "short_description":"Cylinder 3 Misfire Detected", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that cylinder #3 is not firing properly<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCheck Engine Light may flash<br> •\tEngine lacks power<br> •\tEngine may be hard to start<br> •\tEngine may stumble and hesitate frequently<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective or worn out spark plugs in cylinder 3<br> •\tLow fuel pressure<br> •\tVacuum leak<br> •\tDefective catalytic converter<br> •\tDefective fuel injector<br> •\tDefective coil<br> •\tDefective camshaft position sensor<br> •\tDefective crankshaft sensor<br> •\tProblem with distributor<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing a scan tool, pull codes and see if there are any other besides P0303. Address the others first<br> •\tInspect whether there are loose, open or short wires in ignition coils in cylinder 3<br> •\tInspect whether cylinder 3 spark plugs and their wires are in good condition<br> •\tCheck that fuel pressure is within the recommended range<br> •\tInspect fuel injectors to see whether they are in good condition"},
+ "P0304": { "short_description":"Cylinder 4 Misfire Detected", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that cylinder #4 is not firing properly<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCheck Engine Light may flash<br> •\tEngine lacks power<br> •\tEngine may be hard to start<br> •\tEngine may stumble and hesitate frequently<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective or worn out spark plugs in cylinder 4<br> •\tLow fuel pressure<br> •\tVacuum leak<br> •\tDefective catalytic converter<br> •\tDefective fuel injector<br> •\tDefective coil<br> •\tDefective camshaft position sensor<br> •\tDefective crankshaft sensor<br> •\tProblem with distributor<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing a scan tool, pull codes and see if there are any other besides P0304. Address the others first<br> •\tInspect whether there are loose, open or short wires in ignition coils in cylinder 4<br> •\tInspect whether cylinder 4 spark plugs and their wires are in good condition<br> •\tCheck that fuel pressure is within the recommended range<br> •\tInspect fuel injectors to see whether they are in good condition"},
+ "P0305": { "short_description":"Cylinder 5 Misfire Detected", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that cylinder #5 is not firing properly<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCheck Engine Light may flash<br> •\tEngine lacks power<br> •\tEngine may be hard to start<br> •\tEngine may stumble and hesitate frequently<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective or worn out spark plugs in cylinder 5<br> •\tLow fuel pressure<br> •\tVacuum leak<br> •\tDefective catalytic converter<br> •\tDefective fuel injector<br> •\tDefective coil<br> •\tDefective camshaft position sensor<br> •\tDefective crankshaft sensor<br> •\tProblem with distributor<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing a scan tool, pull codes and see if there are any other besides P0305. Address the others first<br> •\tInspect whether there are loose, open or short wires in ignition coils in cylinder 5<br> •\tInspect whether cylinder 5 spark plugs and their wires are in good condition<br> •\tCheck that fuel pressure is within the recommended range<br> •\tInspect fuel injectors to see whether they are in good condition"},
+ "P0306": { "short_description":"Cylinder 6 Misfire Detected", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that cylinder #6 is not firing properly<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCheck Engine Light may flash<br> •\tEngine lacks power<br> •\tEngine may be hard to start<br> •\tEngine may stumble and hesitate frequently<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective or worn out spark plugs in cylinder 6<br> •\tLow fuel pressure<br> •\tVacuum leak<br> •\tDefective catalytic converter<br> •\tDefective fuel injector<br> •\tDefective coil<br> •\tDefective camshaft position sensor<br> •\tDefective crankshaft sensor<br> •\tProblem with distributor<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing a scan tool, pull codes and see if there are any other besides P0306. Address the others first<br> •\tInspect whether there are loose, open or short wires in ignition coils in cylinder 6<br> •\tInspect whether cylinder 6 spark plugs and their wires are in good condition<br> •\tCheck that fuel pressure is within the recommended range<br> •\tInspect fuel injectors to see whether they are in good condition"},
+ "P0316": { "short_description":"Misfire Detected On Startup (First 1000 Revolutions)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected a misfire less than 1,000 revolutions after startup<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine lacks power<br> •\tRough idle<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective or worn out spark plugs<br> •\tNo fuel<br> •\tLow fuel pressure<br> •\tVacuum leak<br> •\tDefective catalytic converter<br> •\tDefective fuel injector<br> •\tDefective coil<br> •\tDefective crankshaft sensor<br> •\tWiring fault in crankshaft position sensor<br> •\tProblem with PCM<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tPull all codes then address other misfire codes first<br> •\tCheck all wiring and connectors in crankshaft and camshaft position sensors<br> •\tReview freeze frame data to narrow down the problem further"},
+ "P0320": { "short_description":"Ignition/Distributor Engine Speed Input Circuit Malfunction", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThere’s an electrical circuit fault in either the crankshaft position (CKP) sensor or camshaft position (CMP) sensor<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine cranks but doesn’t start<br> •\tEngine lacks power<br> •\tEngine misfires, hesitates and stumbles<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tOpen or short in power supply circuit and/or control circuit between PCM and ignition/distributor/engine speed sensor<br> •\tDefective ignition/distributor/engine speed sensor<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck that all the connectors and wiring to ignition/distributor/engine speed sensors are in good condition<br> •\tRemove connectors and see if their terminals are burnt/corroded<br> •\tPull and reset P0320 code, drive the car for several minutes and see if the code returns. If it does then probably a sensor needs replacing"},
+ "P0325": { "short_description":"Knock Sensor 1 Circuit Malfunction (Bank 1 or Single Sensor)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that the engine’s knock sensor 1 in circuit bank 1 is not working properly<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tGenerally doesn’t come with symptoms but Check Engine Light may come on.<br> •\tEngine may also lose power<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tFirst sensor in circuit bank 1 may be faulty<br> •\tOpen or short in wiring to the sensor<br> •\tProblem with engine coolant<br> •\tEngine is excessively lean<br> •\tPCM has failed (least likely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to knock sensor 1 in circuit bank 1. Ensure there are no shorts or open wires<br> •\tView coolant temp data to check for issues<br> •\tIf there are none, clear the code and test drive the car. If it comes back the sensor is defective"},
+ "P0327": { "short_description":"Knock Sensor 1 Circuit low Input (Bank 1 or Single Sensor)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tKnock sensor on bank 1 is has low output voltage than normal; usually .5V or less<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tGenerally doesn’t come with symptoms but Check Engine Light may come on<br> •\tYou may also notice fluctuating RPM and loss of engine power<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tSensor in circuit bank 1 may be faulty<br> •\tOpen or short in wiring to the sensor<br> •\tPCM has failed (least likely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck the resistance of the knock sensor and ensure it matches manufacturer’s specifications<br> •\tVisually inspect all wiring to knock sensor 1 in circuit bank 1. Ensure there are no shorts or open wires<br> •\tIf the above don’t work replace knock sensor"},
+ "P0328": { "short_description":"Knock Sensor 1 Circuit high Input (Bank 1 or Single Sensor)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tKnock sensor on bank 1 is has high output voltage than normal; usually .5V or less<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tLoss of power<br> •\tIrregular RPM<br> •\tEngine pings when accelerating<br> •\tKnocking sound coming from engine compartment<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tKnock sensor 1 in circuit 1 may be faulty<br> •\tOpen or short in wiring to the sensor<br> •\tLow fuel pressure<br> •\tLoose knock sensor<br> •\tUsing incorrect type of fuel<br> •\tPCM has failed (least likely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tEnsure the correct fuel was used<br> •\tVisually inspect all wiring to knock sensor 1 in circuit bank 1. Ensure there are no shorts or open wires<br> •\tMeasure resistance of the sensor. If it doesn’t match manufacturer specs replace the sensor"},
+ "P0332": { "short_description":"Knock Sensor 2 Circuit Low Input (Bank 2)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tKnock sensor on bank 2 is has low output voltage than normal; usually .5V or less<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tGenerally doesn’t come with symptoms but Check Engine Light may come on<br> •\tYou may also notice fluctuating RPM and loss of engine power<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tSensor in circuit bank 2 may be faulty<br> •\tOpen or short in wiring to the sensor<br> •\tPCM has failed (least likely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck the resistance of the knock sensor and ensure it matches manufacturer’s specifications<br> •\tVisually inspect all wiring to knock sensor 2 in circuit bank 2. Ensure there are no shorts or open wires<br> •\tIf the above don’t work replace knock sensor"},
+ "P0335": { "short_description":"Crankshaft Position Sensor A Circuit Malfunction", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that crankshaft position (CKP) sensor is not producing pulses or the pulses are not normal. It uses these pulses to determine the position of the crankshaft<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine may fail to start<br> •\tVehicle may run rough<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective CKP sensor<br> •\tOpen or short in CKP sensor wiring<br> •\tTiming belt is broken<br> •\tPCM has failed (least likely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tStart by checking if there’s an RPM signal (using a scanner)<br> •\tIf it’s not there check all the wires and connectors to the sensor. Repair as necessary<br> •\tCheck the sensor’s resistance and compare with manufacturer’s recommendation. If they don’t match replace sensor"},
+ "P0336": { "short_description":"Crankshaft Position Sensor A Circuit Range/Performance", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has not received proper information from CKP sensor and therefore cannot adjust ignition timing and fuel injection accordingly<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine may fail to start<br> •\tIntermittent stalling<br> •\tIntermittent misfire<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective CKP sensor<br> •\tProblem with CKP sensor wiring<br> •\tReluctor ring is dislodged from its stationary location<br> •\tReluctor ring is broken<br> •\tPCM has failed (least likely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect CKP sensor for wiring issues<br> •\tInspect reluctor ring if it has broken/damaged teeth or dirt lodged in the teeth<br> •\tCheck sensor resistance and compare with manufacturer specs. If they don’t match replace sensor"},
+ "P0340": { "short_description":"Camshaft Position Sensor Circuit Malfunction", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThere’s a problem in the camshaft position sensor (CPS) circuit. As such, PCM can’t perform ignition spark and fuel injector timing properly<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine may fail to start<br> •\tVehicle may run rough<br> •\tRough idle<br> •\tMisfire <br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective CPS<br> •\tOpen or short in CPS wiring<br> •\tDefective CKP sensor<br> •\tPCM has failed (least likely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect wiring to CPS and ensure there are no open or broken wires<br> •\tCheck CPS voltage if it’s within the manufacturer’s specs. If it’s not replace sensor<br> •\tCheck CKP sensor as well to determine whether it’s the source of the problem"},
+ "P0341": { "short_description":"Camshaft Position Sensor Circuit Range/Performance", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe signal that the PCM is receiving from the camshaft position sensor (CPS ) is inconsistent with what it should be<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tGenerally doesn’t come with symptoms but Check Engine Light may come on<br> •\tPossible poor fuel economy<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective CPS<br> •\tOpen or short in CPS wiring<br> •\tDefective reluctor wheel<br> •\tInterference in CPS wiring (from spark plug)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect wiring to CPS and ensure there are no open or broken wires<br> •\tInspect reluctor wheel and check for damage or missing teeth<br> •\tReplace the CPS"},
+ "P0345": { "short_description":"Camshaft Position Sensor A Circuit Malfunction (Bank 2)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected a problem in the CPS circuit of bank 2. The problem could be anywhere in the circuit; sensor, wring or PC<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tLow engine power<br> •\tHard starting or no starting completely<br> •\tVehicle runs rough and/or misfires<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tOpen, grounded or short wiring in CPS circuit of bank 2<br> •\tDefective CPS<br> •\tDefective CKP sensor<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect wiring to CPS in bank 2 and ensure there are no open or broken wires<br> •\tCheck CPS voltage to ensure it’s within the range specified by manufacturer<br> •\tCheck circuit connectors for corrosion and burns<br> •\tCheck that CKP sensor is operating as it should<br> •\tReplace CPS if all the above check out"},
+ "P0351": { "short_description":"Ignition Coil A Primary/Secondary Circuit Malfunction", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThere’s a short in the driver circuit for the engine’s coil #1 (the coil for cylinder #1)<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine misfire<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tShort or open in the coil on plug (COP) driver circuit<br> •\tLoose or broken connection at coil<br> •\tDefective COP<br> •\tDefective PCM (least likely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tIf the engine is not currently misfiring then it’s an intermittent problem. Start by checking coil #1 wires visually as well as using wiggle test<br> •\tCheck for loose connections and broken connector locks<br> •\tIf all the above check out replace coil #1"},
+ "P0354": { "short_description":"Ignition Coil D Primary/Secondary Circuit Malfunction", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThere’s a short in the driver circuit for the engine’s coil #4 (the coil for cylinder #4)<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine misfire<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tShort or open in the coil on plug (COP) driver circuit<br> •\tLoose or broken connection at coil<br> •\tDefective COP<br> •\tDefective PCM (least likely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tIf the engine is not currently misfiring then it’s an intermittent problem. Start by checking coil #4 wires visually as well as using wiggle test<br> •\tCheck for loose connections and broken connector locks<br> •\tIf all the above check out replace coil #4"},
+ "P0400": { "short_description":"Exhaust Gas Recirculation Flow Malfunction", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThere’s either an insufficient or non-existent amount of exhaust gases entering the cylinders<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tIncreased NOx emissions<br> •\tIncreased combustion temperatures <br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tExhaust gas recirculation (EGR) passage is plugged<br> •\tEGR solenoid is faulty<br> •\tWiring or harness to EGR solenoid is faulty<br> •\tEGR valve is faulty<br> •\tEither vacuum lines are damaged or disconnected from EGR valve or EGR valve solenoid<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tWith a bidirectional scan tool, open and close EGR valve while the engine is running. If the engine stumbles then there’s a wiring problem<br> •\tIf the engine doesn’t stumble but it dies then the ports are plugged<br> •\tAfter the above visually inspect all hoses, vacuum lines, solenoid and solenoid harnesses for damage<br> •\tUsing the scanner, check solenoid voltage to ensure its within normal range<br> •\tIf all the above check out replace EGR valve"},
+ "P0401": { "short_description":"Exhaust Gas Recirculation Flow Insufficient Detected", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected an insufficient amount of EGR<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tMost notable symptom is engine pinging when the vehicle is in high speed or under load<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective differential pressure feedback EGR (DPFE) sensor<br> •\tDefective EGR valve<br> •\tEGR valve can’t open because of lack of vacuum<br> •\tBlockage in EGR tube<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck EGR valve and its tubing for deposits<br> •\tCheck DPFE sensor voltage to ensure its within specified range<br> •\tIf not replace the sensor. If it is replace the EGR valve"},
+ "P0402": { "short_description":"Exhaust Gas Recirculation Flow Excessive Detected", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected an excessive amount of EGR<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tMost notable symptom is engine surging off idle<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective differential pressure feedback EGR (DPFE) sensor<br> •\tDefective EGR valve<br> •\tEGR valve can’t open because of lack of vacuum<br> •\tBlockage in EGR tube<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck DPFE sensor voltage to ensure its within specified range<br> •\tIf not replace the sensor."},
+ "P0403": { "short_description":"Exhaust Gas Recirculation Circuit Malfunction", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that the EGR circuit has malfunctioned and isn’t sending the proper voltage at the proper time<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine may misfire under acceleration<br> •\tRough idle<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tShort or open in circuit leading to EGR solenoid<br> •\tPins connecting EGR solenoid are worn out or loose<br> •\tPresence of water in EGR solenoid harness<br> •\tEGR solenoid isn’t getting voltage supply<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tPull codes and freeze frame data to confirm P0403 code<br> •\tCheck all wiring and connections to EGR solenoid<br> •\tDisconnect and check EGR valve circuit for a short or open<br> •\tClear code and do test drive. If it comes back replace solenoid"},
+ "P0404": { "short_description":"Exhaust Gas Recirculation Circuit Range/Performance", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has determined that EGR valve is open when it should be closed or its closed when it should be open<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine may idle rough<br> •\tEngine may fail to idle<br> •\tVehicle may fail emissions<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tOpen or short in reference, ground or PCM controlled circuit<br> •\tDefective PCM (least likely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to EGR to ensure there are no shorts or opens<br> •\tUsing a bidirectional scanner, open and close EGR valve as you watch the EGR position. If it’s not close to the “desired” position then it’s likely a bad valve"},
+ "P0405": { "short_description":"Exhaust Gas Recirculation Sensor A Circuit Low", "long_description":"<strong>1. Meaning:<\/strong><br> •\tEGR valve pintle is not moving as it should either because of unusually low voltage or its position is lower than the PCM has commanded<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tOpen or short in reference or ground circuit<br> •\tDefective EGR valve<br> •\tDefective PCM (least likely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to EGR to ensure there are no shorts or opens<br> •\tUsing a bidirectional scanner, open and close EGR valve and watch how it responds. If its moving properly then it’s an intermittent problem"},
+ "P0406": { "short_description":"Exhaust Gas Recirculation Sensor A Circuit High", "long_description":"<strong>1. Meaning:<\/strong><br> •\tEGR sensor has had abnormally high voltage reading for too long<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tMay surge when you drive<br> •\tMay stall intermittently<br> •\tVehicle may fail emissions<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective EGR valve<br> •\tShort or open in EGR wiring circuit<br> •\tDebris build up in EGR valve and is holding it open<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tPull codes and freeze frame data<br> •\tVisually inspect all wiring to EGR to ensure there are no shorts or opens<br> •\tUsing a scan tool, view EGR position during startup and while running to ensure its correct<br> •\tClear code and do test drive"},
+ "P0411": { "short_description":"Secondary Air Injection System Incorrect Flow Detected", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe flow coming from the secondary air injection system is out of the range specified by PCM<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine may hesitate when you accelerate<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective air injection pump<br> •\tCheck valve is damaged or missing<br> •\tDamage or leak in exhaust component<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect air injection system and check for broken components, damaged hoses and excess carbon<br> •\tReset the code and do a test drive"},
+ "P0420": { "short_description":"Catalyst System Efficiency Below Threshold (Bank 1)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tCatalytic converter is not working as efficiently as it should and the vehicle is therefore emitting more harmful substances<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine lacks power<br> •\tReduced fuel economy<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective O2 sensor<br> •\tDefective engine coolant temp<br> •\tWiring to downstream O2 sensor is damaged or improperly done<br> •\tLeaking fuel injector<br> •\tOil is contaminated<br> •\tUsing leaded fuel where unleaded fuel was required<br> •\tDefective catalytic converter, exhaust pipe, muffler or exhaust manifold<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect exhaust system for damage and leaks.<br> •\tCheck voltage of downstream O2 sensor while the engine is running. If its not steady (jumpy between .1 and .9 V) then the catalytic converter needs replacing"},
+ "P0421": { "short_description":"Warm Up Catalyst Efficiency Below Threshold (Bank 1)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tDownstream O2 sensor on bank 1 has detected that the converter is not working according to specification<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine may lack power<br> •\tEngine may hesitate when accelerating <br> <br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective catalytic converter<br> •\tDefective O2 sensor, particularly downstream O2 sensor<br> •\tFouled up spark plug<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tMeasure voltage of O2 sensor (both) and ensure they match the specs. If not replace as necessary<br> •\tVisually inspect catalytic converters and check for red fumes (when car is running)<br> •\tSmell fumes and try to find traces of excessive fuel<br> •\tIf the latter two are present replace catalytic converter"},
+ "P0430": { "short_description":"Catalyst System Efficiency Below Threshold (Bank 2)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tCatalytic converter is not working as efficiently as it should. Its therefore releasing more harmful pollutants<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine may lack power<br> •\tReduced fuel economy<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective O2 sensor<br> •\tLeak in exhaust system<br> •\tDefective catalytic converter<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck exhaust system for any damages and leaks<br> •\tWith the car running, check the voltage of downstream O2 sensor. If it’s not steady then the catalytic converter is at fault"},
+ "P0440": { "short_description":"Evaporative Emission Control System Malfunction", "long_description":"<strong>1. Meaning:<\/strong><br> • A component in the EVAP system is not working properly<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light may come on<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tGas cap is not working or has not been installed properly<br> •\tCanister is plugged and defective<br> •\tPurge solenoid has failed<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect gas cap to see if its installed tightly<br> •\tCheck for disconnected or cracked EVAP hoses<br> •\tInspect charcoal canister and fuel tank for leaks and damages<br> •\tCheck that purge valve (solenoid) has no leaks"},
+ "P0441": { "short_description":"Evaporative Emission Control System Incorrect Purge flow", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that there’s no purge flow (i.e. purge control valve is still closed) despite commanding a purge<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light may come on<br> •\tRough or erratic idle<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tLoose or damaged EVAP hoses<br> •\tDefective purge valve<br> •\tGas cap is loose, missing or damaged<br> •\tCharcoal canister is damaged or defective<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect gas cap to see if its installed tightly<br> •\tCheck for disconnected or cracked EVAP hoses<br> •\tInspect charcoal canister and fuel tank for leaks and damages<br> •\tCheck that purge valve (solenoid) has no leaks"},
+ "P0442": { "short_description":"Evaporative Emission Control System leak Detected (small leak)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected a very small vapor leak somewhere in the EVAP control system <br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light may come on<br> •\tReduced fuel economy<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tLoose or damaged EVAP hoses<br> •\tDefective purge valve<br> •\tGas cap is loose, missing or damaged<br> •\tCharcoal canister is leaking<br> •\tFuel tank is leaking<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect gas cap to see if its installed tightly<br> •\tCheck for disconnected or cracked EVAP hoses<br> •\tInspect charcoal canister and fuel tank for leaks and damages<br> •\tCheck that purge valve (solenoid) has no leaks<br> •\tIf the above don’t narrow down the problem perform a smoke test"},
+ "P0443": { "short_description":"Evaporative Emission Control System Purge Control Valve circuit Malfunction", "long_description":"<strong>1. Meaning:<\/strong><br> •\tEither there’s an open in the purge control valve circuit or the circuit has abnormal voltage (too high or too low)<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light may come on<br> •\tCar may have lean condition<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tPurge solenoid has short or open<br> •\tShort or open somewhere in the wiring harness to purge valve<br> •\tDriver circuit in PCM has an open or short<br> •\tWater intrusion has caused connector to break or wear out<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing a scan tool, command purge valve to open. Listen for a clicking sound (one or many times)<br> •\tIf it doesn’t click examine solenoid and connectors for breakages and signs of extreme wearing out<br> •\tCheck all the circuits for wiring problems"},
+ "P0446": { "short_description":"Evaporative Emission Control System Vent Control Circuit Malfunction", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected an open or short in EVAP control circuit or a short to ground circuit<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective EVAP vent valve<br> •\tBlockage in vent valve<br> •\tVent valve control circuit has an open or short<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tExamine all wiring to vent valve<br> •\tIf the above checks out replace vent valve"},
+ "P0449": { "short_description":"Evaporative Emission Control System Vent Valve/Solenoid Circuit Malfunction", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected a problem in the circuit that controls the EVAP system vent<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective EVAP vent valve<br> •\tWiring issue in the EVAP vent valve<br> •\tCircuit issue in the EVAP vent valve<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck all wires leading to the vent valve for shorts and opens<br> •\tCheck fuses that power the vent solenoid (in case there are any)<br> •\tExamine if vent valve has cracks or openings<br> •\tUsing a bidirectional scanner, actuate the valve to see if its working"},
+ "P0452": { "short_description":"Evaporative Emission System Pressure Sensor/Switch Low", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that the fuel tank pressure is abnormally low<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective fuel tank pressure (FTP) sensor<br> •\tWiring problem in the circuits that lead to FTP sensor<br> •\tBroken or cracked vapor line (either to the tank or vacuum canister)<br> •\tLoose gas cap leading to loss of vacuum<br> •\tLeaking gasket in fuel pump module<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck vapor hoses for any breakages and opens<br> •\tSince diagnosing this problem is extremely hard (due to the location of the FTP sensor), its recommended that you get a professional to do the job"},
+ "P0455": { "short_description":"Evaporative Emission Control System Leak Detected (large leak)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected a large vapor leak somewhere in the EVAP control system <br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light may come on<br> •\tReduced fuel economy<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tLoose or damaged EVAP hoses<br> •\tGas cap is loose, missing or damaged<br> •\tNon-compatible gas cap<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect gas cap to see if its installed tightly<br> •\tCheck for disconnected or cracked EVAP hoses<br> •\tInspect charcoal canister and fuel tank for leaks and damages<br> •\tIf the above don’t work replace the gas cap"},
+ "P0456": { "short_description":"Evaporative Emissions System - Small leak detected", "long_description":"<strong>1. Meaning:<\/strong><br> •\tFTP sensor has indicated a small leak in EVAP system<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tFaulty gas cap<br> •\tLeak in fuel tank hoses or EVAP hoses<br> •\tLeak in vent valve or purge valve<br> •\tLeak in EVAP canister<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUse a bidirectional tool to activate vent solenoid as you monitor FTP sensor. It will tell you if the system is sealing properly or not<br> •\tIf it is then use a smoke test to determine the leak"},
+ "P0457": { "short_description":"Evaporative Emission Control System (EVAP) Leak Detected", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThere’s a vacuum leak and the EVAP system can’t draw fuel vapors into the system for efficient burning<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tSmell of fuel in exhaust<br> •\tReduced fuel economy<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tGas cap is either loose, cracked or missing<br> •\tLoose, disconnected or cracked hose in EVAP system<br> •\tCracked vacuum canister<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect gas cap and check if its loose or has debris that’s preventing it from fitting tightly<br> •\tInspect vacuum hoses for cracks and breaks<br> •\tInspect charcoal canister for leaks"},
+ "P0463": { "short_description":"Evaporative Emission Control System Pressure Sensor High Input", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe signal from the fuel level sensor is above 5 volts for a prolonged period of time<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tFuel light may come on and sound alarm<br> •\tFluctuating fuel level gauge<br> •\tFuel level gauge may erroneously read empty or full<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective fuel level sensor<br> •\tProblem with fuel level sensor circuit<br> •\tDefective instrument cluster<br> •\tDamaged fuel tank<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect fuel tank for damage or leaks<br> •\tInspect wiring harness<br> •\tDo voltage test on fuel level sensor circuit<br> •\tIf all those check out you may have to replace fuel tank"},
+ "P0500": { "short_description":"Vehicle Speed Sensor Malfunction", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe vehicle speed, as given by the vehicle speed sensor (VSS) is not within the expected range<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tSpeedometer may fail to work<br> •\tLoss of ABS (anti-lock brakes)<br> •\tABS light may come on<br> •\tTransmission may not work properly<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective VSS<br> •\tWiring problem in VSS circuit<br> •\tPCM is not configured properly for the tire size of the vehicle<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to VSS and check for open, short, broken and chaffed wires<br> •\tCheck the voltage of the speed sensor"},
+ "P0506": { "short_description":"Idle Control System RPM lower Than Expected", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that the engine idle speed is lower than the pre-programmed RPM<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tRough idle due to lower idle speed<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tVacuum leak<br> •\tAir is restricted in the exhaust or intake air path<br> •\tDefective positive crankcase ventilation valve<br> •\tProblem with throttle body<br> •\tFailed PCM<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck for vacuum leaks, damages and restriction<br> •\tNote that this code is informational more than anything, so look out for other codes that it comes with and address them first"},
+ "P0507": { "short_description":"Idle Control System RPM higher Than Expected", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that the engine idle speed is higher than the pre-programmed RPM (typically over 200 RPM)<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tVacuum leak<br> •\tDefective positive crankcase ventilation valve<br> •\tLeaking air intake<br> •\tProblem with throttle body<br> •\tDefective EVAP system<br> •\tDefective idle air controller (IAC) or a problem with IAC circuit<br> •\tFailed PCM<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck for vacuum leaks, damages and restriction<br> •\tNote that this code is informational more than anything, so look out for other codes that it comes with and address those first"},
+ "P0521": { "short_description":"Engine Oil Pressure Sensor/Switch Range/Performance", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has seen an unexpected value in engine oil pressure sensor. The value could be fixed when it should fluctuate or simply out of the normal range<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tOil pressure gauge may read too low or too high<br> •\tOil pressure light may come on<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tOil level in the engine is too low<br> •\tOil pressure is too low<br> •\tDirty oil<br> •\tFaulty wiring to oil pressure sensor<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck that oil level is not too low<br> •\tCheck that the right oil was used<br> •\tVisually inspect all wiring to oil pressure sensor and check for open, short or broken wires<br> •\tIf you can, take the oil pressure reading and compare with the reading shown by the vehicle’s PCM. That should tell you if the problem is with oil pressure"},
+ "P0522": { "short_description":"Engine Oil Pressure Sensor/Switch Low Voltage", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected a very low value in engine oil pressure sensor<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tOil pressure light comes on<br> •\tOil pressure gauge reads zero or low value<br> •\tEngine may fail to start<br> •\tEngine may stall when you’re driving<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tWiring problem in oil pressure sensor circuit<br> •\tDefective oil pressure sensor<br> •\tLow oil level or blockage in oil passage<br> •\tUsing wrong type of oil<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck oil level and condition<br> •\tVisually inspect all wiring to oil pressure sensor<br> •\tCheck the sensor’s voltage to ensure it meets manufacturer’s specs<br> •\tIf you can, take the oil pressure reading and compare with the reading shown by the vehicle’s PCM. That should tell you if the problem is with oil pressure"},
+ "P0562": { "short_description":"System Voltage Low", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that the ignition feed circuit has very low voltage. Meaning the charging system might not be working<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tRed battery light on<br> •\tReduced fuel economy<br> •\tTransmission may fail<br> •\tEngine may fail to start<br> •\tEngine may start then stall and die<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective alternator<br> •\tHigh resistance either in alternator-battery circuit, alternator-PCM circuit or both<br> •\tDefective PCM<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck whether battery voltage is sufficient<br> •\tEnsure battery is properly connected then check alternator belt<br> •\tUsing a digital volt ohm meter (DVOM), check whether the charging system is working<br> •\tReset the code then do a test drive. If the code returns check PCM voltage"},
+ "P0606": { "short_description":"ECM/PCM Processor Fault", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected an integrity fault in its own system<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tFailed PCM<br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tRe-flash PCM with updated software. If that doesn’t work replace the PCM"},
+ "P0700": { "short_description":"Transmission Control System Malfunction", "long_description":"<strong>1. Meaning:<\/strong><br> •\tIf the transmission control module (TCM) detects a fault in the transmission system and sets a code, this code is also stored in the PCM<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tTransmission may exhibit problems<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tAny transmission-related problem can trigger this code<br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tThis is only an informational code, so pull all transmission codes, address them and do a test drive to fix this code"},
+ "P0705": { "short_description":"Transmission Range Sensor Circuit Malfunction (PRNDL Input)", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected a malfunction in the transmission range sensor (TRS)<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tActuating starter may be impossible<br> •\tBack up lights may fail<br> •\tEngine may only start at neutral<br> •\tIrregular shift RPMs<br> •\tDelayed transmission engagement<br> •\tReduced fuel economy<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective TRS<br> •\tLoose TRS<br> •\tShorted wire in TRS circuit<br> •\tLoose or corroded connector at the external TRS. Pins may also be bent<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tMore often than not this code means replacing the TRS"},
+ "P0715": { "short_description":"Input/Turbine Speed Sensor Circuit Malfunction", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe actual transmission input speed does not match the desired input speed <br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tTransmission shifts erratically<br> •\tTransmission may fail to shift<br> •\tFailure in speedometer<br> •\tLower fuel economy<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective input speed sensor<br> •\tDefective output speed sensor<br> •\tA wiring problem in input/output speed sensor circuit<br> •\tLoose or burnt connector in transmission circuit<br> •\tDefective or improperly programmed PCM<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring and connectors for loose, burnt, open or broken connections<br> •\tUsing a scanner, pull all codes and freeze frame data to see which sensor is malfunctioning (input/output)<br> •\tReplace sensor if necessary"},
+ "P0720": { "short_description":"Output Speed Sensor Circuit Malfunction", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has determined that there’s a malfunction in the Output Shaft Speed Sensor (OSS) of the transmission system<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tDelayed shifts<br> •\tFailed speedometer<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective OSS<br> •\tDefective transmission fluid temperature sensor<br> •\tWiring problem in the OSS circuit<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck that all wiring to OSS is properly done and there are no open, broken or shorted wires<br> •\tMeasure OSS voltage and compare with manufacturer’s specs. If they don’t match replace OSS<br> •\tMeasure transmission fluid temperature sensor voltage and compare with manufacturer’s specs. If they don’t match replace the sensor"},
+ "P0741": { "short_description":"Torque Converter Clutch Circuit Performance or Stuck Off", "long_description":"<strong>1. Meaning:<\/strong><br> •\tTCM has detected a problem within the circuit that controls the torque converter clutch (TCC) solenoid<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tSlightly reduced fuel economy<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tShorted wire in transmission’s ground circuit<br> •\tInternal short in TCC solenoid<br> •\tDefective TCM<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck that all wiring in the transmission circuit is properly done and there are no open, broken or shorted wires<br> •\tCheck the resistance of the TCC solenoid and compare with manufacturer’s specs<br> •\tMonitor TCM using an advanced scan tool and see if its performance parameters are within normal range"},
+ "P1101": { "short_description":"MAF Sensor Out Of Self-Test Range./KOER Not Able To Complete KOER Aborted", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe PCM has detected an irregular (or abnormal) voltage from the Mass Air Flow (MAF) sensor<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine performs erratically upon startup<br> •\tReduced vehicle power<br> •\tRough idling<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective MAF sensor<br> •\tWiring problem in MAF sensor circuit<br> •\tFaulty connector(s) in MAF system<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck that all wiring in the MAF sensor circuit is properly done and there are no open, broken or shorted wires<br> •\tCheck air filters for dirt and debris that might be obstructing air flow<br> •\tPerform smoke test in vacuum system to check for leaks before and after MAF sensor<br> •\tCheck the voltage in MAF sensor and compare with manufacturer’s specs. If they don’t match replace the sensor<br> •\tCheck continuity between PCM and MAF sensor"},
+ "P1133": { "short_description":"HO2S Insufficient Switching Sensor 1", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has determined that the front heated O2 sensor (HO2S) is not functioning properly <br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tHard starting<br> •\tReduced fuel economy<br> •\tRough or erratic idling<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective O2 sensor<br> •\tDamaged, broken, shorted or corroded wires/connectors in front HO2S<br> •\tEGR valve is stuck open<br> •\tMisfires on at least one cylinder<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck that all O2 sensor wires and connectors are not damaged, open, broken, shorted or burnt<br> •\tUsing a scanner, determine whether oxygen sensors are switching enough times<br> •\tIf not, measure their voltage to determine which sensor is faulty. Replace as necessary"},
+ "P1135": { "short_description":"Air/Fuel Ratio Sensor Heater Circuit Malfunction Bank 1 Sensor 1", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThis Toyota code means the PCM has detected an oxygen sensor heater circuit malfunction<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tLonger time needed to achieve closed loop<br> •\tDecreased fuel economy<br> •\tEngine may go into fixed fuel mix<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tH02S sensor in bank 1, circuit 1 is not sending the correct signal to ECM<br> •\tDamaged or failed element in heater circuit<br> •\tOpen in O2 sensor heater’s circuit<br> •\tOpen/short in O2 sensor heater’s battery<br> •\tDefective ECM (this is the least likely cause)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect wiring and power to the O2 sensor and ensure there’s no damage/open/short<br> •\tUse code reader to pull engine codes<br> •\tCheck voltage of O2 sensor and ensure it matches manufacturer’s specs<br> •\tReplace O2 sensor if necessary"},
+ "P1399": { "short_description":"Random Cylinder Misfire Detected", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThis Honda code means the PCM has detected that there’s an engine cylinder that’s not firing properly. It could be one or more cylinders. PCM hasn’t specified the exact cylinder<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCheck Engine Light may flash<br> •\tEngine lacks power<br> •\tEngine may be hard to start<br> •\tEngine may stumble and hesitate frequently<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective or worn out spark plugs<br> •\tLow fuel pressure<br> •\tVacuum leak<br> •\tDefective catalytic converter<br> •\tDefective fuel injector<br> •\tDefective coil<br> •\tDefective camshaft position sensor<br> •\tDefective crankshaft sensor<br> •\tProblem with distributor<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing a scan tool, pull codes and see if there are any other besides P0300. Address the others first<br> •\tInspect whether there are loose, open or short wires in ignition coils<br> •\tInspect whether spark plugs and their wires are in good condition<br> •\tCheck that fuel pressure is within the recommended range<br> •\tInspect fuel injectors to see whether they are in good condition"},
+ "P1443": { "short_description":"Evaporative Emission Control System Control Valve", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThis is a predominantly Ford, Nissan and Range Rover code that means the same thing as P0443. Please refer to that code (#79 on this list)"},
+ "P1450": { "short_description":"Unable To Bleed Up Fuel Tank Vacuum", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThis is a Ford, Jaguar, Lincoln, Mercedes, Mercury and Oldsmobile code that means that the Evaporative Emission Control System has failed to bleed up the fuel tank<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine may fail to start<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective vent valve<br> •\tBlockage in vacuum lines<br> •\tDamaged charcoal canister<br> •\tOverfilling fuel tank<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck that all vent valve wires and connectors are not damaged, open, broken, shorted or burnt<br> •\tRemove any blockage in vacuum lines. Refer to your application manual for this procedure<br> •\tVisually inspect charcoal canister for any damages<br> •\tCheck that the fuel amount is within the recommended range"},
+ "P1456": { "short_description":"Fuel Tank Temperature Sensor Circuit Malfunction", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThis Honda code means the same thing as P0442. Please refer to that code (#78 on this list)"},
+ "P1457": { "short_description":"This is a manufacturer-specific code that means different things in different cars<br> •\tIn Honda it means Evaporative emission (EVAP) canister purge system (canister system) - leak detected<br> •\tIn Acura it means Evaporative emission (EVAP) canister purge system (canister system) - leak detected<br> •\tIn Audi it means Exhaust gas recirculation temperature (EGRT) sensor 2/Bank 2 - open circuit/short to positive<br> •\tIn Isuzu it means Evaporative emission (EVAP) canister purge system (canister system) - leak detected<br> •\tIn Kia it means Evaporative emission (EVAP) canister purge valve (low)<br> •\tIn Volkswagen it means Exhaust gas recirculation temperature (EGRT) open circuit/short to positive"},
+ "P1491": { "short_description":"This is a manufacturer-specific code that means different things in different cars<br> •\tIn Acura it means Exhaust gas recirculation (EGR) system - valve lift insufficient<br> •\tIn Chrysler it means Radiator Fan Relay Circuit Conditions<br> •\tIn Honda it means Exhaust gas recirculation (EGR) system - valve lift insufficient<br> •\tIn Infiniti it means Evaporative emission (EVAP) canister purge control system – malfunction<br> •\tIn Isuzu it means Exhaust gas recirculation (EGR) system - valve lift insufficient<br> •\tIn Mercedes it means AC system - pressure too high<br> •\tIn Nissan it means Evaporative emission (EVAP) canister purge system - bypass vacuum valve malfunction"},
+ "P1494": { "short_description":"EVAP Leak Detection Pump Pressure Switch Condition", "long_description":"<strong>1. Meaning:<\/strong><br> •\tA Chrysler code, this code means the same as P0442, i.e. PCM has detected a very small vapor leak somewhere in the EVAP control system <br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light may come on<br> •\tReduced fuel economy<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tLoose or damaged EVAP hoses<br> •\tDefective purge valve<br> •\tGas cap is loose, missing or damaged<br> •\tCharcoal canister is leaking<br> •\tFuel tank is leaking<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tInspect gas cap to see if its installed tightly<br> •\tCheck for disconnected or cracked EVAP hoses<br> •\tInspect charcoal canister and fuel tank for leaks and damages<br> •\tCheck that purge valve (solenoid) has no leaks<br> •\tIf the above don’t narrow down the problem perform a smoke test"},
+ "P1516": { "short_description":"Throttle actuator control module / throttle actuator position performance", "long_description":"<strong>1. Meaning:<\/strong><br> •\tA GM code, this DTC means that the voltage being sent by the throttle actuator position sensor (TAPS) doesn’t match the voltage being received by the actual throttle position sensor<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tVehicle may fail to accelerate<br> •\tIntermittent surging<br> •\tReduced fuel economy<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective pedal position sensor<br> •\tOpen or short in circuit supplying power to pedal position sensor<br> •\tDefective PCM<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to pedal position sensor and ensure there are no open, broken or shorted wires<br> •\tRun a resistance test on sensor. If it fails replace it<br> •\tDo a test drive, if the code returns run a test on PCM"},
+ "P1684": { "short_description":"Battery Power to Module Disconnected", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThis code appears on Dodge and Chrysler vehicles. It means the transmission control module (TCM) is disconnected from the battery’s power B+ or ground<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tRecently disconnected battery<br> •\tTCM was either replaced or disconnected<br> •\tShort in TCM harness<br> •\tDefective TCM<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck all wiring to TCM and ensure there are no shorted, broken or open wires<br> •\tUse a scan tool to reset the code<br> •\tDo a voltage test on TCM to determine if its defective"},
+ "P2096": { "short_description":"Post Catalyst Fuel Trim System Too Lean Bank 1", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThere’s a lean condition (i.e. too much air and too little fuel) in cylinder #1 on a V6 or V8 engine.<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tReduced fuel economy<br> •\tErratic acceleration<br> •\tEngine misfires<br> •\tRough idle<br> •\tMay produce spark knock<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tLarge vacuum leak<br> •\tLarge air leak somewhere around the 1st cylinder<br> •\tLow fuel pressure<br> •\tMisfiring plugs that cause the engine to run rough<br> •\tDefective O2 sensor<br> •\tDefective exhaust system<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing a scan tool, pull all the codes and address all the others first<br> •\tVisually inspect exhaust system for any damaged or worn out components<br> •\tCheck for vacuum leaks in the engine, particularly between the intake manifold and MAF sensor<br> •\tCheck that plug wires are not burning<br> •\tIf the vehicle has very little acceleration power, check for clogged converter<br> •\tIf none of the above work replace MAF sensor then downstream O2 sensor (in that order)"},
+ "P2097": { "short_description":"Post Catalyst Fuel Trim System Too Rich Bank 1", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThere’s a rich condition (i.e. too little oxygen content) in cylinder #1<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine lacks power<br> •\tReduced fuel economy<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective catalytic converter<br> •\tDefective O2 sensor(s)<br> •\tDefective MAF sensor or manifold air pressure sensor<br> •\tLeak in exhaust system<br> •\tWiring problem e.g. burnt, open, broken or disconnected wire<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect wiring harnesses for broken, open, burnt or disconnected wires<br> •\tCheck the exhaust for leaks and damages<br> •\tPull all codes and freeze frame data. Reset the codes and do a test drive<br> •\tIf code P2097 returns check resistance of MAF sensor and O2 sensors. Replace as necessary"},
+ "P2101": { "short_description":"Throttle Actuator \"A\" Control Motor Circuit Range/Performance", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThis code is set when there’s an electrical or mechanical problem in the throttle actuator A (TA-A)<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine fails to accelerate<br> •\tFixed idle speed<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective TA-A<br> •\tOpen or short in TA-A circuit<br> •\tDefective PCM (least likely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tLocate TA-A and check all its wiring harnesses. Ensure there are no open, broken, disconnected, shorted or burnt wires and connectors<br> •\tReset the code and do a test drive. If it returns test the actuator"},
+ "P2138": { "short_description":"Throttle/Pedal Pos Sensor/Switch D / E Voltage Correlation", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected a fault in either the D or E (or both) circuit of the throttle position sensor<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tVehicle may fail to start<br> •\tVehicle may stall<br> •\tPoor acceleration<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective throttle position sensor<br> •\tDefective throttle body motor<br> •\tWiring or connector problem in throttle body motor circuit<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect throttle body motor circuit for loose, broken, burnt or open wires and connectors<br> •\tTest resistance of throttle motor and throttle position sensor. Replace as necessary"},
+ "P2181": { "short_description":"Cooling System Performance", "long_description":"<strong>1. Meaning:<\/strong><br> •\tA vague OBD2 code, the P2181 suggests that there’s somewhere in the engine where the temperature is out of range (either too hot or too cold)<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tTemperature gauge indicates too high or too low temp<br> •\tIf the temp is too cold the engine will have a rich condition<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective engine coolant temperature (ECT) sensor<br> •\tWiring or connector problem in ECT circuit<br> •\tThermostat is stuck open or closed<br> •\tPresence of air in cooling system<br> •\tLow engine coolant level<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tIf the engine is running too cold replace thermostat<br> •\tCheck to ensure there are no open, broken, disconnected, shorted or burnt wires and connectors in ECT circuit<br> •\tCheck whether fan is working. If it’s wobbling or has a leak tighten or replace the fan. Remember to check its fuse as well<br> •\tTest the resistance of ECT sensor. If it’s off the recommended reading replace the sensor"},
+ "P2195": { "short_description":"O2 Sensor Signal Stuck Lean Bank 1 Sensor 1", "long_description":"<strong>1. Meaning:<\/strong><br> •\tO2 sensor 1 on cylinder 1 (bank 1) is reading an air/fuel ratio that has strayed so far from the normal 14.7:1 that the PCM is no longer able to correct the ratio<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective O2 sensor or A/F (air/fuel) ratio sensor<br> •\tOpen or short in O2 sensor circuit<br> •\tDefective fuel pressure system leading to too high or too low fuel pressure<br> •\tFuel leak<br> •\tLeak in engine vacuum or intake air<br> •\tLeak in PCV system<br> •\tLeak in fuel system (tank or hoses)<br> •\tDefective MAF sensor<br> •\tDefective PCM<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring harnesses to O2 sensor circuits, especially sensor 1<br> •\tCheck vacuum, fuel tank and PCV systems for leaks<br> •\tUsing a scan tool, monitor short and long term fuel trim values and compare with manufacturer specs<br> •\tAlso take readings for MAF and O2 sensor 1 and compare with specs<br> •\tCheck the resistance of those sensors to ensure they work properly. Replace as necessary"},
+ "P2196": { "short_description":"O2 Sensor Signal Stuck Rich Bank 1 Sensor 1", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThis code is similar to P2195; i.e. O2 sensor 1 on cylinder 1 (bank 1) is reading an air/fuel ratio that has strayed so far from the normal 14.7:1 that the PCM is no longer able to correct the ratio<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective O2 sensor or A/F (air/fuel) ratio sensor<br> •\tOpen or short in O2 sensor circuit<br> •\tDefective fuel pressure system leading to too high or too low fuel pressure<br> •\tFuel leak<br> •\tLeak in engine vacuum or intake air<br> •\tLeak in PCV system<br> •\tLeak in fuel system (tank or hoses)<br> •\tDefective MAF sensor<br> •\tDefective PCM<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring harnesses to O2 sensor circuits, especially sensor 1<br> •\tCheck vacuum, fuel tank and PCV systems for leaks<br> •\tUsing a scan tool, monitor short and long term fuel trim values and compare with manufacturer specs<br> •\tAlso take readings for MAF and O2 sensor 1 and compare with specs<br> •\tCheck the resistance of those sensors to ensure they work properly. Replace as necessary"},
+ "P2270": { "short_description":"O2 Sensor Signal Biased/Stuck Lean Bank 1 Sensor 2", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe signal being put out by sensor 2 on bank 1 is stuck lean (the sensor has detected too much air)<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine may run rough<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tProblem with fuel injector<br> •\tExhaust leak near sensor 2 of bank 1<br> •\tDefective sensor 2 of bank 1<br> •\tIncorrect fuel pressure<br> •\tLeak in engine coolant<br> •\tDefective purge solenoid valve<br> •\tDefective PCM (least likely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring harnesses to O2 sensor circuits, especially sensor 1 of bank 1<br> •\tCheck for exhaust leaks<br> •\tUsing a scan tool, monitor sensor readings and compare with manufacturer specs<br> •\tProceed to test resistance of sensors and replace as necessary"},
+ "P2646": { "short_description":"“A” Rocker Arm Actuator System Performance/Stuck Off Bank 1", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe “A” rocker arm actuator control circuit is either stuck in the off position or not working as it should<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tEngine may lack power<br> •\tEngine valve train may be excessively noisy<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tLow oil pressure<br> •\tClogged oil passages<br> •\tRocker arm actuator has built-up slug<br> •\tOil used is too thick<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVerify that the oil used is of the right viscosity<br> •\tCheck A” rocker arm actuator hoses and passages for blockage<br> •\tClear code and do test drive. If it returns perform manufacturer pinpoint test for A” rocker arm actuator"},
+ "P2A00": { "short_description":"O2 Sensor Circuit Range/Performance Bank 1 Sensor 1", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe upstream O2 sensor circuit has failed to cycle as expected by the PCM over a period of time predetermined by the PCM<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tReduced fuel economy<br> •\tPoor engine performance<br> •\tEngine misfires<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective O2 sensor 1 in bank 1<br> •\tBurnt, open, broken, shorted or disconnected wire/connector in the sensor circuit<br> •\tVacuum leak<br> •\tDefective MAF sensor<br> •\tLeak in engine exhaust<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring harnesses to O2 sensor circuits, especially sensor 1 of bank 1<br> •\tCheck for leaks in engine and vacuum system<br> •\tAddress other codes, reset all codes and do test drive. If the code returns check resistance of MAF sensor and O2 sensor. Replace as necessary"},
+ "U0001": { "short_description":"Controller Area Network (CAN) Data Bus: High Speed Bus/Communication Control Module", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe high speed bus is a communication line between the totally integrated power module (TIPM) and other vehicle modules. When this code sets it means there’s a module (especially ABS module) that has failed to communicate with TIPM<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tVehicle may fail to start on one or few attempts<br> •\tKey alarm may activate intermittently<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tOpen in either positive or negative CAN bus circuit<br> •\tOpen in power or ground supply circuit to the module that set the code<br> •\tShort to ground on CAN bus circuit<br> •\tLow voltage<br> •\tProblem with TIPM<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing a bidirectional scan tool, operate each module independently to find out which one is not working<br> •\tOnce you’ve pinpointed the module check that its circuits have no loose, open, broken or disconnected wires and connectors<br> •\tDo the same for TIPM<br> •\tUse an ohmmeter to check continuity on wire terminals in the module and TIPM<br> •\tIf all the above don’t work replace the TIPM"},
+ "U0073": { "short_description":"Control Module Communication Bus “A” Off", "long_description":"<strong>1. Meaning:<\/strong><br> •\tProblem with CAN bus making it hard for modules to exchange information and to communicate with scan tool<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tInstrument cluster indicator “light” on<br> •\tReduced fuel economy<br> •\tEngine lacks power<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tOpen in the “A” CAN bus + or – circuit <br> •\tShort to power or ground in “A” CAN bus circuit<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tPull all communication codes and address them first then this one last<br> •\tVisually inspect all bus communication connections (connectors and wires) for breaks, shorts, opens, chafing, burns and melted spots<br> •\tReset all codes and do a test drive. If this code returns disconnect one control module at a time and see if the scanner can finally communicate with PCM"},
+ "U0101": { "short_description":"Lost Communication With Transmission Control Module", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThere’s no communication between the transmission control module (TCM) and other control modules<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tCar doesn’t shift gears<br> •\tStays in one gear, usually 2nd or 3rd gear<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tOpen in CAN bus + or – circuit<br> •\tShort to power or ground in either + or – CAN bus circuit<br> •\tDefective TCM (least likely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing a bidirectional scan tool, control TCM and see if it responds. If it doesn’t probe it further<br> •\tIf it responds then check all the wires, connectors and fuses that make the circuit<br> •\tWith key on engine off, check the voltage of CAN C+ and C-. If the readings don’t match manufacturer’s specs then the communication circuits are bad"},
+ "U0107": { "short_description":"Lost Communication With Throttle Actuator Control Module", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThere’s no communication between the throttle actuator control (TAC) module and other control modules<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tElectronic throttle control light comes on or flashes<br> •\tNo throttle response<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tOpen in CAN bus + or – circuit<br> •\tShort to power or ground in either + or – CAN bus circuit<br> •\tDefective TAC module (least likely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing a bidirectional scan tool, control TAC module and see if it responds. If it doesn’t probe it further<br> •\tIf it responds then check all the wires, connectors and fuses that make the circuit<br> •\tWith key on engine off, check the voltage of CAN C+ and C-. If the readings don’t match manufacturer’s specs then the communication circuits are bad"},
+ "U0121": { "short_description":"Lost Communication With Anti-Lock Brake System Control Module", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThere’s no communication between the anti-lock brake system (ABS) control module and other control modules<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tABS warning light comes on<br> •\tTRAC or ESP/ESC (or both) warning light comes on<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tOpen in CAN bus + or – circuit<br> •\tShort to power or ground in either + or – CAN bus circuit<br> •\tDefective ABS control module (least likely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing a bidirectional scan tool, control ABS control module and see if it responds. If it doesn’t probe it further<br> •\tIf it responds then check all the wires, connectors and fuses that make the circuit<br> •\tWith key on engine off, check the voltage of CAN C+ and C-. If the readings don’t match manufacturer’s specs then the communication circuits are bad"},
+ "U0155": { "short_description":"Lost Communication With Instrument Panel Control Module", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThere’s no communication between the instrument panel control (IPC) module and other control modules<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tAll indicator lights in instrument panel/cluster come on, or<br> •\tNo indicator lights in instrument panel/cluster come on<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> <br> •\tOpen in CAN bus + or – circuit<br> •\tShort to power or ground in either + or – CAN bus circuit<br> •\tDefective IPC module (least likely)<br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing a bidirectional scan tool, control IPC module and see if it responds. If it doesn’t probe it further<br> •\tIf it responds then check all the wires, connectors and fuses that make the circuit<br> •\tWith key on engine off, check the voltage of CAN C+ and C-. If the readings don’t match manufacturer’s specs then the communication circuits are bad"},
+ "U1120": { "short_description":"Lost Wheel Distance", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPrimarily a Chrysler code, the U1120 means the ABS module is not able to communicate with speed sensors<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tABS warning light may come on<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tOpen in CAN bus + or – circuit<br> •\tShort to power or ground in either + or – CAN bus circuit<br> •\tDefective ABS control module (least likely)<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing a bidirectional scan tool, control ABS control module and see if it responds. If it doesn’t probe it further<br> •\tIf it responds then check all the wires, connectors and fuses that make the circuit<br> •\tWith key on engine off, check the voltage of CAN C+ and C-. If the readings don’t match manufacturer’s specs then the communication circuits are bad"},
+ "U1900": { "short_description":"CAN Communication Bus Fault", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPrimarily a Ford code, the U1900 means the same as U0001 <br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tVehicle may fail to start on one or few attempts<br> •\tKey alarm may activate intermittently<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tOpen in either positive or negative CAN bus circuit<br> •\tOpen in power or ground supply circuit to the module that set the code<br> •\tShort to ground on CAN bus circuit<br> •\tLow voltage<br> •\tProblem with TIPM<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tUsing a bidirectional scan tool, operate each module independently to find out which one is not working<br> •\tOnce you’ve pinpointed the module check that its circuits have no loose, open, broken or disconnected wires and connectors<br> •\tDo the same for TIPM<br> •\tUse an ohmmeter to check continuity on wire terminals in the module and TIPM<br> •\tIf all the above don’t work replace the TIPM"},
+ "B0092": { "short_description":"Left Side Restraints Sensor 2", "long_description":"<strong>1. Meaning:<\/strong><br> •\tA Ford code, the B0092 means that the left side airbag sensor has detected a problem with the airbag system<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tAirbag warning lights may come on<br> •\tAbnormal illumination of airbag warning lights<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tOpen, short or broken wire in left side restraint sensor 2 harness<br> •\tDefective left side restraint sensor 2<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to left side restraint sensor 2 for loose, open or short connections<br> •\tCheck resistance of left side restraint sensor 2 and compare with specs. If they don’t match replace sensor"},
+ "B1015": { "short_description":"This Is A Manufacturer-Specific Code That Means Different Things In Different Cars<br> •\tIn GM It Means Passenger Deploy. Loop Resistance High<br> •\tIn Chrysler It Means Rear Defrost Switch Request Input Circuit/Performance<br> •\tIn Ford It Means Electronic Instrument Cluster Unconfigured<br> •\tIn Mazda It Means Electronic Instrument Cluster Unconfigured<br> •\tIn Mitsubishi It Means Heater Water Temperature Sensor Performance"},
+ "B1047": { "short_description":"Driver-Side Side Air Bag Module And Other Air Bag Module Circuits Short", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThere’s a short in the side airbag on the driver’s side<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tAirbag warning lights may come on<br> •\tAbnormal illumination of airbag warning lights<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tOpen or short in the circuit leading to driver-side side air bag module<br> •\tDefective driver-side side air bag module<br> •\tDefective SRS (airbag) module<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to the driver-side side air bag module for loose, open or short connections<br> •\tPerform resistance test on driver-side side air bag module<br> •\tPerform resistance test on airbag control module"},
+ "B1057": { "short_description":"Driver Airbag Module Short", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe airbag diagnosis sensor on the driver’s side has detected a short in the circuit<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tAirbag warning light comes on<br> <br> <strong>4. Possible Causes:<\/strong><br> •\tShort in driver airbag’s harness<br> •\tProblem with spiral cable<br> •\tDefective driver airbag<br> •\tProblem with electrical connection in driver airbag<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect the wiring harness to driver’s airbag<br> •\tPerform resistance test on driver’s airbag module<br> •\tCheck resistance of spiral cable and airbag diagnosis sensor and replace as necessary"},
+ "B1318": { "short_description":"Battery Voltage Low", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThis is a Ford and Jaguar code that is set when the PCM detects that battery voltage has fallen below a predetermined level <br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tRed battery light on<br> •\tReduced fuel economy<br> •\tTransmission may fail<br> •\tEngine may fail to start<br> •\tEngine may start then stall and die<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective alternator<br> •\tUsing an incorrect battery<br> •\tUnmaintained battery<br> •\tHigh resistance either in alternator-battery circuit, alternator-PCM circuit or both<br> •\tDefective PCM<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck whether battery voltage is sufficient<br> •\tEnsure battery is properly connected then check alternator belt<br> •\tUsing a digital volt ohm meter (DVOM), check whether the charging system is working<br> •\tReset the code then do a test drive. If the code returns check PCM voltage"},
+ "B1342": { "short_description":"ECU Is Defective", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe Electronic Control Unit (ECU) has failed<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tOther warning lights may come on depending on which module is affected<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective ECU<br> •\tDamaged controller(s) due to abnormal system voltages<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tDiagnose and address all other codes first before replacing ECU<br> •\tCheck whether system voltage is within manufacturer’s recommendation<br> •\tInspect wiring to ECU and ensure that there are no open, shorted or broken wires<br> •\tReset all codes and do test drive. If the code returns you may have to replace ECU"},
+ "B1650": { "short_description":"Occupant Classification System Fault", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM or airbag control module has detected a malfunction in the occupant classification system<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tAirbag warning light comes on<br> •\tCheck Engine Light may come on<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tProblem in the occupant classification system<br> •\tWiring problem in the right front seat<br> •\tProblem with airbag sensor assembly center<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring in the occupant classification system for loose, open or short connections<br> •\tPerform resistance test on occupant classification system and airbag sensor assembly center and replace as necessary<br> •\tPerform resistance test on airbag control module. If it doesn’t pass the test replace the module"},
+ "B1676": { "short_description":"Battery Pack Voltage Out Of Range", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThis anti-lock brake system (ABS) code is set when the ABS module detects a voltage signal that’s less than 9v or more than 19v for more than 8 seconds<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tABS warning light comes on<br> •\tCheck Engine Light may come on<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tBlown fuse in ABS<br> •\tProblem in the charging system<br> •\tWiring problem in ABS module connector<br> •\tDefective ABS module<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring and connectors in ABS module as well as charging system for loose, open or short connections<br> •\tCheck that all fuses in ABS are not blown. If any is blown replace<br> •\tTest resistance of ABS module and compare with manufacturer’s specs<br> •\tReset code and do test drive. If it returns consider replacing the module"},
+ "C0265": { "short_description":"EBCM Motor Relay Circuit Low When On ", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe Electronic Brake Control Module (EBCM) is sending an abnormally low voltage signal<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tABS warning light comes on<br> •\tCheck Engine Light may come on<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tShorted or open wire in EBCM harness<br> •\tPoor electrical connection in EBCM circuit<br> •\tDefective EBCM<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring and connectors in EBCM for loose, open or shorted connections<br> •\tTest EBCM for resistance and compare readings with manufacturer’s specs. If they are out of range consider replacing"},
+ "C1130": { "short_description":"Engine Signal 1", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe ABS control module has detected that there’s a problem with the engine control unit (ECU) or PCM<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tABS warning light comes on<br> •\tCheck Engine Light comes on<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective ECU<br> •\tDefective ABS actuator and/or ABS control module<br> •\tProblem with CAN communication line<br> •\tDamaged controller(s) due to abnormal system voltages<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tDiagnose and address all other codes first before replacing ECU<br> •\tCheck whether system voltage is within manufacturer’s recommendation<br> •\tInspect wiring to ECU and ensure that there are no open, shorted or broken wires<br> •\tCheck all fuses and replace as necessary<br> •\tRun tests on ABS module<br> •\tRun tests on CAN line<br> •\tReset all codes and do test drive. If the code returns you may have to replace ECU"},
+ "C1145": { "short_description":"Right Front Wheel Speed Sensor Input Circuit Failure", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe right front wheel speed, as given by the wheel’s speed sensor is not within the expected range<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tABS warning light comes on<br> •\tCheck Engine Light comes on<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective right front wheel speed sensor<br> •\tWiring problem in that speed sensor’s circuit<br> •\tPCM is not configured properly for the size of the right front wheel<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring to the right front wheel speed sensor and check for open, short, broken and chaffed wires<br> •\tCheck the voltage of the speed sensor and match with manufacturer specs. If they don’t match replace the sensor"},
+ "C1201": { "short_description":"Engine Control System Malfunction", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThe Electronic Control Unit (ECU) has failed<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tOther warning lights may come on depending on which module is affected<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective ECU<br> •\tDamaged controller(s) due to abnormal system voltages<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tDiagnose and address all other codes first before replacing ECU<br> •\tCheck whether system voltage is within manufacturer’s recommendation<br> •\tInspect wiring to ECU and ensure that there are no open, shorted or broken wires<br> •\tReset all codes and do test drive. If the code returns you may have to replace ECU"},
+ "C121C": { "short_description":"Torque Request Signal Denied", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThis camshaft-related code is an informational. It comes with codes P0344, P0345 or P0365. Addressing those codes will get rid of this one"},
+ "C1223": { "short_description":"ABS Control System Malfunction", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThis code is set when the car’s vehicle stability control (VSC) system detects any malfunction in the ABS<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tABS warning light comes on<br> •\tCheck Engine Light comes on<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tOpen or short in the ABS circuit<br> •\tDefective ABS sensor<br> •\tDefective ABS control module<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring in the ABS circuit for loose, open or short connections<br> •\tPerform resistance test on ABS sensors and module. Replace as necessary<br> •\tReset code and do drive cycle, if it returns probe other systems, including PCM"},
+ "C1233": { "short_description":"Left Front Wheel Speed Sensor Input Signal Missing", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM or vehicle speed sensor (VSS) has failed to receive signals from the Left Front Wheel Speed Sensor<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tABS warning light comes on<br> •\tCheck Engine Light comes on<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tPoor connection in Left Front Wheel Speed Sensor<br> •\tOpen, shorted or broken wire in Left Front Wheel Speed Sensor harness<br> •\tDefective Left Front Wheel Speed Sensor<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring in the Left Front Wheel Speed Sensor circuit for loose, open or short connections<br> •\tPerform resistance test on Left Front Wheel Speed Sensor. Replace if necessary<br> •\tReset code and do drive cycle, if it returns probe ABS system entirely"},
+ "C1234": { "short_description":"Right Front Wheel Speed Sensor Input Signal Missing", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM or vehicle speed sensor (VSS) has failed to receive signals from the Right Front Wheel Speed Sensor<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tABS warning light comes on<br> •\tCheck Engine Light comes on<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tPoor connection in Right Front Wheel Speed Sensor<br> •\tOpen, shorted or broken wire in Right Front Wheel Speed Sensor harness<br> •\tDefective Right Front Wheel Speed Sensor<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring in the Right Front Wheel Speed Sensor circuit for loose, open or short connections<br> •\tPerform resistance test on Right Front Wheel Speed Sensor. Replace if necessary<br> •\tReset code and do drive cycle, if it returns probe ABS system entirely"},
+ "C1241": { "short_description":"Low Battery Positive Voltage", "long_description":"<strong>1. Meaning:<\/strong><br> •\tThis code is set when there’s a problem with the skid control ECU (master cylinder solenoid)<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tABS warning light comes on<br> •\tCheck Engine Light comes on<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tLow battery voltage<br> •\tUsing an incorrect battery<br> •\tUnmaintained battery<br> •\tHigh resistance either in alternator-battery circuit, alternator-PCM circuit or both<br> •\tDefective charging system<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tCheck whether battery voltage is sufficient<br> •\tEnsure battery is properly connected then check alternator belt<br> •\tUsing a digital volt ohm meter (DVOM), check whether the charging system is working<br> •\tReset the code then do a test drive. If the code returns check PCM voltage"},
+ "C1713": { "short_description":"Right Rear Height Control Sensor<br> Circuit<br> ", "long_description":"<strong>1. Meaning:<\/strong><br> •\tPCM has detected that after switching ignition ON, a voltage of .3V or less, or 4.7V or more was achieved for more than 1 second at each height control sensor sub−assy rear<br> <br> <strong>3. Main Symptoms:<\/strong><br> •\tCheck Engine Light comes on<br> •\tHeight control indicator lamp (N) comes on or blinks<br> •\tVehicle won’t be able to perform height control function<br> <br> <br> <strong>4. Possible Causes:<\/strong><br> •\tDefective Right Rear Height Control Sensor<br> •\tWiring issue in Right Rear Height Control Sensor<br> •\tWorn out suspension and ride control parts<br> •\tProblem with shocks and/or struts<br> <br> <br> <strong>5. Diagnostic Steps:<\/strong><br> •\tVisually inspect all wiring in the RIGHT Rear Height Control Sensor circuit for loose, open or short connections<br> •\tPerform resistance test on Right Rear Height Control Sensor. Replace if necessary<br> •\tEnsure that all parts, including ball joints, springs (for ride height), shocks and struts are well maintained"}
+ }
\ No newline at end of file
diff --git a/tests/DiagnosticTools/res/raw/system_float_sensors.json b/tests/DiagnosticTools/res/raw/system_float_sensors.json
new file mode 100644
index 0000000..4311e10
--- /dev/null
+++ b/tests/DiagnosticTools/res/raw/system_float_sensors.json
@@ -0,0 +1,36 @@
+{
+ "FUEL_TANK_LEVEL_INPUT": {
+ "units": "%",
+ "translation": "x/2.55",
+ "name": "Fuel Tank Level Input"
+ },
+ "ENGINE_RPM": {
+ "units": "RPM",
+ "translation": "x/4",
+ "name": "Engine RPM"
+ },
+ "CALCULATED_ENGINE_LOAD": {
+ "units": "%",
+ "translation": "x/2.55",
+ "name": "Calculated Engine Load"
+ },
+ "SHORT_TERM_FUEL_TRIM_BANK1": {
+ "units": "%",
+ "conversion": {
+ "scale": 0.78125,
+ "offset": -100
+ },
+ "translation": "x/1.28 - 100",
+ "name": "Short Term Fuel Trim: Bank 1"
+ },
+ "VEHICLE_SPEED": {
+ "units": "KMH",
+ "translation": "",
+ "name": "Vehicle Speed"
+ },
+ "ENGINE_COOLANT_TEMPERATURE": {
+ "units": "C",
+ "translation": "x-40",
+ "name": "Engine Coolant Temperature"
+ }
+}
\ No newline at end of file
diff --git a/tests/DiagnosticTools/res/raw/system_integer_sensors.json b/tests/DiagnosticTools/res/raw/system_integer_sensors.json
new file mode 100644
index 0000000..a9f2775
--- /dev/null
+++ b/tests/DiagnosticTools/res/raw/system_integer_sensors.json
@@ -0,0 +1,23 @@
+{
+ "AMBIENT_AIR_TEMPERATURE": {
+ "units": "C",
+ "translation": "x-40",
+ "name": "Ambient Air Temperature"
+ },
+ "RUNTIME_SINCE_ENGINE_START": {
+ "units": "seconds",
+ "translation": "x-40",
+ "name": "Runtime Since Engine Start"
+ },
+ "FUEL_SYSTEM_STATUS": {
+ "units": "",
+ "mapping": {
+ "1": "Open loop due to insufficient engine temperature",
+ "2": "Closed loop, using oxygen sensor feedback to determine fuel mix",
+ "4": "Open loop due to engine load OR fuel cut due to deceleration",
+ "8": "Open loop due to system failure",
+ "16": "Closed loop, using at least one oxygen sensor but there is a fault in the feedback system"
+ },
+ "name": "Fuel System Status"
+ }
+}
\ No newline at end of file
diff --git a/tests/DiagnosticTools/res/raw/vendor_dtcs.json b/tests/DiagnosticTools/res/raw/vendor_dtcs.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/tests/DiagnosticTools/res/raw/vendor_dtcs.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/tests/DiagnosticTools/res/raw/vendor_ecus.json b/tests/DiagnosticTools/res/raw/vendor_ecus.json
new file mode 100644
index 0000000..973e627
--- /dev/null
+++ b/tests/DiagnosticTools/res/raw/vendor_ecus.json
@@ -0,0 +1,7 @@
+{
+ "123": "Door Control Unit",
+ "124": "Engine Control Unit",
+ "125": "Engine Power Steering Control Unit",
+ "222": "Seat Control Unit",
+ "221": "Telematic Control Unit"
+}
\ No newline at end of file
diff --git a/tests/DiagnosticTools/res/raw/vendor_float_sensors.json b/tests/DiagnosticTools/res/raw/vendor_float_sensors.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/tests/DiagnosticTools/res/raw/vendor_float_sensors.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/tests/DiagnosticTools/res/raw/vendor_integer_sensors.json b/tests/DiagnosticTools/res/raw/vendor_integer_sensors.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/tests/DiagnosticTools/res/raw/vendor_integer_sensors.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/tests/DiagnosticTools/res/values-af/strings.xml b/tests/DiagnosticTools/res/values-af/strings.xml
new file mode 100644
index 0000000..57424bd
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-af/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Wys Vries Raam-inligting"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-am/strings.xml b/tests/DiagnosticTools/res/values-am/strings.xml
new file mode 100644
index 0000000..44fa319
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-am/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"የክፈፍ እሰር መረጃን አሳይ"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-ar/strings.xml b/tests/DiagnosticTools/res/values-ar/strings.xml
new file mode 100644
index 0000000..d2e46ff
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-ar/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"عرض معلومات عن الإطار الثابت"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-as/strings.xml b/tests/DiagnosticTools/res/values-as/strings.xml
new file mode 100644
index 0000000..98fc05f
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-as/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"ফ্ৰীজ ফ্ৰে’মৰ তথ্য দেখুৱাওক"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-az/strings.xml b/tests/DiagnosticTools/res/values-az/strings.xml
new file mode 100644
index 0000000..95f4ea9
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-az/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Stop-kadr məlumatını göstərin"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-b+sr+Latn/strings.xml b/tests/DiagnosticTools/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..fa16fed
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-b+sr+Latn/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Prikaži informacije o zamrznutom okviru"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-be/strings.xml b/tests/DiagnosticTools/res/values-be/strings.xml
new file mode 100644
index 0000000..e73e14c
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-be/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Інфармацыя пра замарожаны кадр экрана"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-bg/strings.xml b/tests/DiagnosticTools/res/values-bg/strings.xml
new file mode 100644
index 0000000..71b4550
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-bg/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Показване на информацията за фиксиране на рамката"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-bn/strings.xml b/tests/DiagnosticTools/res/values-bn/strings.xml
new file mode 100644
index 0000000..56ce8c7
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-bn/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"ফ্রিজ ফ্রেমের তথ্য দেখাও"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-bs/strings.xml b/tests/DiagnosticTools/res/values-bs/strings.xml
new file mode 100644
index 0000000..f049f27
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-bs/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Prikaz informacija o zamrznutom okviru"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-ca/strings.xml b/tests/DiagnosticTools/res/values-ca/strings.xml
new file mode 100644
index 0000000..9bcaa94
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-ca/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Mostra informació sobre el bloqueig del marc"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-cs/strings.xml b/tests/DiagnosticTools/res/values-cs/strings.xml
new file mode 100644
index 0000000..b769c80
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-cs/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Zobrazit informace o ukotveném rámci"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-da/strings.xml b/tests/DiagnosticTools/res/values-da/strings.xml
new file mode 100644
index 0000000..5472fde
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-da/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Vis oplysninger om stillbillede"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-de/strings.xml b/tests/DiagnosticTools/res/values-de/strings.xml
new file mode 100644
index 0000000..9aabaf5
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-de/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Informationen zum Freeze Frame anzeigen"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-el/strings.xml b/tests/DiagnosticTools/res/values-el/strings.xml
new file mode 100644
index 0000000..ec201ec
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-el/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Εμφάνιση πληροφοριών σταθεροποίησης πλαισίου"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-en-rAU/strings.xml b/tests/DiagnosticTools/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..bd4ccb9
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-en-rAU/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Display freeze frame Info"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-en-rCA/strings.xml b/tests/DiagnosticTools/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..bd4ccb9
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-en-rCA/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Display freeze frame Info"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-en-rGB/strings.xml b/tests/DiagnosticTools/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..bd4ccb9
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-en-rGB/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Display freeze frame Info"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-en-rIN/strings.xml b/tests/DiagnosticTools/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..bd4ccb9
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-en-rIN/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Display freeze frame Info"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-en-rXC/strings.xml b/tests/DiagnosticTools/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..6203c22
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-en-rXC/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Display Freeze Frame Info"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-es-rUS/strings.xml b/tests/DiagnosticTools/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..437c8df
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-es-rUS/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Mostrar información del fotograma bloqueado"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-es/strings.xml b/tests/DiagnosticTools/res/values-es/strings.xml
new file mode 100644
index 0000000..e1c0523
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-es/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Mostrar información del marco inmovilizado"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-et/strings.xml b/tests/DiagnosticTools/res/values-et/strings.xml
new file mode 100644
index 0000000..cdeb1c6
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-et/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Kuva hangunud kaadri teave"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-eu/strings.xml b/tests/DiagnosticTools/res/values-eu/strings.xml
new file mode 100644
index 0000000..5adc732
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-eu/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Bistaratu fotogramaren informazioa"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-fa/strings.xml b/tests/DiagnosticTools/res/values-fa/strings.xml
new file mode 100644
index 0000000..9785166
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-fa/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"نمایش اطلاعات Freeze Frame"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-fi/strings.xml b/tests/DiagnosticTools/res/values-fi/strings.xml
new file mode 100644
index 0000000..e19f9f9
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-fi/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Näytä pysäytetyn kehyksen tiedot"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-fr-rCA/strings.xml b/tests/DiagnosticTools/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..c67b69e
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-fr-rCA/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Afficher les renseignements de l\'arrêt sur image"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-fr/strings.xml b/tests/DiagnosticTools/res/values-fr/strings.xml
new file mode 100644
index 0000000..f7b39e9
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-fr/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Afficher les informations sur l\'image fixe"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-gl/strings.xml b/tests/DiagnosticTools/res/values-gl/strings.xml
new file mode 100644
index 0000000..6f9c271
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-gl/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Mostrar información de marco fixo"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-gu/strings.xml b/tests/DiagnosticTools/res/values-gu/strings.xml
new file mode 100644
index 0000000..bf3308f
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-gu/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"ફ્રેમને સ્થિર કરવા માટેની માહિતી બતાવો"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-hi/strings.xml b/tests/DiagnosticTools/res/values-hi/strings.xml
new file mode 100644
index 0000000..0975220
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-hi/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"फ़्रेम को फ़्रीज़ करने की जानकारी दिखाएं"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-hr/strings.xml b/tests/DiagnosticTools/res/values-hr/strings.xml
new file mode 100644
index 0000000..f049f27
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-hr/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Prikaz informacija o zamrznutom okviru"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-hu/strings.xml b/tests/DiagnosticTools/res/values-hu/strings.xml
new file mode 100644
index 0000000..3f6c0db
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-hu/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Freeze Frame-adat megjelenítése"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-hy/strings.xml b/tests/DiagnosticTools/res/values-hy/strings.xml
new file mode 100644
index 0000000..f121ac9
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-hy/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Ցուցադրել սառեցված կադրի տվյալները"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-in/strings.xml b/tests/DiagnosticTools/res/values-in/strings.xml
new file mode 100644
index 0000000..cf97c3c
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-in/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Tampilkan Info Freeze Frame"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-is/strings.xml b/tests/DiagnosticTools/res/values-is/strings.xml
new file mode 100644
index 0000000..e6b6ae9
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-is/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Birta upplýsingar um frystan ramma"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-it/strings.xml b/tests/DiagnosticTools/res/values-it/strings.xml
new file mode 100644
index 0000000..d35ff17
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-it/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Mostra informazioni sul fotogramma di blocco"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-iw/strings.xml b/tests/DiagnosticTools/res/values-iw/strings.xml
new file mode 100644
index 0000000..e0065b7
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-iw/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"הצגת פרטים על הקפאת מסגרת"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-ja/strings.xml b/tests/DiagnosticTools/res/values-ja/strings.xml
new file mode 100644
index 0000000..4c75450
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-ja/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"ディスプレイ フリーズ フレーム情報"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-ka/strings.xml b/tests/DiagnosticTools/res/values-ka/strings.xml
new file mode 100644
index 0000000..cf35524
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-ka/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"სტოპ-კადრის ინფორმაციის ჩვენება"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-kk/strings.xml b/tests/DiagnosticTools/res/values-kk/strings.xml
new file mode 100644
index 0000000..04626ed
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-kk/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Стоп-кадр ақпаратын көрсету"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-km/strings.xml b/tests/DiagnosticTools/res/values-km/strings.xml
new file mode 100644
index 0000000..37f54f4
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-km/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"បង្ហាញព័ត៌មានអំពីស៊ុមគាំង"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-kn/strings.xml b/tests/DiagnosticTools/res/values-kn/strings.xml
new file mode 100644
index 0000000..cf4e172
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-kn/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"ಫ್ರೀಜ್ ಫ್ರೇಮ್ ಮಾಹಿತಿಯನ್ನು ಡಿಸ್ಪ್ಲೇ ಮಾಡಿ"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-ko/strings.xml b/tests/DiagnosticTools/res/values-ko/strings.xml
new file mode 100644
index 0000000..26fea08
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-ko/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"정지 화면 정보 표시"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-ky/strings.xml b/tests/DiagnosticTools/res/values-ky/strings.xml
new file mode 100644
index 0000000..c74ecfc
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-ky/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Freeze Frame\'дин маалыматын чагылдыруу"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-lo/strings.xml b/tests/DiagnosticTools/res/values-lo/strings.xml
new file mode 100644
index 0000000..34a5849
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-lo/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"ສະແດງຂໍ້ມູນເຟຣມຄ້າງ"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-lt/strings.xml b/tests/DiagnosticTools/res/values-lt/strings.xml
new file mode 100644
index 0000000..1f83787
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-lt/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Rodyti užfiksuoto kadro informaciją"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-lv/strings.xml b/tests/DiagnosticTools/res/values-lv/strings.xml
new file mode 100644
index 0000000..a835124
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-lv/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Rādīt fiksētā kadra informāciju"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-mk/strings.xml b/tests/DiagnosticTools/res/values-mk/strings.xml
new file mode 100644
index 0000000..804ab83
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-mk/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Информации за замрзната рамка на екранот"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-ml/strings.xml b/tests/DiagnosticTools/res/values-ml/strings.xml
new file mode 100644
index 0000000..dc612dd
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-ml/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"ഫ്രീസ് ഫ്രെയിമിനെക്കുറിച്ചുള്ള വിവരം കാണിക്കുക"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-mn/strings.xml b/tests/DiagnosticTools/res/values-mn/strings.xml
new file mode 100644
index 0000000..ded1e9a
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-mn/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Freeze Frame-н мэдээлэл харуулах"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-mr/strings.xml b/tests/DiagnosticTools/res/values-mr/strings.xml
new file mode 100644
index 0000000..94eea43
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-mr/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"फ्रीझ फ्रेम माहिती प्रदर्शित करा"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-ms/strings.xml b/tests/DiagnosticTools/res/values-ms/strings.xml
new file mode 100644
index 0000000..67d2ba0
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-ms/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Paparkan Maklumat Bingkai Pegun"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-my/strings.xml b/tests/DiagnosticTools/res/values-my/strings.xml
new file mode 100644
index 0000000..98c8d16
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-my/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"ရပ်နေသည့်ဖရိမ် အချက်အလက်များကို ပြရန်"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-nb/strings.xml b/tests/DiagnosticTools/res/values-nb/strings.xml
new file mode 100644
index 0000000..51af902
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-nb/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Vis informasjon om øyeblikksbildet"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-ne/strings.xml b/tests/DiagnosticTools/res/values-ne/strings.xml
new file mode 100644
index 0000000..c227447
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-ne/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"डिस्प्ले फ्रिज गर्ने फ्रेमसम्बन्धी जानकारी"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-nl/strings.xml b/tests/DiagnosticTools/res/values-nl/strings.xml
new file mode 100644
index 0000000..a808fd2
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-nl/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Informatie over freeze frame weergeven"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-or/strings.xml b/tests/DiagnosticTools/res/values-or/strings.xml
new file mode 100644
index 0000000..22df718
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-or/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"ଫ୍ରିଜ୍ ଫ୍ରେମ୍ ସୂଚନା ପ୍ରଦର୍ଶନ କରନ୍ତୁ"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-pa/strings.xml b/tests/DiagnosticTools/res/values-pa/strings.xml
new file mode 100644
index 0000000..a2277c6
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-pa/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"ਫ੍ਰੀਜ਼ ਫ੍ਰੇਮ ਜਾਣਕਾਰੀ ਦਿਖਾਓ"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-pl/strings.xml b/tests/DiagnosticTools/res/values-pl/strings.xml
new file mode 100644
index 0000000..4828319
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-pl/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Wyświetl informacje o zatrzymanej klatce"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-pt-rPT/strings.xml b/tests/DiagnosticTools/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..d768d53
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-pt-rPT/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Apresentar informações de frame fixo"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-pt/strings.xml b/tests/DiagnosticTools/res/values-pt/strings.xml
new file mode 100644
index 0000000..968bfe1
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-pt/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Mostrar informação do congelamento do frame"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-ro/strings.xml b/tests/DiagnosticTools/res/values-ro/strings.xml
new file mode 100644
index 0000000..d06e299
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-ro/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Afișați informații despre cadrul blocat"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-ru/strings.xml b/tests/DiagnosticTools/res/values-ru/strings.xml
new file mode 100644
index 0000000..482ee1b
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-ru/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Показывать информацию на стоп-кадре"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-si/strings.xml b/tests/DiagnosticTools/res/values-si/strings.xml
new file mode 100644
index 0000000..3304298
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-si/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"ඇවුරුම් රාමු තතු සංදර්ශනය"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-sk/strings.xml b/tests/DiagnosticTools/res/values-sk/strings.xml
new file mode 100644
index 0000000..967abff
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-sk/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Zobraziť informácie o ukotvenom rámci"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-sl/strings.xml b/tests/DiagnosticTools/res/values-sl/strings.xml
new file mode 100644
index 0000000..c856e68
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-sl/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Prikaz podatkov o zamrznjenem okviru"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-sq/strings.xml b/tests/DiagnosticTools/res/values-sq/strings.xml
new file mode 100644
index 0000000..a129f8d
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-sq/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Shfaq informacionin e ngrirjes së kuadrit"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-sr/strings.xml b/tests/DiagnosticTools/res/values-sr/strings.xml
new file mode 100644
index 0000000..abae266
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-sr/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Прикажи информације о замрзнутом оквиру"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-sv/strings.xml b/tests/DiagnosticTools/res/values-sv/strings.xml
new file mode 100644
index 0000000..ab70663
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-sv/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Visa information om fryst bildruta"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-sw/strings.xml b/tests/DiagnosticTools/res/values-sw/strings.xml
new file mode 100644
index 0000000..c3f839e
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-sw/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Onyesha Maelezo kuhusu Fremu ya Kufanya Skrini Isisonge"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-ta/strings.xml b/tests/DiagnosticTools/res/values-ta/strings.xml
new file mode 100644
index 0000000..09e74cc
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-ta/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"ஃப்ரீஸ் ஃப்ரேம் தகவலைக் காட்டு"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-te/strings.xml b/tests/DiagnosticTools/res/values-te/strings.xml
new file mode 100644
index 0000000..dfad13b
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-te/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"స్తంభించిన ఫ్రేమ్ సమాచారాన్ని ప్రదర్శించు"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-th/strings.xml b/tests/DiagnosticTools/res/values-th/strings.xml
new file mode 100644
index 0000000..098229f
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-th/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"แสดงข้อมูลเฟรมค้าง"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-tl/strings.xml b/tests/DiagnosticTools/res/values-tl/strings.xml
new file mode 100644
index 0000000..561b1e8
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-tl/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Ipakita ang Impormasyon ng Freeze Frame"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-tr/strings.xml b/tests/DiagnosticTools/res/values-tr/strings.xml
new file mode 100644
index 0000000..e7c5340
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-tr/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Kare Dondurma Bilgilerini Göster"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-uk/strings.xml b/tests/DiagnosticTools/res/values-uk/strings.xml
new file mode 100644
index 0000000..073f940
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-uk/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Інформація про показ стоп-кадру"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-ur/strings.xml b/tests/DiagnosticTools/res/values-ur/strings.xml
new file mode 100644
index 0000000..07254b9
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-ur/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"فریز کو فریم کرنے کی معلومات دکھائیں"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-uz/strings.xml b/tests/DiagnosticTools/res/values-uz/strings.xml
new file mode 100644
index 0000000..40b606e
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-uz/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Stop-kadrni chiqarish axboroti"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-vi/strings.xml b/tests/DiagnosticTools/res/values-vi/strings.xml
new file mode 100644
index 0000000..a2b79b0
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-vi/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Hiển thị thông tin về khung cố định"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-zh-rCN/strings.xml b/tests/DiagnosticTools/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..f7bdfea
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-zh-rCN/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"显示冻结帧信息"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-zh-rHK/strings.xml b/tests/DiagnosticTools/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..4733dbb
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-zh-rHK/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"顯示頁框凍結資訊"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-zh-rTW/strings.xml b/tests/DiagnosticTools/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..103d099
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-zh-rTW/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"顯示凍結頁框資訊"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values-zu/strings.xml b/tests/DiagnosticTools/res/values-zu/strings.xml
new file mode 100644
index 0000000..94ff953
--- /dev/null
+++ b/tests/DiagnosticTools/res/values-zu/strings.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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_freeze_frame_info" msgid="1425573367248263107">"Bonisa ulwazi lokumisa uzimele"</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values/strings.xml b/tests/DiagnosticTools/res/values/strings.xml
new file mode 100644
index 0000000..fa8fb51
--- /dev/null
+++ b/tests/DiagnosticTools/res/values/strings.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>
+ <string name="display_freeze_frame_info">Display Freeze Frame Info</string>
+</resources>
diff --git a/tests/DiagnosticTools/res/values/styles.xml b/tests/DiagnosticTools/res/values/styles.xml
new file mode 100644
index 0000000..66e44ff
--- /dev/null
+++ b/tests/DiagnosticTools/res/values/styles.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
+ -->
+
+<resources>
+ <style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
+ <item name="android:colorPrimary">#008577</item>
+ <item name="android:colorPrimaryDark">#00574B</item>
+ <item name="android:colorAccent">#D81B60</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowActionBar">false</item>
+ </style>
+
+</resources>
diff --git a/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/DTC.java b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/DTC.java
new file mode 100644
index 0000000..ca75157
--- /dev/null
+++ b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/DTC.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.google.android.car.diagnostictools;
+
+import android.content.Context;
+import android.os.Parcel;
+import android.text.Html;
+import android.text.Spanned;
+import android.text.SpannedString;
+
+import com.google.android.car.diagnostictools.utils.DTCMetadata;
+import com.google.android.car.diagnostictools.utils.MetadataProcessing;
+import com.google.android.car.diagnostictools.utils.SelectableRowModel;
+
+import java.util.Random;
+
+/**
+ * Model which wraps DTC code and metadata information for display through DTCAdapter. Extends
+ * SelectableRowModel to allow for selection and use with SelectableAdapter
+ */
+public class DTC extends SelectableRowModel implements android.os.Parcelable {
+
+ public static final Creator<DTC> CREATOR =
+ new Creator<DTC>() {
+ @Override
+ public DTC createFromParcel(Parcel source) {
+ return new DTC(source);
+ }
+
+ @Override
+ public DTC[] newArray(int size) {
+ return new DTC[size];
+ }
+ };
+ private static final String TAG = "DTC";
+ private static Random sRandomGen;
+ private String mCode;
+ private String mDescription;
+ private long mTimestamp;
+ private Spanned mLongDescription;
+ private String mStringLongDescription; // Used for Parcelable compatibility
+
+ /**
+ * Full constructor for DTC.
+ *
+ * @param code DTC code associated with the DTC
+ * @param description Short description associated with the DTC
+ * @param timestamp Timestamp associated with the DTC
+ * @param longDescription Long descriptions associated with the DTC
+ * @param stringLongDescription String version of longDescription for Parcelable support
+ */
+ private DTC(
+ String code,
+ String description,
+ long timestamp,
+ Spanned longDescription,
+ String stringLongDescription) {
+ this.mCode = code;
+ this.mDescription = description;
+ this.mTimestamp = timestamp;
+ this.mLongDescription = longDescription;
+ this.mStringLongDescription = stringLongDescription;
+ }
+
+ /**
+ * Paired down constructor that utilizes DTC metadata that is preloaded.
+ *
+ * @param code DTC code associated with the DTC
+ * @param timestamp Timestamp associated with the DTC
+ * @param context Context from which this is called. Required to allow MetadataProcessing to be
+ * loaded if the singleton has not been instantiated
+ */
+ DTC(String code, long timestamp, Context context) {
+ this.mCode = code;
+ this.mTimestamp = timestamp;
+ DTCMetadata dtcMetadata = getDTCMetadata(code, context);
+ if (dtcMetadata != null) {
+ this.mDescription = dtcMetadata.getShortDescription();
+ this.mLongDescription = dtcMetadata.getSpannedLongDescription();
+ this.mStringLongDescription = dtcMetadata.getStringLongDescription();
+ } else {
+ this.mDescription = "No Description Available";
+ this.mLongDescription = SpannedString.valueOf("No Details Available");
+ this.mStringLongDescription = "No Details Available";
+ }
+ }
+
+ protected DTC(Parcel in) {
+ this.mCode = in.readString();
+ this.mDescription = in.readString();
+ this.mTimestamp = in.readLong();
+ this.mStringLongDescription = in.readString();
+ this.mLongDescription = Html.fromHtml(this.mStringLongDescription, 0);
+ }
+
+ public String getCode() {
+ return mCode;
+ }
+
+ public String getDescription() {
+ return mDescription;
+ }
+
+ public long getTimestamp() {
+ return mTimestamp;
+ }
+
+ //Delete when DTCs are implemented
+ public void setTimestamp(long timestamp) {
+ mTimestamp = timestamp;
+ }
+
+ public Spanned getLongDescription() {
+ return mLongDescription;
+ }
+
+
+ /**
+ * Create sample DTC using MetadataProcessing for values. Some numbers will not return actual
+ * values and will be replaced with placeholder information that would be presented if metadata
+ * wasn't found.
+ *
+ * @param number Used to generate the DTC code which will be "P(008+number)"
+ * @param context Context from which this is called. Required to allow MetadataProcessing to be
+ * loaded if the singleton has not been instantiated
+ * @return New sample DTC based on number and metadata
+ */
+ static DTC createSampleDTC(int number, Context context) {
+ String code = String.format("P%04d", 8 + number);
+ if (sRandomGen == null) {
+ sRandomGen = new Random();
+ }
+ long timestamp = sRandomGen.nextLong();
+ return new DTC(code, timestamp, context);
+ }
+
+ private DTCMetadata getDTCMetadata(String code, Context context) {
+ return MetadataProcessing.getInstance(context).getDTCMetadata(code);
+ }
+
+ /**
+ * Implement method of SelectableRowModel. One element is selected as the DTC is the base child
+ *
+ * @return Returns 1 (as DTC is the based element)
+ */
+ @Override
+ public int numSelected() {
+ return 1;
+ }
+
+ /** TODO: Calls VHAL DTC delete method to allow this DTC to be cleared */
+ @Override
+ public void delete() {
+ // TODO clear DTC
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(this.mCode);
+ dest.writeString(this.mDescription);
+ dest.writeLong(this.mTimestamp);
+ dest.writeString(this.mStringLongDescription);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+}
diff --git a/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/DTCAdapter.java b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/DTCAdapter.java
new file mode 100644
index 0000000..f837666
--- /dev/null
+++ b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/DTCAdapter.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.google.android.car.diagnostictools;
+
+import android.content.Context;
+import android.content.Intent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+
+import com.google.android.car.diagnostictools.utils.SelectableAdapter;
+
+import java.util.List;
+
+/** Adapter for RecyclerView in DTCListActivity which displays DTCs */
+public class DTCAdapter extends SelectableAdapter<DTC, RowViewHolder> {
+
+ private List<DTC> mDtcs;
+ private Context mContext;
+
+ DTCAdapter(List<DTC> inputDTCs, Context context) {
+ mDtcs = inputDTCs;
+ mContext = context;
+ }
+
+ @NonNull
+ @Override
+ public RowViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+
+ View v = inflater.inflate(R.layout.row_layout, parent, false);
+
+ return new RowViewHolder(v, true, false, false);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull RowViewHolder holder, int position) {
+ final DTC refDTC = mDtcs.get(position);
+ final RowViewHolder finalHolder = holder;
+ holder.setFields(refDTC.getCode(), refDTC.getDescription(), "", false);
+ refDTC.setColor(finalHolder);
+ holder.layout.setOnClickListener(
+ new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (hasSelected()) {
+ toggleSelect(refDTC);
+ refDTC.setColor(finalHolder);
+ } else {
+ Intent intent = new Intent(mContext, DTCDetailActivity.class);
+ intent.putExtra("dtc", refDTC);
+ mContext.startActivity(intent);
+ }
+ }
+ });
+ holder.layout.setOnLongClickListener(
+ new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View view) {
+ toggleSelect(refDTC);
+ refDTC.setColor(finalHolder);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public int getItemCount() {
+ return mDtcs.size();
+ }
+
+ /**
+ * Overrides method getBaseList of SelectableAdapter to allow selection of elements
+ *
+ * @return base list of DTCs
+ */
+ @Override
+ protected List<DTC> getBaseList() {
+ return mDtcs;
+ }
+}
diff --git a/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/DTCDetailActivity.java b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/DTCDetailActivity.java
new file mode 100644
index 0000000..7ea03fc
--- /dev/null
+++ b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/DTCDetailActivity.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.google.android.car.diagnostictools;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.car.Car;
+import android.car.diagnostic.CarDiagnosticEvent;
+import android.car.diagnostic.CarDiagnosticManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import android.widget.Toolbar;
+
+import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.google.android.car.diagnostictools.utils.MetadataProcessing;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Displays detailed information about a specific DTC. Opened through clicking a DTC in
+ * DTCListActivity
+ */
+public class DTCDetailActivity extends Activity {
+
+ private static final String TAG = "DTCDetailActivity";
+ private final Handler mHandler = new Handler();
+ private Toolbar mDTCTitle;
+ private TextView mDTCDetails;
+ private DTC mDTC;
+ private ProgressBar mFreezeFrameLoading;
+ private TextView mFreezeFrameTitle;
+ private Button mFreezeFrameClear;
+ private RecyclerView mFreezeFrameData;
+ private CarDiagnosticManager mCarDiagnosticManager;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_dtc_details);
+
+ mDTCTitle = findViewById(R.id.toolbar);
+ mDTCTitle.setNavigationIcon(R.drawable.ic_arrow_back_black_24dp);
+ mDTCTitle.setNavigationOnClickListener(
+ view -> {
+ finish();
+ mHandler.removeCallbacksAndMessages(null);
+ });
+ mDTCDetails = findViewById(R.id.dtc_details);
+ mFreezeFrameLoading = findViewById(R.id.freeze_frame_loading);
+ mFreezeFrameTitle = findViewById(R.id.freeze_frame_title);
+ mFreezeFrameClear = findViewById(R.id.freeze_frame_clear);
+ mFreezeFrameData = findViewById(R.id.freeze_frame_data);
+
+ hideFreezeFrameFields();
+
+ // Set up RecyclerView
+ mFreezeFrameData.setHasFixedSize(false);
+ mFreezeFrameData.setLayoutManager(new LinearLayoutManager(DTCDetailActivity.this));
+ final List<LiveDataAdapter.SensorDataWrapper> input = new ArrayList<>();
+ // Add test data
+ for (int i = 0; i < 100; i++) {
+ input.add(new LiveDataAdapter.SensorDataWrapper("Test " + i, "%", i));
+ }
+ LiveDataAdapter adapter = new LiveDataAdapter(input);
+ mFreezeFrameData.setAdapter(adapter);
+ mFreezeFrameData.addItemDecoration(
+ new DividerItemDecoration(
+ mFreezeFrameData.getContext(), DividerItemDecoration.VERTICAL));
+
+ loadingFreezeFrame();
+
+ mCarDiagnosticManager =
+ (CarDiagnosticManager) Car.createCar(this).getCarManager(Car.DIAGNOSTIC_SERVICE);
+
+ // Runnable function that checks to see if there is a Freeze Frame available or not.
+ // Repeats
+ // until there is a Freeze Frame available
+ mHandler.postDelayed(
+ new Runnable() {
+ @Override
+ public void run() {
+ long[] timestamps = mCarDiagnosticManager.getFreezeFrameTimestamps();
+ Log.e(TAG, "onCreate: Number of timestamps" + timestamps.length);
+ if (timestamps.length > 0) {
+ CarDiagnosticEvent freezeFrame =
+ mCarDiagnosticManager.getFreezeFrame(
+ timestamps[timestamps.length - 1]);
+ adapter.update(
+ LiveDataActivity.processSensorInfoIntoWrapper(
+ freezeFrame,
+ MetadataProcessing.getInstance(
+ DTCDetailActivity.this)));
+ loadedFreezeFrame();
+ mDTC.setTimestamp(timestamps[timestamps.length - 1]);
+ } else {
+ hideFreezeFrameFields();
+ mHandler.postDelayed(this, 2000);
+ }
+ }
+ },
+ 0);
+
+ getIncomingIntent();
+ }
+
+ /** Handle incoming intent to extract extras. */
+ private void getIncomingIntent() {
+ Log.d(TAG, "getIncomingIntent: extras: " + getIntent().toString());
+ if (getIntent().hasExtra("dtc")) {
+ mDTC = getIntent().getParcelableExtra("dtc");
+ setUpDetailPage();
+ }
+ }
+
+ /** Assuming dtc has been set to a DTC. */
+ private void setUpDetailPage() {
+ if (mDTC != null) {
+ mDTCTitle.setTitle(mDTC.getCode() + ": " + mDTC.getDescription());
+ mDTCDetails.setText(mDTC.getLongDescription());
+ } else {
+ mDTCTitle.setTitle("No DTC input");
+ mDTCDetails.setText("No DTC long description");
+ }
+ }
+
+ /** Hide all Freeze Frame associated elements. */
+ private void hideFreezeFrameFields() {
+ mFreezeFrameData.setVisibility(View.INVISIBLE);
+ mFreezeFrameClear.setVisibility(View.INVISIBLE);
+ mFreezeFrameTitle.setVisibility(View.INVISIBLE);
+ mFreezeFrameLoading.setVisibility(View.INVISIBLE);
+ }
+
+ /** Hide most Freeze Frame associated elements and tell user that there isn't one available. */
+ private void noFreezeFrameAvailable() {
+ hideFreezeFrameFields();
+ mFreezeFrameTitle.setVisibility(View.VISIBLE);
+ mFreezeFrameTitle.setText(
+ "No Freeze Frame Data Available Right Now. Data will appear if becomes available");
+ }
+
+ /** Indicate to the user that a freeze frame is being loaded with a spinning progress bar */
+ private void loadingFreezeFrame() {
+ mFreezeFrameTitle.setVisibility(View.VISIBLE);
+ mFreezeFrameTitle.setText("Freeze Frame Loading...");
+ mFreezeFrameLoading.setVisibility(View.VISIBLE);
+ }
+
+ /**
+ * Displays freeze frame and conditionally displays button to clear it based on if functionality
+ * is supported
+ */
+ private void loadedFreezeFrame() {
+ mFreezeFrameLoading.setVisibility(View.INVISIBLE);
+ if (mCarDiagnosticManager.isClearFreezeFramesSupported()
+ && mCarDiagnosticManager.isSelectiveClearFreezeFramesSupported()) {
+ mFreezeFrameClear.setVisibility(View.VISIBLE);
+ }
+ mFreezeFrameData.setVisibility(View.VISIBLE);
+ mFreezeFrameTitle.setText("Freeze Frame");
+ }
+
+ /**
+ * Handles button press of the clear Freeze Frame button. Confirms that the user would like to
+ * do this action and then clears Frames with Manager methods
+ *
+ * @param v View that triggered the function
+ */
+ public void clearFreezeFrameButtonPress(View v) {
+ new AlertDialog.Builder(this)
+ .setTitle("Confirm Freeze Frame Clear")
+ .setMessage(
+ String.format(
+ "Do you really want to clear the freeze frame for DTC %s?",
+ mDTC.getCode()))
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setPositiveButton(
+ android.R.string.yes,
+ (dialog, whichButton) -> {
+ mCarDiagnosticManager.clearFreezeFrames(mDTC.getTimestamp());
+ hideFreezeFrameFields();
+ })
+ .setNegativeButton(android.R.string.no, null)
+ .show();
+ }
+
+ /** Removes all callbacks from mHandler when DTCDetailActivity is destroyed */
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (mHandler != null) {
+ mHandler.removeCallbacksAndMessages(null);
+ }
+ }
+}
diff --git a/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/DTCListActivity.java b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/DTCListActivity.java
new file mode 100644
index 0000000..4d7220b
--- /dev/null
+++ b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/DTCListActivity.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.google.android.car.diagnostictools;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Toolbar;
+
+import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.List;
+
+/** Displays a list of DTCs associated with an ECU */
+public class DTCListActivity extends Activity {
+
+ private static final String TAG = "DTCListActivity";
+ private String mEcuName;
+ private List<DTC> mDtcs;
+ private Toolbar mEcuTitle;
+ private RecyclerView mDTCList;
+ private DTCAdapter mAdapter;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_dtc_list);
+ mEcuTitle = findViewById(R.id.toolbar);
+ mEcuTitle.setNavigationIcon(R.drawable.ic_arrow_back_black_24dp);
+ mEcuTitle.setNavigationOnClickListener(view -> finish());
+
+ mDTCList = findViewById(R.id.dtc_list);
+ mDTCList.setHasFixedSize(true);
+ mDTCList.setLayoutManager(new LinearLayoutManager(this));
+ getIncomingIntent();
+ }
+
+ /** Handle incoming intent and extras. Extract ECU name and DTC list */
+ private void getIncomingIntent() {
+ Log.d(TAG, "getIncomingIntent: extras: " + getIntent().toString());
+ if (getIntent().hasExtra("name")) {
+ mEcuName = getIntent().getStringExtra("name");
+ mEcuTitle.setTitle(mEcuName);
+ }
+ if (getIntent().hasExtra("dtcs")) {
+ mDtcs = getIntent().getParcelableArrayListExtra("dtcs");
+ mAdapter = new DTCAdapter(mDtcs, this);
+ mDTCList.setAdapter(mAdapter);
+ mDTCList.addItemDecoration(
+ new DividerItemDecoration(
+ mDTCList.getContext(), DividerItemDecoration.VERTICAL));
+ }
+ }
+
+ /**
+ * Handle clicks from the ActionButton. Confirms that the user wants to clear selected DTCs and
+ * then deletes them on confirmation.
+ */
+ public void onClickActionButton(View view) {
+ new AlertDialog.Builder(this)
+ .setTitle("Clear DTCs")
+ .setMessage(
+ String.format(
+ "Do you really want to clear %d mDtcs?", mAdapter.numSelected()))
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setPositiveButton(
+ android.R.string.yes, (dialog, whichButton) -> mAdapter.deleteSelected())
+ .setNegativeButton(android.R.string.no, null)
+ .show();
+ }
+}
diff --git a/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/ECU.java b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/ECU.java
new file mode 100644
index 0000000..ca8fe3c
--- /dev/null
+++ b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/ECU.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.google.android.car.diagnostictools;
+
+import android.content.Context;
+
+import com.google.android.car.diagnostictools.utils.MetadataProcessing;
+import com.google.android.car.diagnostictools.utils.SelectableRowModel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Model which wraps ECU data (address, name, and associated DTCs) and extends SelectableRowModel to
+ * enable the selection of ECU elements.
+ */
+public class ECU extends SelectableRowModel {
+
+ private String mAddress;
+ private String mName;
+ /**
+ * MUST be locked when integrating DTC properties to prevent issues with parallel adding and
+ * deleting.
+ */
+ private List<DTC> mDtcs;
+
+ /**
+ * Full constructor that creates an ECU model with its address, name, and list of associated
+ * DTCs.
+ *
+ * @param address Address for ECU
+ * @param name Human readable name for ECU
+ * @param dtcs List of DTCs that are raised by the ECU
+ */
+ private ECU(String address, String name, List<DTC> dtcs) {
+ mAddress = address;
+ mName = name;
+ this.mDtcs = dtcs;
+ }
+
+ /**
+ * Paired down constructor that creates an ECU based on its address, list of associated DTCs,
+ * and metadata.
+ *
+ * @param address Address for ECU
+ * @param dtcs List of DTCs that are raised by the ECU
+ * @param context Context from which this is called. Required to allow MetadataProcessing to be
+ * loaded if the singleton has not been instantiated
+ */
+ public ECU(String address, List<DTC> dtcs, Context context) {
+ mAddress = address;
+ this.mDtcs = dtcs;
+ String metadata = MetadataProcessing.getInstance(context).getECUMetadata(address);
+ if (metadata != null) {
+ this.mName = metadata;
+ } else {
+ this.mName = "No Name Available";
+ }
+ }
+
+ public String getAddress() {
+ return mAddress;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public List<DTC> getDtcs() {
+ return mDtcs;
+ }
+
+ /**
+ * Create sample DTC using MetadataProcessing for values. Some numbers will not return actual
+ * values and will be replaced with placeholder information that would be presented if metadata
+ * wasn't found.
+ *
+ * @param number Used to generate the DTC code which will be "P(008+number)"
+ * @param context Context from which this is called. Required to allow MetadataProcessing to be
+ * loaded if the singleton has not been instantiated
+ * @return New sample DTC based on number and metadata
+ */
+ static ECU createSampleECU(int number, Context context) {
+ List<DTC> dtcs = new ArrayList<>();
+ String address = (number + 123) + "";
+
+ ECU rtrECU = new ECU(address, dtcs, context);
+
+ for (int i = 0; i < number; i++) {
+ dtcs.add(DTC.createSampleDTC(i, context));
+ }
+ return rtrECU;
+ }
+
+ /**
+ * Implement method of SelectableRowModel. The number of elements selected is based on the
+ * number of elements in its children
+ *
+ * @return Returns the number of DTCs that are its children (as DTC is the based element)
+ */
+ @Override
+ public int numSelected() {
+ int count = 0;
+ for (DTC dtc : mDtcs) {
+ count += dtc.numSelected();
+ }
+ return count;
+ }
+
+ /** Runs the implemented delete method in the DTC model to delete records on a VHAL level */
+ @Override
+ public void delete() {
+ for (DTC dtc : mDtcs) {
+ dtc.delete();
+ }
+ }
+}
diff --git a/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/ECUAdapter.java b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/ECUAdapter.java
new file mode 100644
index 0000000..e8eda50
--- /dev/null
+++ b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/ECUAdapter.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.google.android.car.diagnostictools;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Parcelable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+
+import com.google.android.car.diagnostictools.utils.SelectableAdapter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** Adapter for RecyclerView in ECUListActivity which displays ECUs */
+public class ECUAdapter extends SelectableAdapter<ECU, RowViewHolder> {
+
+ private List<ECU> mEcuOrderedList;
+ private Context mContext;
+
+ public ECUAdapter(List<ECU> ecusIn, Context context) {
+ mEcuOrderedList = ecusIn;
+ mContext = context;
+ mEcuOrderedList.sort((ecu, t1) -> t1.getDtcs().size() - ecu.getDtcs().size());
+ }
+
+ @NonNull
+ @Override
+ public RowViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+
+ View v = inflater.inflate(R.layout.row_layout, parent, false);
+
+ return new RowViewHolder(v, true, false, true);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull RowViewHolder holder, final int position) {
+ final ECU refECU = mEcuOrderedList.get(position);
+ final RowViewHolder finalHolder = holder;
+ final String name = refECU.getName();
+ refECU.setColor(finalHolder);
+ holder.setFields(
+ refECU.getAddress(), name, String.format("%d DTCs", refECU.getDtcs().size()),
+ false);
+ holder.layout.setOnClickListener(
+ view -> {
+ if (hasSelected()) {
+ toggleSelect(refECU);
+ refECU.setColor(finalHolder);
+ } else {
+ Intent intent = new Intent(mContext, DTCListActivity.class);
+ intent.putExtra("name", name);
+ intent.putParcelableArrayListExtra(
+ "dtcs", (ArrayList<? extends Parcelable>) refECU.getDtcs());
+ mContext.startActivity(intent);
+ }
+ });
+ holder.layout.setOnLongClickListener(
+ view -> {
+ toggleSelect(refECU);
+ refECU.setColor(finalHolder);
+ return true;
+ });
+ }
+
+ @Override
+ public int getItemCount() {
+ return mEcuOrderedList.size();
+ }
+
+ /**
+ * Overrides method getBaseList of SelectableAdapter to allow selection of elements
+ *
+ * @return base list of DTCs
+ */
+ @Override
+ protected List<ECU> getBaseList() {
+ return mEcuOrderedList;
+ }
+}
diff --git a/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/ECUListActivity.java b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/ECUListActivity.java
new file mode 100644
index 0000000..a2ee70b
--- /dev/null
+++ b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/ECUListActivity.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.google.android.car.diagnostictools;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Toolbar;
+
+import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** Displays a list of ECUs */
+public class ECUListActivity extends Activity {
+
+ private RecyclerView mRecyclerView;
+ private ECUAdapter mAdapter;
+ private RecyclerView.LayoutManager mLayoutManager;
+ private Toolbar mToolbar;
+
+ /** Called with the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ View view = getLayoutInflater().inflate(R.layout.diagnostic_tools, null);
+ setContentView(view);
+
+ mRecyclerView = findViewById(R.id.my_recycler_view);
+
+ mRecyclerView.setHasFixedSize(true);
+
+ mLayoutManager = new LinearLayoutManager(this);
+ mRecyclerView.setLayoutManager(mLayoutManager);
+ List<ECU> input = new ArrayList<>();
+ for (int i = 0; i < 100; i++) {
+ input.add(ECU.createSampleECU(i, this));
+ }
+ mAdapter = new ECUAdapter(input, this);
+ mRecyclerView.setAdapter(mAdapter);
+ mRecyclerView.addItemDecoration(
+ new DividerItemDecoration(
+ mRecyclerView.getContext(), DividerItemDecoration.VERTICAL));
+
+ mToolbar = findViewById(R.id.toolbar);
+ setActionBar(mToolbar);
+ mToolbar.setNavigationIcon(R.drawable.ic_show_chart_black_24dp);
+ mToolbar.setTitle("ECU Overview");
+ final Context mContext = this;
+ mToolbar.setNavigationOnClickListener(
+ view1 -> {
+ Intent intent = new Intent(mContext, LiveDataActivity.class);
+ mContext.startActivity(intent);
+ });
+ }
+
+ /**
+ * Handle clicks from the ActionButton. Confirms that the user wants to clear selected DTCs and
+ * then deletes them on confirmation.
+ */
+ public void onClickActionButton(View view) {
+ new AlertDialog.Builder(this)
+ .setTitle("Clear DTCs")
+ .setMessage(
+ String.format(
+ "Do you really want to clear %d mDtcs?", mAdapter.numSelected()))
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setPositiveButton(
+ android.R.string.yes, (dialog, whichButton) -> mAdapter.deleteSelected())
+ .setNegativeButton(android.R.string.no, null)
+ .show();
+ }
+}
diff --git a/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/LiveDataActivity.java b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/LiveDataActivity.java
new file mode 100644
index 0000000..d985603
--- /dev/null
+++ b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/LiveDataActivity.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.google.android.car.diagnostictools;
+
+import android.app.Activity;
+import android.car.Car;
+import android.car.diagnostic.CarDiagnosticEvent;
+import android.car.diagnostic.CarDiagnosticManager;
+import android.car.diagnostic.FloatSensorIndex;
+import android.car.diagnostic.IntegerSensorIndex;
+import android.car.hardware.property.CarPropertyManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Toast;
+import android.widget.Toolbar;
+
+import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.LayoutManager;
+
+import com.google.android.car.diagnostictools.utils.MetadataProcessing;
+import com.google.android.car.diagnostictools.utils.SensorMetadata;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LiveDataActivity extends Activity {
+ private static final String TAG = "LiveDataActivity";
+
+ private Car mCar;
+ private MetadataProcessing mMetadataProcessing;
+ private RecyclerView mRecyclerView;
+ private LayoutManager mLayoutManager;
+ private LiveDataAdapter mAdapter;
+
+ /**
+ * Convert CarDiagnosticEvent into a list of SensorDataWrapper objects to be displayed
+ *
+ * @param event CarDiagnosticEvent with live(freeze) frame data in it.
+ * @param mMetadataProcessing MetadataProcessing object to associate sensor data with
+ * @return List of LiveDataWrappers to be displayed
+ */
+ static List<LiveDataAdapter.SensorDataWrapper> processSensorInfoIntoWrapper(
+ CarDiagnosticEvent event, MetadataProcessing mMetadataProcessing) {
+ List<LiveDataAdapter.SensorDataWrapper> sensorData = new ArrayList<>();
+ for (int i = 0; i <= FloatSensorIndex.LAST_SYSTEM; i++) {
+ Float sensor_value = event.getSystemFloatSensor(i);
+ if (sensor_value != null) {
+ SensorMetadata metadata = mMetadataProcessing.getFloatMetadata(i);
+ if (metadata != null) {
+ Log.d(TAG, "Float metadata" + metadata.toString());
+ sensorData.add(metadata.toLiveDataWrapper(sensor_value));
+ } else {
+ sensorData.add(
+ new LiveDataAdapter.SensorDataWrapper(
+ "Float Sensor " + i, "", sensor_value));
+ }
+ }
+ }
+ for (int i = 0; i <= IntegerSensorIndex.LAST_SYSTEM; i++) {
+ Integer sensor_value = event.getSystemIntegerSensor(i);
+ if (sensor_value != null) {
+ SensorMetadata metadata = mMetadataProcessing.getIntegerMetadata(i);
+ if (metadata != null) {
+ Log.d(TAG, "Sensor metadata" + metadata.toString());
+ sensorData.add(metadata.toLiveDataWrapper(sensor_value));
+ } else {
+ sensorData.add(
+ new LiveDataAdapter.SensorDataWrapper(
+ "Integer Sensor " + i, "", sensor_value));
+ }
+ }
+ }
+ return sensorData;
+ }
+
+ /**
+ * Overloaded version of processSensorInfoIntoWrapper that uses the metadata member variable
+ *
+ * @param event CarDiagnosticEvent with live(freeze) frame data in it.
+ * @return List of LiveDataWrappers to be displayed
+ */
+ private List<LiveDataAdapter.SensorDataWrapper> processSensorInfoIntoWrapper(
+ CarDiagnosticEvent event) {
+ return processSensorInfoIntoWrapper(event, mMetadataProcessing);
+ }
+
+ /** Called with the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ View view = getLayoutInflater().inflate(R.layout.activity_live_data, null);
+ setContentView(view);
+
+ mCar = Car.createCar(this);
+ mMetadataProcessing = MetadataProcessing.getInstance(this);
+
+ CarDiagnosticManager diagnosticManager =
+ (CarDiagnosticManager) mCar.getCarManager(Car.DIAGNOSTIC_SERVICE);
+
+ CarDiagnosticListener listener = new CarDiagnosticListener(diagnosticManager);
+
+ if (diagnosticManager != null && diagnosticManager.isLiveFrameSupported()) {
+ diagnosticManager.registerListener(
+ listener,
+ CarDiagnosticManager.FRAME_TYPE_LIVE,
+ (int) CarPropertyManager.SENSOR_RATE_NORMAL);
+ } else if (diagnosticManager == null) {
+ Toast.makeText(this, "Error reading manager, please reload", Toast.LENGTH_LONG).show();
+ } else if (!diagnosticManager.isLiveFrameSupported()) {
+ Toast.makeText(this, "Live Frame data not supported", Toast.LENGTH_LONG).show();
+ }
+
+ Toolbar toolbar = findViewById(R.id.toolbar);
+ setActionBar(toolbar);
+ toolbar.setNavigationIcon(R.drawable.ic_arrow_back_black_24dp);
+ toolbar.setNavigationOnClickListener(view1 -> finish());
+
+ mRecyclerView = findViewById(R.id.live_data_list);
+
+ mRecyclerView.setHasFixedSize(false);
+
+ mLayoutManager = new LinearLayoutManager(this);
+ mRecyclerView.setLayoutManager(mLayoutManager);
+ mAdapter = new LiveDataAdapter();
+ mRecyclerView.setAdapter(mAdapter);
+ mRecyclerView.addItemDecoration(
+ new DividerItemDecoration(
+ mRecyclerView.getContext(), DividerItemDecoration.VERTICAL));
+ }
+
+ /** Listener which updates live frame data when it is available */
+ private class CarDiagnosticListener implements CarDiagnosticManager.OnDiagnosticEventListener {
+
+ private final CarDiagnosticManager mManager;
+
+ CarDiagnosticListener(CarDiagnosticManager manager) {
+ this.mManager = manager;
+ }
+
+ @Override
+ public void onDiagnosticEvent(CarDiagnosticEvent event) {
+ if (mManager.isLiveFrameSupported()) {
+ mAdapter.update(processSensorInfoIntoWrapper(event));
+ }
+ }
+ }
+}
diff --git a/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/LiveDataAdapter.java b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/LiveDataAdapter.java
new file mode 100644
index 0000000..7127052
--- /dev/null
+++ b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/LiveDataAdapter.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.google.android.car.diagnostictools;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** Adapter which displays live data */
+public class LiveDataAdapter extends RecyclerView.Adapter<RowViewHolder> {
+
+ private List<SensorDataWrapper> mLiveData;
+
+ public LiveDataAdapter(List<SensorDataWrapper> initialData) {
+ mLiveData = initialData;
+ }
+
+ public LiveDataAdapter() {
+ mLiveData = new ArrayList<>();
+ }
+
+ @NonNull
+ @Override
+ public RowViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+
+ View v = inflater.inflate(R.layout.row_layout, parent, false);
+
+ return new RowViewHolder(v, false, false, true);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull RowViewHolder holder, int position) {
+ SensorDataWrapper wrapper = mLiveData.get(position);
+ holder.setFields(wrapper.mName, "", "" + wrapper.mNumber + " " + wrapper.mUnit, false);
+ }
+
+ @Override
+ public int getItemCount() {
+ return mLiveData.size();
+ }
+
+ /**
+ * Takes in new data to update the RecyclerView with
+ *
+ * @param data New list of LiveDataWrappers to display
+ */
+ public void update(List<SensorDataWrapper> data) {
+ mLiveData.clear();
+ mLiveData.addAll(data);
+ notifyDataSetChanged();
+ }
+
+ /** Wrapper which holds data about a DataFrame */
+ public static class SensorDataWrapper {
+
+ private String mName;
+ private String mUnit;
+ private String mNumber;
+
+ public SensorDataWrapper(String name, String unit, float number) {
+ this.mName = name;
+ this.mUnit = unit;
+ this.mNumber = String.valueOf(number);
+ }
+
+ public SensorDataWrapper(String name, String unit, String number) {
+ this.mName = name;
+ this.mUnit = unit;
+ this.mNumber = number;
+ }
+ }
+}
diff --git a/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/RowViewHolder.java b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/RowViewHolder.java
new file mode 100644
index 0000000..3e83f06
--- /dev/null
+++ b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/RowViewHolder.java
@@ -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.
+ */
+
+package com.google.android.car.diagnostictools;
+
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+/** Generic ViewHolder which is used to represent data in rows. */
+public class RowViewHolder extends RecyclerView.ViewHolder {
+
+ public TextView textHeader;
+ public TextView textDescription;
+ public TextView textValueField;
+ public CheckBox checkBox;
+ public View layout;
+
+ public RowViewHolder(@NonNull View itemView) {
+ super(itemView);
+ layout = itemView;
+ textHeader = itemView.findViewById(R.id.firstLine);
+ textDescription = itemView.findViewById(R.id.secondLine);
+ textValueField = itemView.findViewById(R.id.dtc_number);
+ checkBox = itemView.findViewById(R.id.checkBox);
+ }
+
+ /**
+ * Full constructor which allows selective displaying of description, checkbox, and value
+ * fields.
+ *
+ * @param itemView View to construct on
+ * @param showDescription Display description if true, remove from view (View.GONE) if false
+ * @param showCheckBox Display checkBox if true, remove from view (View.GONE) if false
+ * @param showValue Display value if true, remove from view (View.GONE) if false
+ */
+ public RowViewHolder(
+ @NonNull View itemView,
+ boolean showDescription,
+ boolean showCheckBox,
+ boolean showValue) {
+ this(itemView);
+ checkBox.setVisibility(showCheckBox ? View.VISIBLE : View.GONE);
+ textValueField.setVisibility(showValue ? View.VISIBLE : View.GONE);
+ textDescription.setVisibility(showDescription ? View.VISIBLE : View.GONE);
+ }
+
+ /**
+ * Set values of elements inside the view.
+ *
+ * @param header Header value to display
+ * @param description Description value to display
+ * @param valueField Value to display on the right side
+ * @param chbx Whether or not the checkbox is checked
+ */
+ public void setFields(String header, String description, String valueField, boolean chbx) {
+ textHeader.setText(header);
+ textDescription.setText(description);
+ textValueField.setText(valueField);
+ checkBox.setChecked(chbx);
+ }
+}
diff --git a/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/DTCMetadata.java b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/DTCMetadata.java
new file mode 100644
index 0000000..8071365
--- /dev/null
+++ b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/DTCMetadata.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.google.android.car.diagnostictools.utils;
+
+import android.text.Html;
+import android.text.Spanned;
+import android.util.Log;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/** Holds metadata for a DTC. The intended use case is to map this to a DTC code. */
+public class DTCMetadata {
+
+ private static final String TAG = "DTCMetadata";
+ private static final String SHORT_DESCRIPTION_KEY = "short_description";
+ private static final String LONG_DESCRIPTION_KEY = "long_description";
+
+ private String mShortDescription;
+ private String mStringLongDescription;
+ private Spanned mSpannedLongDescription;
+
+ /**
+ * Creates new DTCMeta data object. Both the String and Spanned version of the longDescription
+ * are stored to allow for the object to be parcelable (String is used) and allow only one call
+ * to Html.fromHTML (Spanned is used)
+ *
+ * @param shortDescription Main description of 50 characters or less
+ * @param longDescription Longer description that can be in HTML format to allow for more
+ * complex formatting.
+ */
+ private DTCMetadata(String shortDescription, String longDescription) {
+ this.mShortDescription = shortDescription;
+ this.mStringLongDescription = longDescription;
+ this.mSpannedLongDescription = Html.fromHtml(longDescription, 0);
+ }
+
+ /**
+ * Build a DTCmeta object from a JSON object. Used by JsonMetadataReader
+ *
+ * @param jsonObject JSONObject that contains both a "short_description" key and a
+ * "long_description" key
+ * @return New DTCMetadata object if successful or null if not
+ */
+ static DTCMetadata buildFromJson(JSONObject jsonObject) {
+ try {
+ return new DTCMetadata(
+ jsonObject.getString(SHORT_DESCRIPTION_KEY),
+ jsonObject.getString(LONG_DESCRIPTION_KEY));
+ } catch (JSONException e) {
+ Log.d(
+ TAG,
+ "DTC JSON Object doesn't match expected format: "
+ + jsonObject.toString()
+ + " Error: "
+ + e.toString());
+ return null;
+ }
+ }
+
+ public String getShortDescription() {
+ return mShortDescription;
+ }
+
+ public Spanned getSpannedLongDescription() {
+ return mSpannedLongDescription;
+ }
+
+ public String getStringLongDescription() {
+ return mStringLongDescription;
+ }
+}
diff --git a/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/JsonMetadataReader.java b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/JsonMetadataReader.java
new file mode 100644
index 0000000..3ce3e66
--- /dev/null
+++ b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/JsonMetadataReader.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.google.android.car.diagnostictools.utils;
+
+import android.car.diagnostic.FloatSensorIndex;
+import android.car.diagnostic.IntegerSensorIndex;
+import android.util.Log;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.Field;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Takes in an InputStream of a JSON file and converts it into a mapping from Integer (SensorIndex
+ * IntDef) to a SensorMetadata object
+ *
+ * <p>Two similar methods used are read(Float|Integer)SensorIndexFromJson. These utilize the
+ * (Float|Integer)SensorIndex.class objects to allow the JSON object to utilize @IntDef variable
+ * names.
+ *
+ * <p>Additionally two similar methods are read(DTCs|ECUs)FromJson which take in an input stream and
+ * return a mapping between DTCs/ECUs and their respective metadata (DTCMetadata or String
+ * respectively)
+ */
+class JsonMetadataReader {
+
+ private static final String TAG = "JsonMetadataReader";
+
+ /**
+ * Converts a JSON file with DTC -> DTCMetadata formatting into the corresponding mapping
+ *
+ * @param in InputStream for JSON file
+ * @return Mapping from String to SensorMetadata
+ * @throws IOException Thrown if there is an issue with reading the file from the InputStream
+ * @throws JSONException Thrown if the JSON object is malformed
+ */
+ static Map<String, DTCMetadata> readDTCsFromJson(InputStream in)
+ throws IOException, JSONException {
+ JSONObject metadataMapping = new JSONObject(inputStreamToString(in));
+ Map<String, DTCMetadata> metadata = new HashMap<>();
+ for (String dtc : metadataMapping.keySet()) {
+ try {
+ metadata.put(dtc, DTCMetadata.buildFromJson(metadataMapping.getJSONObject(dtc)));
+ } catch (JSONException e) {
+ Log.d(TAG, "Invalid JSON for DTC: " + dtc);
+ }
+ }
+ return metadata;
+ }
+
+ /**
+ * Converts a JSON file with ECU -> String formatting into the corresponding mapping
+ *
+ * @param in InputStream for JSON file
+ * @return Mapping from String to SensorMetadata
+ * @throws IOException Thrown if there is an issue with reading the file from the InputStream
+ * @throws JSONException Thrown if the JSON object is malformed
+ */
+ static Map<String, String> readECUsFromJson(InputStream in) throws IOException, JSONException {
+ JSONObject metadataMapping = new JSONObject(inputStreamToString(in));
+ Map<String, String> metadata = new HashMap<>();
+ for (String address : metadataMapping.keySet()) {
+ try {
+ metadata.put(address, metadataMapping.getString(address));
+ } catch (JSONException e) {
+ Log.d(TAG, "Invalid JSON for ECU: " + address);
+ }
+ }
+
+ return metadata;
+ }
+
+ /**
+ * Takes an InputStream of JSON and converts it to a mapping from FloatSensorIndex field value
+ * to Sensor Metadata objects
+ *
+ * @param in InputStream of JSON
+ * @return Mapping from FloatSensorIndex field values to SensorMetadata objects
+ * @throws IOException Thrown if there is an issue with reading the file from the InputStream
+ * @throws JSONException Thrown if the JSON object is malformed
+ */
+ static Map<Integer, SensorMetadata> readFloatSensorIndexFromJson(InputStream in)
+ throws IOException, JSONException {
+ return readSensorIndexFromJson(in, FloatSensorIndex.class);
+ }
+
+ /**
+ * Takes an InputStream of JSON and converts it to a mapping from IntegerSensorIndex field value
+ * to Sensor Metadata objects
+ *
+ * @param in InputStream of JSON
+ * @return Mapping from IntegerSensorIndex field values to SensorMetadata objects
+ * @throws IOException Thrown if there is an issue with reading the file from the InputStream
+ * @throws JSONException Thrown if the JSON object is malformed
+ */
+ static Map<Integer, SensorMetadata> readIntegerSensorIndexFromJson(InputStream in)
+ throws IOException, JSONException {
+ return readSensorIndexFromJson(in, IntegerSensorIndex.class);
+ }
+
+ /**
+ * Takes an InputStream and Class to read in as a SensorIndex. The Class is used to connect with
+ * reflections and assert that key names are consistent with the SensorIndex class input
+ *
+ * @param in InputStream of JSON file
+ * @param sensorIndexClass Defines which of the (Float|Integer)SensorIndex classes does the key
+ * for the output mapping link to
+ * @return Mapping from sensorIndexClass field values to SensorMetadata objects
+ * @throws IOException Thrown if there is an issue with reading the file from the InputStream
+ * @throws JSONException Thrown if the JSON object is malformed
+ */
+ private static Map<Integer, SensorMetadata> readSensorIndexFromJson(
+ InputStream in, Class sensorIndexClass) throws IOException, JSONException {
+ Map<String, SensorMetadata> metadata = JsonMetadataReader.readSensorsFromJson(in);
+ Map<Integer, SensorMetadata> metadataMap = new HashMap<>();
+ // Use Reflection to get all fields of the specified sensorIndexClass
+ Field[] sensorIndexFields = sensorIndexClass.getFields();
+ // For all fields, if the JSON object contains the field then put it into the map
+ for (Field f : sensorIndexFields) {
+ if (metadata.containsKey(f.getName())) {
+ try {
+ metadataMap.put((Integer) f.get(sensorIndexClass), metadata.get(f.getName()));
+ } catch (IllegalAccessException e) { // Added for safety though should never
+ // trigger
+ Log.e(TAG, "Illegal Access Exception throws but should not be thrown");
+ }
+ }
+ }
+ return metadataMap;
+ }
+
+ /**
+ * Helper method that creates an unchecked String to SensorMetadata mapping from an InputStream
+ *
+ * @param in InputStream for JSON file
+ * @return Mapping from String to SensorMetadata
+ * @throws IOException Thrown if there is an issue with reading the file from the InputStream
+ * @throws JSONException Thrown if the JSON object is malformed
+ */
+ private static Map<String, SensorMetadata> readSensorsFromJson(InputStream in)
+ throws IOException, JSONException {
+ JSONObject metadataMapping = new JSONObject(inputStreamToString(in));
+ Map<String, SensorMetadata> metadata = new HashMap<>();
+ for (String sensorIndex : metadataMapping.keySet()) {
+ // Use a static method from SensorMetadata to handle the conversion from
+ // JSON->SensorMetadata
+ metadata.put(
+ sensorIndex,
+ SensorMetadata.buildFromJson(metadataMapping.getJSONObject(sensorIndex)));
+ }
+ return metadata;
+ }
+
+ /**
+ * Converts an InputStream into a String
+ *
+ * @param in InputStream
+ * @return InputStream converted to a String
+ * @throws IOException Thrown if there are issues in reading the file
+ */
+ private static String inputStreamToString(InputStream in) throws IOException {
+ StringBuilder builder = new StringBuilder();
+ try (BufferedReader reader =
+ new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
+ reader.lines().forEach(builder::append);
+ }
+ return builder.toString();
+ }
+}
diff --git a/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/MathEval.java b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/MathEval.java
new file mode 100644
index 0000000..11910df
--- /dev/null
+++ b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/MathEval.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.google.android.car.diagnostictools.utils;
+
+/**
+ * This class allows for custom formulas to translate input live/freeze frame data into the
+ * appropriate values. Ideally a `conversion` object should be used in the JSON but this allows for
+ * more flexibility if needed.
+ */
+class MathEval {
+
+ /**
+ * This is a sanity check for user generated strings to catch errors once instead of everytime
+ * the data is translated
+ *
+ * @param str Translation string to test
+ * @return True if the string doesn't or won't fail when processing simple inputs
+ */
+ static boolean testTranslation(final String str) {
+ if (str == null || str.length() == 0) {
+ return true;
+ } else if (str.length() > 50) {
+ return false;
+ }
+
+ try {
+ eval(str, (float) 100.0);
+ eval(str, (float) 10.0);
+ eval(str, (float) 1);
+ eval(str, (float) .1);
+ eval(str, (float) 0);
+ eval(str, (float) -100.0);
+ eval(str, (float) -10.0);
+ eval(str, (float) -1);
+ eval(str, (float) -.1);
+ } catch (Exception e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Uses a translation string and applies the formula to a variable From
+ * https://stackoverflow.com/a/26227947 with modifications. String must only use +,-,*,/,^,(,)
+ * or "sqrt", "sin", "cos", "tan" (as a function ie sqrt(4)) and the variable x
+ *
+ * @param translationString Translation string which uses x as the variable
+ * @param variableIn Float that the translation is operating on
+ * @return New Float that has gone through operations defined in "translationString". If
+ * translationString is non-operable then the variableIn will be returned
+ * @throws TranslationTooLongException Thrown if the translation string is longer than 50 chars
+ * to prevent long execution times
+ */
+ static double eval(final String translationString, Float variableIn)
+ throws TranslationTooLongException {
+
+ if (translationString == null || translationString.length() == 0) {
+ return variableIn;
+ } else if (translationString.length() > 50) {
+ throw new TranslationTooLongException(
+ "Translation function " + translationString + " is too long");
+ }
+
+ return new Object() {
+ int mPos = -1, mCh;
+
+ void nextChar() {
+ mCh = (++mPos < translationString.length()) ? translationString.charAt(mPos) : -1;
+ }
+
+ boolean eat(int charToEat) {
+ while (mCh == ' ') {
+ nextChar();
+ }
+ if (mCh == charToEat) {
+ nextChar();
+ return true;
+ }
+ return false;
+ }
+
+ double parse() {
+ nextChar();
+ double x = parseExpression();
+ if (mPos < translationString.length()) {
+ throw new RuntimeException("Unexpected: " + (char) mCh);
+ }
+ return x;
+ }
+
+ // Grammar:
+ // expression = term | expression `+` term | expression `-` term
+ // term = factor | term `*` factor | term `/` factor
+ // factor = `+` factor | `-` factor | `(` expression `)`
+ // | number | functionName factor | factor `^` factor
+
+ double parseExpression() {
+ double x = parseTerm();
+ for (;; ) {
+ if (eat('+')) {
+ x += parseTerm(); // addition
+ } else if (eat('-')) {
+ x -= parseTerm(); // subtraction
+ } else {
+ return x;
+ }
+ }
+ }
+
+ double parseTerm() {
+ double x = parseFactor();
+ for (;; ) {
+ if (eat('*')) {
+ x *= parseFactor(); // multiplication
+ } else if (eat('/')) {
+ x /= parseFactor(); // division
+ } else {
+ return x;
+ }
+ }
+ }
+
+ double parseFactor() {
+ if (eat('+')) {
+ return parseFactor(); // unary plus
+ }
+ if (eat('-')) {
+ return -parseFactor(); // unary minus
+ }
+
+ double x;
+ int startPos = this.mPos;
+ if (eat('(')) { // parentheses
+ x = parseExpression();
+ eat(')');
+ } else if ((mCh >= '0' && mCh <= '9') || mCh == '.') { // numbers
+ while ((mCh >= '0' && mCh <= '9') || mCh == '.') {
+ nextChar();
+ }
+ x = Double.parseDouble(translationString.substring(startPos, this.mPos));
+ } else if (mCh == 'x') {
+ x = variableIn;
+ nextChar();
+ // System.out.println(x);
+ } else if (mCh >= 'a' && mCh <= 'z') { // functions
+ while (mCh >= 'a' && mCh <= 'z') {
+ nextChar();
+ }
+ String func = translationString.substring(startPos, this.mPos);
+ x = parseFactor();
+ switch (func) {
+ case "sqrt":
+ x = Math.sqrt(x);
+ break;
+ case "sin":
+ x = Math.sin(Math.toRadians(x));
+ break;
+ case "cos":
+ x = Math.cos(Math.toRadians(x));
+ break;
+ case "tan":
+ x = Math.tan(Math.toRadians(x));
+ break;
+ default:
+ throw new RuntimeException("Unknown function: " + func);
+ }
+ } else {
+ throw new RuntimeException("Unexpected: " + (char) mCh);
+ }
+
+ if (eat('^')) {
+ x = Math.pow(x, parseFactor()); // exponentiation
+ }
+
+ return x;
+ }
+ }.parse();
+ }
+
+ /** Exception thrown if the translation string is too long */
+ static class TranslationTooLongException extends Exception {
+
+ TranslationTooLongException(String errorMsg) {
+ super(errorMsg);
+ }
+ }
+}
diff --git a/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/MetadataProcessing.java b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/MetadataProcessing.java
new file mode 100644
index 0000000..9f36002
--- /dev/null
+++ b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/MetadataProcessing.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.google.android.car.diagnostictools.utils;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.google.android.car.diagnostictools.R;
+
+import org.json.JSONException;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/** Singleton class that contains all available metadata information */
+public class MetadataProcessing {
+
+ private static final String TAG = "MetadataProcessing";
+ private static MetadataProcessing sInstance = null;
+
+ private Map<Integer, SensorMetadata> mFloatMetadata = new HashMap<>();
+ private Map<Integer, SensorMetadata> mIntegerMetadata = new HashMap<>();
+ private Map<String, DTCMetadata> mDTCMetadataMap = new HashMap<>();
+ private Map<String, String> mECUMetadataMap = new HashMap<>();
+
+ /**
+ * Creates a MetadataProcessing object using a context to access files in res/raw
+ *
+ * @param context Any context object. Used to access files in res/raw
+ */
+ private MetadataProcessing(Context context) {
+ // DTC Metadata
+ try {
+ mDTCMetadataMap =
+ JsonMetadataReader.readDTCsFromJson(
+ context.getResources().openRawResource(R.raw.system_dtcs));
+ } catch (IOException | JSONException e) {
+ Log.d(
+ TAG,
+ "Error reading in JSON Metadata for system DTCs. More info: " + e.toString());
+ }
+ try {
+ mDTCMetadataMap.putAll(
+ JsonMetadataReader.readDTCsFromJson(
+ context.getResources().openRawResource(R.raw.vendor_dtcs)));
+ } catch (IOException | JSONException e) {
+ Log.d(
+ TAG,
+ "Error reading in JSON Metadata for vendor DTCs. More info: " + e.toString());
+ }
+
+ // Float Metadata
+ try {
+ mFloatMetadata =
+ JsonMetadataReader.readFloatSensorIndexFromJson(
+ context.getResources().openRawResource(R.raw.system_float_sensors));
+ } catch (IOException | JSONException e) {
+ Log.e(
+ TAG,
+ "Error reading in JSON Metadata for system float sensors. More info: "
+ + e.toString());
+ }
+ try {
+ mFloatMetadata.putAll(
+ JsonMetadataReader.readFloatSensorIndexFromJson(
+ context.getResources().openRawResource(R.raw.vendor_float_sensors)));
+ } catch (IOException | JSONException e) {
+ Log.e(
+ TAG,
+ "Error reading in JSON Metadata for vendor float sensors. More info: "
+ + e.toString());
+ }
+
+ // Integer Metadata
+ try {
+ mIntegerMetadata =
+ JsonMetadataReader.readIntegerSensorIndexFromJson(
+ context.getResources().openRawResource(R.raw.system_integer_sensors));
+ } catch (IOException | JSONException e) {
+ Log.e(
+ TAG,
+ "Error reading in JSON Metadata for system integer sensors. More info: "
+ + e.toString());
+ }
+ try {
+ mIntegerMetadata.putAll(
+ JsonMetadataReader.readIntegerSensorIndexFromJson(
+ context.getResources().openRawResource(R.raw.vendor_integer_sensors)));
+ } catch (IOException | JSONException e) {
+ Log.e(
+ TAG,
+ "Error reading in JSON Metadata for vendor integer sensors. More info: "
+ + e.toString());
+ }
+
+ // ECU Metadata
+ try {
+ mECUMetadataMap =
+ JsonMetadataReader.readECUsFromJson(
+ context.getResources().openRawResource(R.raw.vendor_ecus));
+ } catch (IOException | JSONException e) {
+ Log.e(TAG, "Error reading in JSON Metadata for ECUs. More info: " + e.toString());
+ }
+ }
+
+ /**
+ * Maintains a singleton object and allows access to it. If no singleton object is created the
+ * method will create one based on passed in context
+ *
+ * @param context Any context that allows access to res/raw
+ * @return Singleton MetadataProcessing object
+ */
+ public static synchronized MetadataProcessing getInstance(Context context) {
+ if (sInstance == null) {
+ sInstance = new MetadataProcessing(context);
+ }
+ return sInstance;
+ }
+
+ public SensorMetadata getFloatMetadata(Integer floatSensorIndex) {
+ return mFloatMetadata.getOrDefault(floatSensorIndex, null);
+ }
+
+ public SensorMetadata getIntegerMetadata(Integer integerSensorIndex) {
+ return mIntegerMetadata.getOrDefault(integerSensorIndex, null);
+ }
+
+ public DTCMetadata getDTCMetadata(String dtcCode) {
+ return mDTCMetadataMap.getOrDefault(dtcCode, null);
+ }
+
+ public String getECUMetadata(String ecuAddress) {
+ return mECUMetadataMap.getOrDefault(ecuAddress, null);
+ }
+}
diff --git a/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/SelectableAdapter.java b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/SelectableAdapter.java
new file mode 100644
index 0000000..77deca9
--- /dev/null
+++ b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/SelectableAdapter.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.google.android.car.diagnostictools.utils;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Used to enable a RecyclerView Adapter to select and delete row elements. Designed to be self
+ * contained so that implementing the abstract function will enable selecting behavior.
+ *
+ * @param <M> Base row model used. For example, the `DTC` class is used for the DTCAdapter
+ * @param <VH> Base view holder used. Included so that SelectableAdapter can use
+ * notifyDataSetChanged
+ */
+public abstract class SelectableAdapter<
+ M extends SelectableRowModel, VH extends RecyclerView.ViewHolder>
+ extends RecyclerView.Adapter<VH> {
+
+ private List<M> mSelected = new ArrayList<>();
+
+ /**
+ * Toggle if an element is selected or not.
+ *
+ * @param model The model object that is related to the row selected
+ */
+ public void toggleSelect(M model) {
+ if (model.isSelected()) {
+ model.setSelected(false);
+ mSelected.remove(model);
+ } else {
+ model.setSelected(true);
+ mSelected.add(model);
+ }
+ }
+
+ /**
+ * Returns the number of elements selected. Uses the model's numSelected method to allow for one
+ * model object to represent multiple element (one ECU holds multiple DTCs). If no elements are
+ * explicitly selected, it is assumed that all elements are selected.
+ *
+ * @return number of elements selected
+ */
+ public int numSelected() {
+ int count = 0;
+ for (M model : mSelected) {
+ count += model.numSelected();
+ }
+ if (count == 0) {
+ for (M model : getBaseList()) {
+ count += model.numSelected();
+ }
+ }
+ return count;
+ }
+
+ /**
+ * Deletes all selected element or all elements if no elements are selected. Additionally, calls
+ * the delete methods for all related models.
+ */
+ public void deleteSelected() {
+ if (mSelected.size() == 0) {
+ for (M model : getBaseList()) {
+ model.delete();
+ }
+ getBaseList().clear();
+ } else {
+ for (M model : mSelected) {
+ model.delete();
+ }
+ getBaseList().removeAll(mSelected);
+ mSelected.clear();
+ }
+ notifyDataSetChanged();
+ }
+
+ /**
+ * If there are any models explicitly selected. Does not take into account there are any
+ * elements in that model (an ECU with 0 DTCs).
+ *
+ * @return if there are any models selected
+ */
+ public boolean hasSelected() {
+ return mSelected.size() > 0;
+ }
+
+ /**
+ * Gets base list that the adapter is built off of. This must be one list which the adapter uses
+ * for both order and elements.
+ *
+ * @return base list that adapter is built off of
+ */
+ protected abstract List<M> getBaseList();
+}
diff --git a/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/SelectableRowModel.java b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/SelectableRowModel.java
new file mode 100644
index 0000000..e2675bf
--- /dev/null
+++ b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/SelectableRowModel.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.google.android.car.diagnostictools.utils;
+
+import android.graphics.Color;
+
+import com.google.android.car.diagnostictools.RowViewHolder;
+
+/**
+ * Data model class which ECUs and DTCs extend. Allows those classes to be connected with a
+ * SelectableAdapter to enable a RecyclerView with elements getting selected
+ */
+public abstract class SelectableRowModel {
+
+ /** If model is selected */
+ private boolean mIsSelected;
+
+ boolean isSelected() {
+ return mIsSelected;
+ }
+
+ void setSelected(boolean selected) {
+ mIsSelected = selected;
+ }
+
+ /**
+ * Takes in a RowViewHolder object and sets its layout background to its appropriate color based
+ * on if it is selected or not. Uses hardcoded values for the selected and default backgrounds.
+ *
+ * @param holder RowViewHolder object associated with the model object
+ */
+ public void setColor(RowViewHolder holder) {
+ int color = mIsSelected ? Color.GRAY : Color.parseColor("#303030");
+ holder.layout.setBackgroundColor(color);
+ }
+
+ /**
+ * Get the number of elements selected when this model is selected. If the object has children
+ * which are also selected as a result of this select, then those should be counted in that
+ * number.
+ *
+ * @return number of elements selected
+ */
+ public abstract int numSelected();
+
+ /**
+ * Delete this model and all of its children. This allows the model to run special functions to
+ * delete itself in any other representation (DTCs can be deleted from the VHAL).
+ */
+ public abstract void delete();
+}
diff --git a/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/SensorMetadata.java b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/SensorMetadata.java
new file mode 100644
index 0000000..91425d1
--- /dev/null
+++ b/tests/DiagnosticTools/src/com/google/android/car/diagnostictools/utils/SensorMetadata.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.google.android.car.diagnostictools.utils;
+
+import android.util.Log;
+
+import com.google.android.car.diagnostictools.LiveDataAdapter;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Stores metadata about a sensor and provides methods to better understand the sensor data.
+ * Provides support for arbitrary translation, scaling (conversion) following the format [Scaled
+ * Data Value] = [Offset] + [Scale] x [Raw Decimal Data Value], and mapping from integer to String.
+ */
+public class SensorMetadata {
+
+ private static final String TRANSLATION_KEY = "translation";
+ private static final String NAME_KEY = "name";
+ private static final String UNITS_KEY = "units";
+ private static final String CONVERSION_KEY = "conversion";
+ private static final String MAPPING_KEY = "mapping";
+ private static final String TAG = "SensorMetadata";
+
+ private String mTranslationString;
+ private float mScale;
+ private float mOffset;
+ private String mName;
+ private String mUnits;
+ private Map<Integer, String> mMapping;
+ private boolean mHasConversion;
+ private boolean mHasMapping;
+
+ /**
+ * Takes in arbitrary translation string that should have x in it as a variable, sensor name,
+ * and the sensor data units. For more information view MathEval.eval.
+ *
+ * @param translationString translation string with a 50 character limit. More information on
+ * usage in MathEval.eval.
+ * @param name Name of sensor.
+ * @param units Units of the sensor's data.
+ */
+ private SensorMetadata(String translationString, String name, String units) {
+ if (MathEval.testTranslation(translationString)) {
+ this.mTranslationString = translationString;
+ } else {
+ Log.e(
+ "ServiceCenterTools",
+ String.format(
+ "Invalid translation string %s for sensor %s because tests failed",
+ translationString, name));
+ this.mTranslationString = "";
+ }
+ this.mName = name;
+ this.mUnits = units;
+ this.mHasConversion = false;
+ this.mHasMapping = false;
+ }
+
+ /**
+ * Takes in float scale and offset values, sensor name, and the sensor data units. Scaling and
+ * mOffset are used in the following format: [Scaled Data Value] = [Offset] + [Scale] x [Raw
+ * Decimal Data Value].
+ *
+ * @param scale Value to mScale sensor data by.
+ * @param offset Value to shift sensor data by.
+ * @param name Name of sensor.
+ * @param units Units of the sensor's data.
+ */
+ private SensorMetadata(float scale, float offset, String name, String units) {
+ this.mScale = scale;
+ this.mOffset = offset;
+ this.mName = name;
+ this.mUnits = units;
+ this.mHasConversion = true;
+ this.mHasMapping = false;
+ }
+
+ /**
+ * Takes in a Integer -> String mapping and sensor mName.
+ *
+ * @param mapping Mapping between Integer sensor values to their String values
+ * @param name Name of sensor.
+ */
+ private SensorMetadata(Map<Integer, String> mapping, String name) {
+ this.mMapping = mapping;
+ this.mName = name;
+ this.mUnits = "";
+ this.mHasMapping = true;
+ this.mHasConversion = false;
+ }
+
+ /**
+ * Takes in json object which represents the metadata for a single sensor and converts it to a
+ * SensorMetadata object. Supports mappings, structured conversions (mScale and mOffset), and
+ * arbitrary translations. Mappings and conversions are preferred and translation read in if
+ * neither are present.
+ *
+ * @param json JSON object for metadata
+ * @return returns a new SensorMeta data object with the data from the JSON object
+ */
+ static SensorMetadata buildFromJson(JSONObject json) {
+ String name = readStringFromJSON(NAME_KEY, json);
+ String units = readStringFromJSON(UNITS_KEY, json);
+
+ if (json.has(CONVERSION_KEY)) {
+ try {
+ JSONObject conversionObject = json.getJSONObject(CONVERSION_KEY);
+ float scale = readFloatFromJSON("scale", conversionObject);
+ float offset = readFloatFromJSON("offset", conversionObject);
+
+ return new SensorMetadata(scale, offset, name, units);
+ } catch (JSONException e) {
+ Log.d(TAG, "buildFromJson: Error reading conversion for " + name + ": " + e);
+ }
+ } else if (json.has(MAPPING_KEY)) {
+ try {
+ Map<Integer, String> mapping = readMappingFromJSON(MAPPING_KEY, json);
+ return new SensorMetadata(mapping, name);
+ } catch (JSONException e) {
+ Log.d(TAG, "buildFromJson: Error reading mapping: " + e);
+ }
+ }
+ String translationString = readStringFromJSON(TRANSLATION_KEY, json);
+
+ return new SensorMetadata(translationString, name, units);
+ }
+
+ /**
+ * Helper function that reads a string at a certain key from a JSONObject. Function wraps the
+ * JSON functions with appropriate exception handling.
+ *
+ * @param key key at which the desired string value is located
+ * @param json JSONObject that has the string value at the key
+ * @return value at key or null if error or not found
+ */
+ private static String readStringFromJSON(String key, JSONObject json) {
+ try {
+ if (json.has(key)) {
+ return json.getString(key);
+ }
+ } catch (JSONException e) {
+ Log.e(TAG, "Error reading " + key + " for String SensorMetadata");
+ }
+ return "";
+ }
+
+ /**
+ * Helper function that reads a float at a certain key from a JSONObject. Function wraps the
+ * JSON functions with appropriate exception handling.
+ *
+ * @param key key at which the desired float value is located
+ * @param json JSONObject that has the float value at the key
+ * @return value at key or null if error or not found
+ * @throws JSONException Throws JSONException if there is any
+ */
+ private static float readFloatFromJSON(String key, JSONObject json) throws JSONException {
+ try {
+ if (json.has(key)) {
+ return (float) json.getDouble(key);
+ } else {
+ Log.e(TAG, "No tag for " + key + " is found");
+ throw new JSONException(String.format("%s missing from object", key));
+ }
+ } catch (JSONException e) {
+ Log.e(TAG, "Error reading " + key + " for float SensorMetadata");
+ throw e;
+ }
+ }
+
+ /**
+ * Helper function that reads a mapping at a certain key from a JSONObject. Function wraps the
+ * JSON functions with appropriate exception handling.
+ *
+ * @param key key at which the desired float value is located
+ * @param json JSONObject that has the float value at the key
+ * @return value at key or null if error or not found
+ * @throws JSONException Throws JSONException if there is any
+ */
+ private static Map<Integer, String> readMappingFromJSON(String key, JSONObject json)
+ throws JSONException {
+ try {
+ if (json.has(key)) {
+ json = json.getJSONObject(key);
+ Map<Integer, String> map = new HashMap<>();
+ Iterator<String> keys = json.keys();
+
+ while (keys.hasNext()) {
+ String integer = keys.next();
+ if (json.get(integer) instanceof String && isInteger(integer)) {
+ map.put(Integer.parseInt(integer), json.getString(integer));
+ }
+ }
+ return map;
+ } else {
+ Log.e(TAG, "No tag for " + key + " is found");
+ throw new JSONException(String.format("%s missing from object", key));
+ }
+ } catch (JSONException e) {
+ Log.e(TAG, "Error reading " + key + " for mapping SensorMetadata");
+ throw e;
+ }
+ }
+
+ /**
+ * Helper function to quickly check if a String can be converted to an int. From
+ * https://stackoverflow.com/a/237204
+ *
+ * @param str String to check.
+ * @return true if String can be converted to an int, false if not.
+ */
+ private static boolean isInteger(String str) {
+ if (str == null) {
+ return false;
+ }
+ int length = str.length();
+ if (length == 0) {
+ return false;
+ }
+ int i = 0;
+ if (str.charAt(0) == '-') {
+ if (length == 1) {
+ return false;
+ }
+ i = 1;
+ }
+ for (; i < length; i++) {
+ char c = str.charAt(i);
+ if (c < '0' || c > '9') {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Uses appropriate translation method (mapping, conversion, translation string) to convert
+ * float sensor data into true value
+ *
+ * @param data Float of data to translate
+ * @return Processed data
+ */
+ private String translateData(Float data) {
+ if (mHasConversion) {
+ return String.valueOf(data * mScale + mOffset);
+ } else if (mHasMapping) {
+ return mMapping.getOrDefault(Math.round(data), "No mapping available");
+ }
+ try {
+ return String.valueOf((float) MathEval.eval(mTranslationString, data));
+ } catch (MathEval.TranslationTooLongException e) {
+ Log.e("ServiceCenterTools", "Translation: " + mTranslationString + " too long");
+ return String.valueOf(data);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Metadata for "
+ + mName
+ + " with units: "
+ + mUnits
+ + " and translation: "
+ + mTranslationString;
+ }
+
+ /**
+ * Translates and wraps data in a SensorDataWrapper object to allow for it to be displayed
+ *
+ * @param data Sensor data to translate and wrapp
+ * @return SensorDataWrapper that can be displayed in the LiveDataAdapter
+ */
+ public LiveDataAdapter.SensorDataWrapper toLiveDataWrapper(float data) {
+ return new LiveDataAdapter.SensorDataWrapper(mName, mUnits, this.translateData(data));
+ }
+}
diff --git a/tests/DiagnosticTools/tests/Android.mk b/tests/DiagnosticTools/tests/Android.mk
new file mode 100644
index 0000000..8c21035
--- /dev/null
+++ b/tests/DiagnosticTools/tests/Android.mk
@@ -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.
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
+
+LOCAL_STATIC_JAVA_LIBRARIES := junit
+
+LOCAL_PACKAGE_NAME := DiagnosticToolsTests
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_INSTRUMENTATION_FOR := DiagnosticTools
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/tests/DiagnosticTools/tests/AndroidManifest.xml b/tests/DiagnosticTools/tests/AndroidManifest.xml
new file mode 100644
index 0000000..ad451f4
--- /dev/null
+++ b/tests/DiagnosticTools/tests/AndroidManifest.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
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.google.android.car.diagnostictools.tests">
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.example.android.diagnostictools"
+ android:label="DiagnosticTools sample tests">
+ </instrumentation>
+
+</manifest>
diff --git a/tests/DiagnosticTools/tests/build.properties b/tests/DiagnosticTools/tests/build.properties
new file mode 100644
index 0000000..e0c39de
--- /dev/null
+++ b/tests/DiagnosticTools/tests/build.properties
@@ -0,0 +1 @@
+tested.project.dir=..
diff --git a/tests/DiagnosticTools/tests/src/com/google/android/car/diagnostictools/DiagnosticToolsTest.java b/tests/DiagnosticTools/tests/src/com/google/android/car/diagnostictools/DiagnosticToolsTest.java
new file mode 100644
index 0000000..ca26a8f
--- /dev/null
+++ b/tests/DiagnosticTools/tests/src/com/google/android/car/diagnostictools/DiagnosticToolsTest.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.google.android.car.diagnostictools;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ * Make sure that the main launcher activity opens up properly, which will be
+ * verified by {@link #testActivityTestCaseSetUpProperly}.
+ */
+public class DiagnosticToolsTest extends ActivityInstrumentationTestCase2<ECUListActivity> {
+
+ /**
+ * Creates an {@link ActivityInstrumentationTestCase2} for the {@link ECUListActivity} activity.
+ */
+ public DiagnosticToolsTest() {
+ super(ECUListActivity.class);
+ }
+
+ /**
+ * Verifies that the activity under test can be launched.
+ */
+ public void testActivityTestCaseSetUpProperly() {
+ assertNotNull("activity should be launched successfully", getActivity());
+ }
+}
diff --git a/tests/android_car_api_test/Android.mk b/tests/android_car_api_test/Android.mk
index b88ca78..c292542 100644
--- a/tests/android_car_api_test/Android.mk
+++ b/tests/android_car_api_test/Android.mk
@@ -42,4 +42,6 @@
LOCAL_JAVA_LIBRARIES := android.car android.test.runner android.test.base
+LOCAL_COMPATIBILITY_SUITE := general-tests
+
include $(BUILD_PACKAGE)
diff --git a/tests/carservice_test/Android.mk b/tests/carservice_test/Android.mk
index 63f1a4e..33f43df 100644
--- a/tests/carservice_test/Android.mk
+++ b/tests/carservice_test/Android.mk
@@ -60,4 +60,6 @@
LOCAL_JNI_SHARED_LIBRARIES := libdexmakerjvmtiagent
+LOCAL_COMPATIBILITY_SUITE := general-tests
+
include $(BUILD_PACKAGE)
diff --git a/tests/carservice_unit_test/Android.mk b/tests/carservice_unit_test/Android.mk
index dd6ab84..d4df44e 100644
--- a/tests/carservice_unit_test/Android.mk
+++ b/tests/carservice_unit_test/Android.mk
@@ -44,7 +44,8 @@
android.car.userlib \
android.test.runner \
android.test.base \
- android.test.mock
+ android.test.mock \
+ EncryptionRunner
LOCAL_STATIC_JAVA_LIBRARIES := \
androidx.test.core \
@@ -58,8 +59,11 @@
testng \
truth-prebuilt
+LOCAL_COMPATIBILITY_SUITE := general-tests
+
# mockito-target-inline dependency
LOCAL_JNI_SHARED_LIBRARIES := \
libdexmakerjvmtiagent \
+ libstaticjvmtiagent \
include $(BUILD_PACKAGE)
diff --git a/tests/carservice_unit_test/src/android/car/CarTest.java b/tests/carservice_unit_test/src/android/car/CarTest.java
new file mode 100644
index 0000000..91a1ddb
--- /dev/null
+++ b/tests/carservice_unit_test/src/android/car/CarTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.car;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.ServiceManager;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+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.invocation.InvocationOnMock;
+import org.mockito.quality.Strictness;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Unit test for Car API.
+ */
+@RunWith(AndroidJUnit4.class)
+public class CarTest {
+ private static final String TAG = CarTest.class.getSimpleName();
+
+ private MockitoSession mMockingSession;
+
+ @Mock
+ private Context mContext;
+
+ // It is tricky to mock this. So create dummy version instead.
+ private ICar.Stub mService = new ICar.Stub() {
+ @Override
+ public void setCarServiceHelper(android.os.IBinder helper) {
+ }
+
+ @Override
+ public void setUserLockStatus(int userHandle, int unlocked) {
+ }
+
+ @Override
+ public void onSwitchUser(int userHandle) {
+ }
+
+ @Override
+ public android.os.IBinder getCarService(java.lang.String serviceName) {
+ return null;
+ }
+
+ @Override
+ public int getCarConnectionType() {
+ return 0;
+ }
+ };
+
+ @Before
+ public void setUp() {
+ mMockingSession = mockitoSession()
+ .initMocks(this)
+ .mockStatic(ServiceManager.class)
+ .strictness(Strictness.LENIENT)
+ .startMocking();
+ }
+
+ @After
+ public void tearDown() {
+ mMockingSession.finishMocking();
+ }
+
+ private void expectService(@Nullable IBinder service) {
+ doReturn(service).when(
+ () -> ServiceManager.getService(Car.CAR_SERVICE_BINDER_SERVICE_NAME));
+ }
+
+ @Test
+ public void testCreateCarSuccessWithCarServiceRunning() {
+ expectService(mService);
+ assertThat(Car.createCar(mContext)).isNotNull();
+ }
+
+ @Test
+ public void testCreateCarReturnNull() {
+ // car service is not running yet and bindService does not bring the service yet.
+ // createCar should timeout and give up.
+ expectService(null);
+ assertThat(Car.createCar(mContext)).isNull();
+ }
+
+ @Test
+ public void testCreateCarOkWhenCarServiceIsStarted() {
+ // Car service is not running yet and binsService call should start it.
+ when(mContext.bindServiceAsUser(anyObject(), anyObject(), anyInt(),
+ anyObject())).thenReturn(true);
+ final int returnNonNullAfterThisCall = 10;
+ doAnswer(new Answer() {
+
+ private int mCallCount = 0;
+
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ mCallCount++;
+ if (mCallCount > returnNonNullAfterThisCall) {
+ return mService;
+ } else {
+ return null;
+ }
+ }
+ }).when(() -> ServiceManager.getService(Car.CAR_SERVICE_BINDER_SERVICE_NAME));
+ Car car = Car.createCar(mContext);
+ assertThat(car).isNotNull();
+ verify(mContext, times(1)).bindServiceAsUser(anyObject(), anyObject(),
+ anyInt(), anyObject());
+
+ // Just call these to guarantee that nothing crashes when service is connected /
+ // disconnected.
+ car.getServiceConnectionListener().onServiceConnected(new ComponentName("", ""), mService);
+ car.getServiceConnectionListener().onServiceDisconnected(new ComponentName("", ""));
+ }
+}
diff --git a/tests/carservice_unit_test/src/android/car/encryptionrunner/EncryptionRunnerTest.java b/tests/carservice_unit_test/src/android/car/encryptionrunner/EncryptionRunnerTest.java
new file mode 100644
index 0000000..94c397e
--- /dev/null
+++ b/tests/carservice_unit_test/src/android/car/encryptionrunner/EncryptionRunnerTest.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.car.encryptionrunner;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.util.Log;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class EncryptionRunnerTest {
+
+ private Key mClientKey;
+ private Key mServerKey;
+ private byte[] mData = "testData".getBytes();
+
+ private interface RunnerFactory {
+ EncryptionRunner newRunner();
+ }
+
+ @Test
+ public void happyFlow_dummyRunner() throws Exception {
+ verifyRunners(EncryptionRunnerFactory::newDummyRunner);
+ }
+
+ @Test
+ public void happyFlow_ukey2Runner() throws Exception {
+ verifyRunners(EncryptionRunnerFactory::newRunner);
+ }
+
+ @Test
+ public void happyFlow_dummyRunner_reconnect() throws Exception {
+ setUpFirstConnection(EncryptionRunnerFactory::newDummyRunner);
+ verifyRunnersReconnect(EncryptionRunnerFactory::newDummyRunner);
+ }
+
+ @Test
+ public void happyFlow_uKey2Runner_reconnect() throws Exception {
+ setUpFirstConnection(EncryptionRunnerFactory::newRunner);
+ verifyRunnersReconnect(EncryptionRunnerFactory::newRunner);
+ }
+
+ @Test
+ public void uKey2Runner_reconnect_encrypt_and_decrypt() throws Exception {
+ setUpFirstConnection(EncryptionRunnerFactory::newRunner);
+ setUpReconnection(EncryptionRunnerFactory::newRunner);
+ assertThat(mClientKey.decryptData(mServerKey.encryptData(mData))).isEqualTo(mData);
+ }
+
+ @Test
+ public void dummyRunner_reconnect_encrypt_and_decrypt() throws Exception {
+ setUpFirstConnection(EncryptionRunnerFactory::newDummyRunner);
+ setUpReconnection(EncryptionRunnerFactory::newDummyRunner);
+ assertThat(mClientKey.decryptData(mServerKey.encryptData(mData))).isEqualTo(mData);
+ }
+
+ private void setUpFirstConnection(RunnerFactory runnerFactory) throws Exception {
+ EncryptionRunner clientRunner = runnerFactory.newRunner();
+ EncryptionRunner serverRunner = runnerFactory.newRunner();
+ verifyHandshake(clientRunner, serverRunner);
+ HandshakeMessage finalServerMessage = serverRunner.verifyPin();
+ HandshakeMessage finalClientMessage = clientRunner.verifyPin();
+ mServerKey = finalServerMessage.getKey();
+ mClientKey = finalClientMessage.getKey();
+ }
+
+ private void setUpReconnection(RunnerFactory runnerFactory) throws Exception {
+ setUpFirstConnection(runnerFactory);
+ EncryptionRunner clientRunner = runnerFactory.newRunner();
+ EncryptionRunner serverRunner = runnerFactory.newRunner();
+ verifyHandshakeReconnect(clientRunner, serverRunner);
+ HandshakeMessage nextClientMessage =
+ clientRunner.initReconnectAuthentication(mClientKey.asBytes());
+ HandshakeMessage finalServerMessage = serverRunner.authenticateReconnection(
+ nextClientMessage.getNextMessage(), mServerKey.asBytes());
+ HandshakeMessage finalClientMessage = clientRunner.authenticateReconnection(
+ finalServerMessage.getNextMessage(), mServerKey.asBytes());
+ mServerKey = finalServerMessage.getKey();
+ mClientKey = finalClientMessage.getKey();
+ }
+
+ /**
+ * Runs through a happy flow of encryption runners and verifies that they behave as expected.
+ * Some * of the test is implementation specific because the interface doesn't specify how many
+ * round * trips may be needed but this test makes assumptions( i.e. white box testing).
+ */
+ private void verifyRunners(RunnerFactory runnerFactory) throws Exception {
+ EncryptionRunner clientRunner = runnerFactory.newRunner();
+ EncryptionRunner serverRunner = runnerFactory.newRunner();
+
+ verifyHandshake(clientRunner, serverRunner);
+
+ HandshakeMessage finalServerMessage = serverRunner.verifyPin();
+ assertThat(finalServerMessage.getHandshakeState())
+ .isEqualTo(HandshakeMessage.HandshakeState.FINISHED);
+ assertThat(finalServerMessage.getKey()).isNotNull();
+ assertThat(finalServerMessage.getNextMessage()).isNull();
+
+ HandshakeMessage finalClientMessage = clientRunner.verifyPin();
+ assertThat(finalClientMessage.getHandshakeState())
+ .isEqualTo(HandshakeMessage.HandshakeState.FINISHED);
+ assertThat(finalClientMessage.getKey()).isNotNull();
+ assertThat(finalClientMessage.getNextMessage()).isNull();
+
+ assertThat(finalServerMessage.getKey()
+ .decryptData(finalClientMessage.getKey().encryptData(mData)))
+ .isEqualTo(mData);
+ assertThat(finalClientMessage.getKey()
+ .decryptData(finalServerMessage.getKey().encryptData(mData)))
+ .isEqualTo(mData);
+ }
+
+ private void verifyRunnersReconnect(RunnerFactory runnerFactory) throws Exception {
+ EncryptionRunner clientRunner = runnerFactory.newRunner();
+ EncryptionRunner serverRunner = runnerFactory.newRunner();
+ verifyHandshakeReconnect(clientRunner, serverRunner);
+
+ HandshakeMessage nextClientMessage =
+ clientRunner.initReconnectAuthentication(mClientKey.asBytes());
+ assertThat(nextClientMessage.getHandshakeState())
+ .isEqualTo(HandshakeMessage.HandshakeState.RESUMING_SESSION);
+ assertThat(nextClientMessage.getKey()).isNull();
+ assertThat(nextClientMessage.getNextMessage()).isNotNull();
+
+ HandshakeMessage finalServerMessage = serverRunner.authenticateReconnection(
+ nextClientMessage.getNextMessage(), mServerKey.asBytes());
+ assertThat(finalServerMessage.getHandshakeState())
+ .isEqualTo(HandshakeMessage.HandshakeState.FINISHED);
+ assertThat(finalServerMessage.getKey()).isNotNull();
+ assertThat(finalServerMessage.getNextMessage()).isNotNull();
+
+ HandshakeMessage finalClientMessage = clientRunner.authenticateReconnection(
+ finalServerMessage.getNextMessage(), mServerKey.asBytes());
+ assertThat(finalClientMessage.getHandshakeState())
+ .isEqualTo(HandshakeMessage.HandshakeState.FINISHED);
+ assertThat(finalClientMessage.getKey()).isNotNull();
+ assertThat(finalClientMessage.getNextMessage()).isNull();
+ }
+
+ private void verifyHandshake(EncryptionRunner clientRunner, EncryptionRunner serverRunner)
+ throws Exception {
+ HandshakeMessage initialClientMessage = clientRunner.initHandshake();
+
+ assertThat(initialClientMessage.getHandshakeState())
+ .isEqualTo(HandshakeMessage.HandshakeState.IN_PROGRESS);
+ assertThat(initialClientMessage.getKey()).isNull();
+ assertThat(initialClientMessage.getNextMessage()).isNotNull();
+
+ // This and the following similar log statements are useful when running this test to
+ // find the payload sizes.
+ Log.i(EncryptionRunner.TAG,
+ "initial client size:" + initialClientMessage.getNextMessage().length);
+
+ HandshakeMessage initialServerMessage =
+ serverRunner.respondToInitRequest(initialClientMessage.getNextMessage());
+
+ assertThat(initialServerMessage.getHandshakeState())
+ .isEqualTo(HandshakeMessage.HandshakeState.IN_PROGRESS);
+ assertThat(initialServerMessage.getKey()).isNull();
+ assertThat(initialServerMessage.getNextMessage()).isNotNull();
+
+ Log.i(EncryptionRunner.TAG,
+ "initial server message size:" + initialServerMessage.getNextMessage().length);
+
+ HandshakeMessage clientMessage =
+ clientRunner.continueHandshake(initialServerMessage.getNextMessage());
+
+ assertThat(clientMessage.getHandshakeState())
+ .isEqualTo(HandshakeMessage.HandshakeState.VERIFICATION_NEEDED);
+ assertThat(clientMessage.getKey()).isNull();
+ assertThat(clientMessage.getVerificationCode()).isNotEmpty();
+ assertThat(clientMessage.getNextMessage()).isNotNull();
+
+ Log.i(EncryptionRunner.TAG,
+ "second client message size:" + clientMessage.getNextMessage().length);
+
+ HandshakeMessage serverMessage =
+ serverRunner.continueHandshake(clientMessage.getNextMessage());
+ assertThat(serverMessage.getHandshakeState())
+ .isEqualTo(HandshakeMessage.HandshakeState.VERIFICATION_NEEDED);
+ assertThat(serverMessage.getKey()).isNull();
+ assertThat(serverMessage.getNextMessage()).isNull();
+
+ Log.i(EncryptionRunner.TAG,
+ "last server message size:" + clientMessage.getNextMessage().length);
+ }
+
+ private void verifyHandshakeReconnect(
+ EncryptionRunner clientRunner, EncryptionRunner serverRunner)
+ throws HandshakeException {
+ clientRunner.setIsReconnect(true);
+ serverRunner.setIsReconnect(true);
+
+ HandshakeMessage initialClientMessage = clientRunner.initHandshake();
+ assertThat(initialClientMessage.getHandshakeState())
+ .isEqualTo(HandshakeMessage.HandshakeState.IN_PROGRESS);
+ assertThat(initialClientMessage.getKey()).isNull();
+ assertThat(initialClientMessage.getNextMessage()).isNotNull();
+
+ // This and the following similar log statements are useful when running this test to
+ // find the payload sizes.
+ Log.i(EncryptionRunner.TAG,
+ "initial client size:" + initialClientMessage.getNextMessage().length);
+
+ HandshakeMessage initialServerMessage =
+ serverRunner.respondToInitRequest(initialClientMessage.getNextMessage());
+
+ assertThat(initialServerMessage.getHandshakeState())
+ .isEqualTo(HandshakeMessage.HandshakeState.IN_PROGRESS);
+ assertThat(initialServerMessage.getKey()).isNull();
+ assertThat(initialServerMessage.getNextMessage()).isNotNull();
+
+ Log.i(EncryptionRunner.TAG,
+ "initial server message size:" + initialServerMessage.getNextMessage().length);
+
+ HandshakeMessage clientMessage =
+ clientRunner.continueHandshake(initialServerMessage.getNextMessage());
+
+ assertThat(clientMessage.getHandshakeState())
+ .isEqualTo(HandshakeMessage.HandshakeState.RESUMING_SESSION);
+ assertThat(clientMessage.getKey()).isNull();
+ assertThat(clientMessage.getNextMessage()).isNotNull();
+
+ HandshakeMessage serverMessage =
+ serverRunner.continueHandshake(clientMessage.getNextMessage());
+ assertThat(serverMessage.getHandshakeState())
+ .isEqualTo(HandshakeMessage.HandshakeState.RESUMING_SESSION);
+ assertThat(serverMessage.getKey()).isNull();
+ }
+
+ @Test
+ public void invalidPin_ukey2() throws Exception {
+ invalidPinTest(EncryptionRunnerFactory::newRunner);
+ }
+
+ @Test
+ public void invalidPin_dummy() throws Exception {
+ invalidPinTest(EncryptionRunnerFactory::newDummyRunner);
+ }
+
+ private void invalidPinTest(RunnerFactory runnerFactory) throws Exception {
+ EncryptionRunner clientRunner = runnerFactory.newRunner();
+ EncryptionRunner serverRunner = runnerFactory.newRunner();
+
+ verifyHandshake(clientRunner, serverRunner);
+ clientRunner.invalidPin();
+ serverRunner.invalidPin();
+
+ try {
+ clientRunner.verifyPin();
+ Assert.fail();
+ } catch (Exception ignored) {
+ // pass
+ }
+
+ try {
+ serverRunner.verifyPin();
+ Assert.fail();
+ } catch (Exception ignored) {
+ // pass
+ }
+ }
+}
diff --git a/EncryptionRunner/test/android/car/encryptionrunner/Ukey2EncryptionRunnerTest.java b/tests/carservice_unit_test/src/android/car/encryptionrunner/Ukey2EncryptionRunnerTest.java
similarity index 100%
rename from EncryptionRunner/test/android/car/encryptionrunner/Ukey2EncryptionRunnerTest.java
rename to tests/carservice_unit_test/src/android/car/encryptionrunner/Ukey2EncryptionRunnerTest.java
diff --git a/tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java b/tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java
index 2c7b9f1..1938a19 100644
--- a/tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java
@@ -23,9 +23,9 @@
import org.junit.Test;
public class VmsPublishersInfoTest {
- public static final byte[] MOCK_INFO_0 = new byte[]{2, 3, 5, 7, 11, 13, 17};
- public static final byte[] SAME_MOCK_INFO_0 = new byte[]{2, 3, 5, 7, 11, 13, 17};
- public static final byte[] MOCK_INFO_1 = new byte[]{2, 3, 5, 7, 11, 13, 17, 19};
+ public static final byte[] MOCK_INFO_1 = new byte[]{2, 3, 5, 7, 11, 13, 17};
+ public static final byte[] SAME_MOCK_INFO_1 = new byte[]{2, 3, 5, 7, 11, 13, 17};
+ public static final byte[] MOCK_INFO_2 = new byte[]{2, 3, 5, 7, 11, 13, 17, 19};
private VmsPublishersInfo mVmsPublishersInfo;
@@ -36,9 +36,9 @@
@Test
public void testSingleInfo() throws Exception {
- int id = mVmsPublishersInfo.getIdForInfo(MOCK_INFO_0);
- assertEquals(0, id);
- assertArrayEquals(MOCK_INFO_0, mVmsPublishersInfo.getPublisherInfo(id));
+ int id = mVmsPublishersInfo.getIdForInfo(MOCK_INFO_1);
+ assertEquals(1, id);
+ assertArrayEquals(MOCK_INFO_1, mVmsPublishersInfo.getPublisherInfo(id));
}
@Test
@@ -48,20 +48,20 @@
@Test
public void testTwoInfos() throws Exception {
- int id0 = mVmsPublishersInfo.getIdForInfo(MOCK_INFO_0);
int id1 = mVmsPublishersInfo.getIdForInfo(MOCK_INFO_1);
- assertEquals(0, id0);
+ int id2 = mVmsPublishersInfo.getIdForInfo(MOCK_INFO_2);
assertEquals(1, id1);
- assertArrayEquals(MOCK_INFO_0, mVmsPublishersInfo.getPublisherInfo(id0));
+ assertEquals(2, id2);
assertArrayEquals(MOCK_INFO_1, mVmsPublishersInfo.getPublisherInfo(id1));
+ assertArrayEquals(MOCK_INFO_2, mVmsPublishersInfo.getPublisherInfo(id2));
}
@Test
public void testSingleInfoInsertedTwice() throws Exception {
- int id = mVmsPublishersInfo.getIdForInfo(MOCK_INFO_0);
- assertEquals(0, id);
+ int id = mVmsPublishersInfo.getIdForInfo(MOCK_INFO_1);
+ assertEquals(1, id);
- int sameId = mVmsPublishersInfo.getIdForInfo(SAME_MOCK_INFO_0);
+ int sameId = mVmsPublishersInfo.getIdForInfo(SAME_MOCK_INFO_1);
assertEquals(sameId, id);
}
}
diff --git a/tests/carservice_unit_test/src/com/android/car/trust/BleMessageStreamV1Test.java b/tests/carservice_unit_test/src/com/android/car/trust/BleMessageStreamV1Test.java
index 5c42126..ec0a1ba 100644
--- a/tests/carservice_unit_test/src/com/android/car/trust/BleMessageStreamV1Test.java
+++ b/tests/carservice_unit_test/src/com/android/car/trust/BleMessageStreamV1Test.java
@@ -27,7 +27,6 @@
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattServer;
import android.os.Handler;
import androidx.test.runner.AndroidJUnit4;
@@ -67,9 +66,9 @@
private BleMessageStreamV1 mBleMessageStream;
private BluetoothDevice mBluetoothDevice;
+ @Mock BlePeripheralManager mBlePeripheralManager;
@Mock BleMessageStreamCallback mCallbackMock;
@Mock Handler mHandlerMock;
- @Mock BluetoothGattServer mGattServerMock;
@Mock BluetoothGattCharacteristic mWriteCharacteristicMock;
@Mock BluetoothGattCharacteristic mReadCharacteristicMock;
@@ -89,7 +88,8 @@
mBluetoothDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(ADDRESS_MOCK);
mBleMessageStream = new BleMessageStreamV1(
- mHandlerMock, mBluetoothDevice, mGattServerMock, mWriteCharacteristicMock);
+ mHandlerMock, mBlePeripheralManager, mBluetoothDevice, mWriteCharacteristicMock,
+ mReadCharacteristicMock);
mBleMessageStream.setCallback(mCallbackMock);
}
@@ -109,6 +109,10 @@
// Verify that the message was written.
verify(mWriteCharacteristicMock).setValue(expectedMessage.toByteArray());
+
+ // Verify that there is also a notification of the characteristic change.
+ verify(mBlePeripheralManager).notifyCharacteristicChanged(mBluetoothDevice,
+ mWriteCharacteristicMock, false);
}
@Test
@@ -131,9 +135,10 @@
int numOfAcks = requiredWrites - 1;
for (int i = 0; i < numOfAcks; i++) {
- mBleMessageStream.processClientMessage(
- BLEMessageV1Factory.makeAcknowledgementMessage().toByteArray(),
- mReadCharacteristicMock);
+ mBleMessageStream.onCharacteristicWrite(
+ mBluetoothDevice,
+ mReadCharacteristicMock,
+ BLEMessageV1Factory.makeAcknowledgementMessage().toByteArray());
}
// Each ACK should trigger a canceling of the retry runnable.
@@ -143,6 +148,9 @@
verify(mWriteCharacteristicMock, times(requiredWrites)).setValue(
messageCaptor.capture());
+ verify(mBlePeripheralManager, times(requiredWrites))
+ .notifyCharacteristicChanged(mBluetoothDevice,
+ mWriteCharacteristicMock, false);
List<byte[]> writtenBytes = messageCaptor.getAllValues();
ByteArrayOutputStream reassembledMessageStream = new ByteArrayOutputStream();
@@ -186,6 +194,8 @@
// Because there is no ACK, the write should be retried up to the limit.
verify(mWriteCharacteristicMock, times(BleMessageStreamV1Kt.BLE_MESSAGE_RETRY_LIMIT))
.setValue(messageCaptor.capture());
+ verify(mBlePeripheralManager, times(BleMessageStreamV1Kt.BLE_MESSAGE_RETRY_LIMIT))
+ .notifyCharacteristicChanged(mBluetoothDevice, mWriteCharacteristicMock, false);
List<byte[]> writtenBytes = messageCaptor.getAllValues();
List<byte[]> writtenPayloads = new ArrayList<>();
@@ -229,6 +239,8 @@
// Because there is no ACK, the write should be retried up to the limit.
verify(mWriteCharacteristicMock, times(BleMessageStreamV1Kt.BLE_MESSAGE_RETRY_LIMIT))
.setValue(any(byte[].class));
+ verify(mBlePeripheralManager, times(BleMessageStreamV1Kt.BLE_MESSAGE_RETRY_LIMIT))
+ .notifyCharacteristicChanged(mBluetoothDevice, mWriteCharacteristicMock, false);
// But the callback should only be notified once.
verify(mCallbackMock).onWriteMessageError();
@@ -242,8 +254,10 @@
BLEMessage clientMessage = BLEMessageV1Factory.makeBLEMessage(
payload, OperationType.CLIENT_MESSAGE, /* isPayloadEncrypted= */ true);
- mBleMessageStream.processClientMessage(clientMessage.toByteArray(),
- mReadCharacteristicMock);
+ mBleMessageStream.onCharacteristicWrite(
+ mBluetoothDevice,
+ mReadCharacteristicMock,
+ clientMessage.toByteArray());
// The callback should be notified with only the payload.
verify(mCallbackMock).onMessageReceived(payload, READ_UUID);
@@ -264,8 +278,10 @@
payload, OperationType.CLIENT_MESSAGE, maxSize, /* isPayloadEncrypted= */ true);
for (BLEMessage message : clientMessages) {
- mBleMessageStream.processClientMessage(message.toByteArray(),
- mReadCharacteristicMock);
+ mBleMessageStream.onCharacteristicWrite(
+ mBluetoothDevice,
+ mReadCharacteristicMock,
+ message.toByteArray());
}
// The callback should be notified with only the payload.
@@ -287,15 +303,19 @@
payload, OperationType.CLIENT_MESSAGE, maxSize, /* isPayloadEncrypted= */ true);
for (BLEMessage message : clientMessages) {
- mBleMessageStream.processClientMessage(message.toByteArray(),
- mReadCharacteristicMock);
+ mBleMessageStream.onCharacteristicWrite(
+ mBluetoothDevice,
+ mReadCharacteristicMock,
+ message.toByteArray());
}
ArgumentCaptor<byte[]> messageCaptor = ArgumentCaptor.forClass(byte[].class);
- // An ACK should be sent for each message received, except the last tone.
+ // An ACK should be sent for each message received, except the last one.
verify(mWriteCharacteristicMock, times(clientMessages.size() - 1))
.setValue(messageCaptor.capture());
+ verify(mBlePeripheralManager, times(clientMessages.size() - 1))
+ .notifyCharacteristicChanged(mBluetoothDevice, mWriteCharacteristicMock, false);
List<byte[]> writtenValues = messageCaptor.getAllValues();
byte[] ackMessageBytes = BLEMessageV1Factory.makeAcknowledgementMessage().toByteArray();
diff --git a/tests/carservice_unit_test/src/com/android/car/trust/CarTrustAgentEnrollmentServiceTest.java b/tests/carservice_unit_test/src/com/android/car/trust/CarTrustAgentEnrollmentServiceTest.java
index c56fcb9..a7ed454 100644
--- a/tests/carservice_unit_test/src/com/android/car/trust/CarTrustAgentEnrollmentServiceTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/trust/CarTrustAgentEnrollmentServiceTest.java
@@ -59,6 +59,8 @@
private static final long TEST_HANDLE1 = 1L;
private static final long TEST_HANDLE2 = 2L;
+ private static final String DEVICE_ID = "device_id";
+ private static final String KEY = "key";
// Random uuid for test
private static final UUID TEST_ID1 = UUID.fromString("9a138a69-7c29-400f-9e71-fc29516f9f8b");
private static final UUID TEST_ID2 = UUID.fromString("3e344860-e688-4cce-8411-16161b61ad57");
@@ -270,6 +272,17 @@
}
@Test
+ public void testEncryptionKeyStorage() {
+ byte[] encryptionKey = KEY.getBytes();
+ if (mCarTrustedDeviceService.saveEncryptionKey(DEVICE_ID, encryptionKey)) {
+ assertThat(mCarTrustedDeviceService.getEncryptionKey(DEVICE_ID))
+ .isEqualTo(encryptionKey);
+ }
+ mCarTrustedDeviceService.clearEncryptionKey(DEVICE_ID);
+ assertThat(mCarTrustedDeviceService.getEncryptionKey(DEVICE_ID) == null).isTrue();
+ }
+
+ @Test
public void testGetUserHandleByTokenHandle_existingHandle() {
setupEncryptionHandshake(TEST_ID1);
mCarTrustAgentEnrollmentService.onEscrowTokenActiveStateChanged(
diff --git a/tests/carservice_unit_test/src/com/android/car/trust/ScanResultsTest.java b/tests/carservice_unit_test/src/com/android/car/trust/ScanResultsTest.java
new file mode 100644
index 0000000..20c2fa4
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/trust/ScanResultsTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.car.trust;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.le.ScanRecord;
+import android.bluetooth.le.ScanResult;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.math.BigInteger;
+
+@RunWith(AndroidJUnit4.class)
+public class ScanResultsTest {
+
+ @Test
+ public void containsUuidsInOverflow_withBitFlipped_shouldReturnTrue() {
+ ScanRecord mockScanRecord = mock(ScanRecord.class);
+ ScanResult scanResult = new ScanResult(null, mockScanRecord, 0, 0);
+ byte[] data = new BigInteger(
+ "02011A14FF4C00010000000000000000000000000020000000000000000000000000000000"
+ + "00000000000000000000000000000000000000000000000000", 16)
+ .toByteArray();
+ BigInteger mask = new BigInteger("00000000000000000000000000200000", 16);
+ when(mockScanRecord.getBytes()).thenReturn(data);
+ assertThat(ScanResults.containsUuidsInOverflow(scanResult, mask)).isTrue();
+ }
+}
diff --git a/tests/carservice_unit_test/src/com/android/car/vms/VmsClientManagerTest.java b/tests/carservice_unit_test/src/com/android/car/vms/VmsClientManagerTest.java
index 77d0847..0bff9d2 100644
--- a/tests/carservice_unit_test/src/com/android/car/vms/VmsClientManagerTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/vms/VmsClientManagerTest.java
@@ -77,8 +77,10 @@
private static final String USER_CLIENT = "com.google.android.apps.vms.test/.VmsUserClient";
private static final ComponentName USER_CLIENT_COMPONENT =
ComponentName.unflattenFromString(USER_CLIENT);
+ private static final int USER_ID = 10;
private static final String USER_CLIENT_NAME =
"com.google.android.apps.vms.test/com.google.android.apps.vms.test.VmsUserClient U=10";
+ private static final int USER_ID_U11 = 11;
private static final String USER_CLIENT_NAME_U11 =
"com.google.android.apps.vms.test/com.google.android.apps.vms.test.VmsUserClient U=11";
@Rule
@@ -96,7 +98,7 @@
private CarUserService mUserService;
@Mock
private CarUserManagerHelper mUserManagerHelper;
- private int mUserId;
+ private int mForegroundUserId;
@Mock
private VmsHalService mHal;
@@ -127,10 +129,7 @@
com.android.car.R.array.vmsPublisherUserClients)).thenReturn(
new String[]{ USER_CLIENT });
- mUserId = 10;
- when(mUserManagerHelper.getCurrentForegroundUserId()).thenAnswer((invocation) -> mUserId);
when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager);
- when(mUserManager.isUserUnlocked(any())).thenReturn(false);
mClientManager = new VmsClientManager(mContext, mUserService, mUserManagerHelper, mHal);
mClientManager.registerConnectionListener(mConnectionListener);
@@ -266,18 +265,26 @@
@Test
public void testUserUnlocked() {
- notifyUserUnlocked();
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
+ notifyUserUnlocked(USER_ID, true);
// Multiple events should only trigger a single bind, when successful
verifyUserBind(1);
}
@Test
+ public void testUserUnlocked_ForegroundUserNotUnlocked() {
+ notifyUserUnlocked(USER_ID, false);
+
+ // Process will not be bound
+ verifyUserBind(0);
+ }
+
+ @Test
public void testUserUnlocked_ClientNotFound() throws Exception {
when(mPackageManager.getServiceInfo(eq(USER_CLIENT_COMPONENT), anyInt()))
.thenThrow(new PackageManager.NameNotFoundException());
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
// Process will not be bound
verifyUserBind(0);
@@ -289,7 +296,7 @@
serviceInfo.permission = Car.PERMISSION_VMS_PUBLISHER;
when(mPackageManager.getServiceInfo(eq(USER_CLIENT_COMPONENT), anyInt()))
.thenReturn(serviceInfo);
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
// Process will not be bound
verifyUserBind(0);
@@ -299,8 +306,8 @@
public void testUserUnlocked_BindFailed() {
when(mContext.bindServiceAsUser(any(), any(), anyInt(), any(), any()))
.thenReturn(false);
- notifyUserUnlocked();
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
+ notifyUserUnlocked(USER_ID, true);
// Failure state will trigger another attempt
verifyUserBind(2);
@@ -308,10 +315,10 @@
@Test
public void testUserUnlocked_UserBindFailed() {
- when(mContext.bindServiceAsUser(any(), any(), anyInt(), any(), eq(UserHandle.of(mUserId))))
+ when(mContext.bindServiceAsUser(any(), any(), anyInt(), any(), eq(UserHandle.of(USER_ID))))
.thenReturn(false);
- notifyUserUnlocked();
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
+ notifyUserUnlocked(USER_ID, true);
// Failure state will trigger another attempt
verifyUserBind(2);
@@ -321,8 +328,8 @@
public void testUserUnlocked_BindException() {
when(mContext.bindServiceAsUser(any(), any(), anyInt(), any(), any()))
.thenThrow(new SecurityException());
- notifyUserUnlocked();
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
+ notifyUserUnlocked(USER_ID, true);
// Failure state will trigger another attempt
verifyUserBind(2);
@@ -338,7 +345,7 @@
when(mContext.bindServiceAsUser(any(), any(), anyInt(), any(), eq(UserHandle.SYSTEM)))
.thenReturn(true);
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
verifySystemBind(1);
verifyUserBind(1);
}
@@ -353,8 +360,8 @@
when(mContext.bindServiceAsUser(any(), any(), anyInt(), any(), eq(UserHandle.SYSTEM)))
.thenReturn(false);
- notifyUserUnlocked();
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
+ notifyUserUnlocked(USER_ID, true);
verifySystemBind(2); // Failure state will trigger another attempt
verifyUserBind(1);
@@ -370,8 +377,8 @@
when(mContext.bindServiceAsUser(any(), any(), anyInt(), any(), eq(UserHandle.SYSTEM)))
.thenThrow(new SecurityException());
- notifyUserUnlocked();
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
+ notifyUserUnlocked(USER_ID, true);
verifySystemBind(2); // Failure state will trigger another attempt
verifyUserBind(1);
@@ -379,36 +386,36 @@
@Test
public void testUserSwitched() {
- notifyUserSwitched();
+ notifyUserSwitched(USER_ID, true);
+ notifyUserSwitched(USER_ID, true);
- // Clients are not bound on user switch alone
- verifyUserBind(0);
+ // Multiple events should only trigger a single bind, when successful
+ verifyUserBind(1);
}
@Test
public void testUserSwitchedAndUnlocked() {
- notifyUserSwitched();
- notifyUserUnlocked();
+ notifyUserSwitched(USER_ID, true);
+ notifyUserUnlocked(USER_ID, true);
// Multiple events should only trigger a single bind, when successful
verifyUserBind(1);
}
@Test
- public void testUserSwitchedAlreadyUnlocked() {
- when(mUserManager.isUserUnlocked(mUserId)).thenReturn(true);
- notifyUserSwitched();
+ public void testUserSwitched_ForegroundUserNotUnlocked() {
+ notifyUserSwitched(USER_ID, false);
- // Multiple events should only trigger a single bind, when successful
- verifyUserBind(1);
+ // Process will not be bound
+ verifyUserBind(0);
}
@Test
public void testUserSwitchedToSystemUser() {
- mUserId = UserHandle.USER_SYSTEM;
- notifyUserSwitched();
+ notifyUserSwitched(UserHandle.USER_SYSTEM, true);
- // User processes will not be bound for system user
+ // Neither user nor system processes will be bound for system user intent
+ verifySystemBind(0);
verifyUserBind(0);
}
@@ -459,7 +466,7 @@
}
private IBinder bindUserClient() {
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
verifyUserBind(1);
resetContext();
@@ -549,7 +556,7 @@
@Test
public void testOnUserServiceDisconnected() throws Exception {
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
verifyUserBind(1);
resetContext();
@@ -566,7 +573,7 @@
@Test
public void testOnUserServiceDisconnected_ServiceReboundByAndroid() throws Exception {
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
verifyUserBind(1);
resetContext();
@@ -584,7 +591,7 @@
@Test
public void testOnUserServiceBindingDied() throws Exception {
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
verifyUserBind(1);
resetContext();
@@ -602,7 +609,7 @@
@Test
public void testOnUserServiceBindingDied_ServiceNotConnected() throws Exception {
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
verifyUserBind(1);
resetContext();
@@ -618,15 +625,30 @@
@Test
public void testOnUserSwitched_UserChange() {
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
verifyUserBind(1);
ServiceConnection connection = mConnectionCaptor.getValue();
connection.onServiceConnected(null, new Binder());
resetContext();
reset(mConnectionListener);
- mUserId = 11;
- notifyUserSwitched();
+ notifyUserSwitched(USER_ID_U11, true);
+
+ verify(mContext).unbindService(connection);
+ verify(mConnectionListener).onClientDisconnected(eq(USER_CLIENT_NAME));
+ verifyUserBind(1);
+ }
+
+ @Test
+ public void testOnUserSwitched_UserChange_ForegroundUserNotUnlocked() {
+ notifyUserUnlocked(USER_ID, true);
+ verifyUserBind(1);
+ ServiceConnection connection = mConnectionCaptor.getValue();
+ connection.onServiceConnected(null, new Binder());
+ resetContext();
+ reset(mConnectionListener);
+
+ notifyUserSwitched(USER_ID_U11, false);
verify(mContext).unbindService(connection);
verify(mConnectionListener).onClientDisconnected(eq(USER_CLIENT_NAME));
@@ -635,15 +657,14 @@
@Test
public void testOnUserSwitched_UserChange_ToSystemUser() {
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
verifyUserBind(1);
ServiceConnection connection = mConnectionCaptor.getValue();
connection.onServiceConnected(null, new Binder());
resetContext();
reset(mConnectionListener);
- mUserId = UserHandle.USER_SYSTEM;
- notifyUserSwitched();
+ notifyUserSwitched(UserHandle.USER_SYSTEM, true);
verify(mContext).unbindService(connection);
verify(mConnectionListener).onClientDisconnected(eq(USER_CLIENT_NAME));
@@ -652,13 +673,25 @@
@Test
public void testOnUserSwitched_UserChange_ServiceNotConnected() {
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
verifyUserBind(1);
ServiceConnection connection = mConnectionCaptor.getValue();
resetContext();
- mUserId = 11;
- notifyUserSwitched();
+ notifyUserSwitched(USER_ID_U11, true);
+
+ verify(mContext).unbindService(connection);
+ verifyUserBind(1);
+ }
+
+ @Test
+ public void testOnUserSwitched_UserChange_ServiceNotConnected_ForegroundUserNotUnlocked() {
+ notifyUserUnlocked(USER_ID, true);
+ verifyUserBind(1);
+ ServiceConnection connection = mConnectionCaptor.getValue();
+ resetContext();
+
+ notifyUserSwitched(USER_ID_U11, false);
verify(mContext).unbindService(connection);
verifyUserBind(0);
@@ -666,15 +699,14 @@
@Test
public void testOnUserUnlocked_UserChange() {
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
verifyUserBind(1);
ServiceConnection connection = mConnectionCaptor.getValue();
connection.onServiceConnected(null, new Binder());
resetContext();
reset(mConnectionListener);
- mUserId = 11;
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID_U11, true);
verify(mContext).unbindService(connection);
verify(mConnectionListener).onClientDisconnected(eq(USER_CLIENT_NAME));
@@ -685,15 +717,14 @@
public void testOnUserUnlocked_UserChange_ToSystemUser() {
notifySystemUserUnlocked();
verifySystemBind(1);
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
verifyUserBind(1);
ServiceConnection connection = mConnectionCaptor.getValue();
connection.onServiceConnected(null, new Binder());
resetContext();
reset(mConnectionListener);
- mUserId = UserHandle.USER_SYSTEM;
- notifyUserUnlocked();
+ notifyUserUnlocked(UserHandle.USER_SYSTEM, true);
verify(mContext).unbindService(connection);
verify(mConnectionListener).onClientDisconnected(eq(USER_CLIENT_NAME));
@@ -703,13 +734,12 @@
@Test
public void testOnUserUnlocked_UserChange_ServiceNotConnected() {
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID, true);
verifyUserBind(1);
ServiceConnection connection = mConnectionCaptor.getValue();
resetContext();
- mUserId = 11;
- notifyUserUnlocked();
+ notifyUserUnlocked(USER_ID_U11, true);
verify(mContext).unbindService(connection);
verifyUserBind(1);
@@ -726,14 +756,24 @@
mClientManager.mSystemUserUnlockedListener.run();
}
- private void notifyUserSwitched() {
- mClientManager.mUserSwitchReceiver.onReceive(mContext,
- new Intent(Intent.ACTION_USER_SWITCHED));
+ private void notifyUserSwitched(int foregroundUserId, boolean isForegroundUserUnlocked) {
+ notifyUserAction(foregroundUserId, isForegroundUserUnlocked, Intent.ACTION_USER_SWITCHED);
}
- private void notifyUserUnlocked() {
- mClientManager.mUserSwitchReceiver.onReceive(mContext,
- new Intent(Intent.ACTION_USER_UNLOCKED));
+ private void notifyUserUnlocked(int foregroundUserId, boolean isForegroundUserUnlocked) {
+ notifyUserAction(foregroundUserId, isForegroundUserUnlocked, Intent.ACTION_USER_UNLOCKED);
+ }
+
+ // Sets the current foreground user + unlock state and dispatches the specified intent action
+ private void notifyUserAction(int foregroundUserId, boolean isForegroundUserUnlocked,
+ String action) {
+ mForegroundUserId = foregroundUserId; // Member variable used by verifyUserBind()
+ when(mUserManagerHelper.getCurrentForegroundUserId()).thenReturn(foregroundUserId);
+
+ reset(mUserManager);
+ when(mUserManager.isUserUnlocked(foregroundUserId)).thenReturn(isForegroundUserUnlocked);
+
+ mClientManager.mUserSwitchReceiver.onReceive(mContext, new Intent(action));
}
private void verifySystemBind(int times) {
@@ -741,7 +781,7 @@
}
private void verifyUserBind(int times) {
- verifyBind(times, USER_CLIENT_COMPONENT, UserHandle.of(mUserId));
+ verifyBind(times, USER_CLIENT_COMPONENT, UserHandle.of(mForegroundUserId));
}
private void verifyBind(int times, ComponentName componentName, UserHandle user) {
diff --git a/tests/vehiclehal_test/assets/car_hvac_set_test.json b/tests/vehiclehal_test/assets/car_hvac_set_test.json
new file mode 100644
index 0000000..e42875f
--- /dev/null
+++ b/tests/vehiclehal_test/assets/car_hvac_set_test.json
@@ -0,0 +1,26 @@
+[
+ {
+ "timestamp": 1526063903356950016,
+ "areaId": 117,
+ "value": 0,
+ "prop": 354419984
+ },
+ {
+ "timestamp": 1526063903357100032,
+ "areaId": 117,
+ "value": 1,
+ "prop": 354419984
+ },
+ {
+ "timestamp": 1526063903358950016,
+ "areaId": 117,
+ "value": 0,
+ "prop": 354419984
+ },
+ {
+ "timestamp": 1526063903359100032,
+ "areaId": 117,
+ "value": 1,
+ "prop": 354419984
+ }
+]
\ No newline at end of file
diff --git a/tests/vehiclehal_test/assets/car_hvac_test.json b/tests/vehiclehal_test/assets/car_hvac_test.json
index 7f6c0bb..bf51b8d 100644
--- a/tests/vehiclehal_test/assets/car_hvac_test.json
+++ b/tests/vehiclehal_test/assets/car_hvac_test.json
@@ -1,518 +1,506 @@
[
{
- "timestamp": 1526063903356950016,
- "areaId": 1,
- "value": 1,
- "prop": 354419984
- },
- {
- "timestamp": 1526063903357100032,
- "areaId": 4,
- "value": 1,
- "prop": 354419984
- },
- {
- "timestamp": 1526063903757636096,
- "areaId": 0,
- "value": 1,
+ "timestamp": 1526063903757636096,
+ "areaId": 117,
+ "value": 1,
"prop": 356517121
- },
+ },
{
- "timestamp": 1526063904959113984,
- "areaId": 0,
- "value": 28,
+ "timestamp": 1526063904959113984,
+ "areaId": 49,
+ "value": 28,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063905159528960,
- "areaId": 0,
- "value": 27,
+ "timestamp": 1526063905159528960,
+ "areaId": 49,
+ "value": 27,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063905359936000,
- "areaId": 0,
- "value": 26,
+ "timestamp": 1526063905359936000,
+ "areaId": 49,
+ "value": 26,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063905560376832,
- "areaId": 0,
- "value": 25,
+ "timestamp": 1526063905560376832,
+ "areaId": 49,
+ "value": 25,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063905760837120,
- "areaId": 0,
- "value": 24,
+ "timestamp": 1526063905760837120,
+ "areaId": 49,
+ "value": 24,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063905961300992,
- "areaId": 0,
- "value": 23,
+ "timestamp": 1526063905961300992,
+ "areaId": 49,
+ "value": 23,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063906362006016,
- "areaId": 0,
- "value": 1,
+ "timestamp": 1526063906362006016,
+ "areaId": 117,
+ "value": 1,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063906562436096,
- "areaId": 0,
- "value": 2,
+ "timestamp": 1526063906562436096,
+ "areaId": 117,
+ "value": 2,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063906762857984,
- "areaId": 0,
- "value": 3,
+ "timestamp": 1526063906762857984,
+ "areaId": 117,
+ "value": 3,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063906963272960,
- "areaId": 0,
- "value": 4,
+ "timestamp": 1526063906963272960,
+ "areaId": 117,
+ "value": 4,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063908364721920,
- "areaId": 0,
- "value": 1,
+ "timestamp": 1526063908364721920,
+ "areaId": 117,
+ "value": 1,
"prop": 356517121
- },
+ },
{
- "timestamp": 1526063910066729984,
- "areaId": 0,
- "value": 4,
+ "timestamp": 1526063910066729984,
+ "areaId": 117,
+ "value": 4,
"prop": 356517121
- },
+ },
{
- "timestamp": 1526063911268203008,
- "areaId": 0,
- "value": 22,
+ "timestamp": 1526063911268203008,
+ "areaId": 49,
+ "value": 22,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063911468478976,
- "areaId": 0,
- "value": 23,
+ "timestamp": 1526063911468478976,
+ "areaId": 49,
+ "value": 23,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063911668872192,
- "areaId": 0,
- "value": 24,
+ "timestamp": 1526063911668872192,
+ "areaId": 49,
+ "value": 24,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063911869281024,
- "areaId": 0,
- "value": 25,
+ "timestamp": 1526063911869281024,
+ "areaId": 49,
+ "value": 25,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063912069678080,
- "areaId": 0,
- "value": 26,
+ "timestamp": 1526063912069678080,
+ "areaId": 49,
+ "value": 26,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063912270088960,
- "areaId": 0,
- "value": 27,
+ "timestamp": 1526063912270088960,
+ "areaId": 49,
+ "value": 27,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063912670825984,
- "areaId": 0,
- "value": 5,
+ "timestamp": 1526063912670825984,
+ "areaId": 117,
+ "value": 5,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063912871236096,
- "areaId": 0,
- "value": 4,
+ "timestamp": 1526063912871236096,
+ "areaId": 117,
+ "value": 4,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063913071654912,
- "areaId": 0,
- "value": 3,
+ "timestamp": 1526063913071654912,
+ "areaId": 117,
+ "value": 3,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063913272064000,
- "areaId": 0,
- "value": 2,
+ "timestamp": 1526063913272064000,
+ "areaId": 117,
+ "value": 2,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063914373497856,
- "areaId": 0,
- "value": 1,
+ "timestamp": 1526063914373497856,
+ "areaId": 117,
+ "value": 1,
"prop": 356517121
- },
+ },
{
- "timestamp": 1526063915574942976,
- "areaId": 0,
- "value": 28,
+ "timestamp": 1526063915574942976,
+ "areaId": 49,
+ "value": 28,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063915775356928,
- "areaId": 0,
- "value": 27,
+ "timestamp": 1526063915775356928,
+ "areaId": 49,
+ "value": 27,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063915975784960,
- "areaId": 0,
- "value": 26,
+ "timestamp": 1526063915975784960,
+ "areaId": 49,
+ "value": 26,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063916176208128,
- "areaId": 0,
- "value": 25,
+ "timestamp": 1526063916176208128,
+ "areaId": 49,
+ "value": 25,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063916376483840,
- "areaId": 0,
- "value": 24,
+ "timestamp": 1526063916376483840,
+ "areaId": 49,
+ "value": 24,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063916576890880,
- "areaId": 0,
- "value": 23,
+ "timestamp": 1526063916576890880,
+ "areaId": 49,
+ "value": 23,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063916977551872,
- "areaId": 0,
- "value": 1,
+ "timestamp": 1526063916977551872,
+ "areaId": 117,
+ "value": 1,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063917177978112,
- "areaId": 0,
- "value": 2,
+ "timestamp": 1526063917177978112,
+ "areaId": 117,
+ "value": 2,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063917378403072,
- "areaId": 0,
- "value": 3,
+ "timestamp": 1526063917378403072,
+ "areaId": 117,
+ "value": 3,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063917578809856,
- "areaId": 0,
- "value": 4,
+ "timestamp": 1526063917578809856,
+ "areaId": 117,
+ "value": 4,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063918980086016,
- "areaId": 0,
- "value": 1,
+ "timestamp": 1526063918980086016,
+ "areaId": 117,
+ "value": 1,
"prop": 356517121
- },
+ },
{
- "timestamp": 1526063920681338112,
- "areaId": 0,
- "value": 4,
+ "timestamp": 1526063920681338112,
+ "areaId": 117,
+ "value": 4,
"prop": 356517121
- },
+ },
{
- "timestamp": 1526063921882802944,
- "areaId": 0,
- "value": 22,
+ "timestamp": 1526063921882802944,
+ "areaId": 49,
+ "value": 22,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063922083273984,
- "areaId": 0,
- "value": 23,
+ "timestamp": 1526063922083273984,
+ "areaId": 49,
+ "value": 23,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063922283792896,
- "areaId": 0,
- "value": 24,
+ "timestamp": 1526063922283792896,
+ "areaId": 49,
+ "value": 24,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063922484265984,
- "areaId": 0,
- "value": 25,
+ "timestamp": 1526063922484265984,
+ "areaId": 49,
+ "value": 25,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063922684783872,
- "areaId": 0,
- "value": 26,
+ "timestamp": 1526063922684783872,
+ "areaId": 49,
+ "value": 26,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063922885256960,
- "areaId": 0,
- "value": 27,
+ "timestamp": 1526063922885256960,
+ "areaId": 49,
+ "value": 27,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063923285954048,
- "areaId": 0,
- "value": 5,
+ "timestamp": 1526063923285954048,
+ "areaId": 117,
+ "value": 5,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063923486427136,
- "areaId": 0,
- "value": 4,
+ "timestamp": 1526063923486427136,
+ "areaId": 117,
+ "value": 4,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063923686938880,
- "areaId": 0,
- "value": 3,
+ "timestamp": 1526063923686938880,
+ "areaId": 117,
+ "value": 3,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063923887389952,
- "areaId": 0,
- "value": 2,
+ "timestamp": 1526063923887389952,
+ "areaId": 117,
+ "value": 2,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063924988778240,
- "areaId": 0,
- "value": 1,
+ "timestamp": 1526063924988778240,
+ "areaId": 117,
+ "value": 1,
"prop": 356517121
- },
+ },
{
- "timestamp": 1526063926190287104,
- "areaId": 0,
- "value": 28,
+ "timestamp": 1526063926190287104,
+ "areaId": 49,
+ "value": 28,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063926390775040,
- "areaId": 0,
- "value": 27,
+ "timestamp": 1526063926390775040,
+ "areaId": 49,
+ "value": 27,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063926591278080,
- "areaId": 0,
- "value": 26,
+ "timestamp": 1526063926591278080,
+ "areaId": 49,
+ "value": 26,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063926791796992,
- "areaId": 0,
- "value": 25,
+ "timestamp": 1526063926791796992,
+ "areaId": 49,
+ "value": 25,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063926992291840,
- "areaId": 0,
- "value": 24,
+ "timestamp": 1526063926992291840,
+ "areaId": 49,
+ "value": 24,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063927192840960,
- "areaId": 0,
- "value": 23,
+ "timestamp": 1526063927192840960,
+ "areaId": 49,
+ "value": 23,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063927593507072,
- "areaId": 0,
- "value": 1,
+ "timestamp": 1526063927593507072,
+ "areaId": 117,
+ "value": 1,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063927793946112,
- "areaId": 0,
- "value": 2,
+ "timestamp": 1526063927793946112,
+ "areaId": 117,
+ "value": 2,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063927994479872,
- "areaId": 0,
- "value": 3,
+ "timestamp": 1526063927994479872,
+ "areaId": 117,
+ "value": 3,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063928194946048,
- "areaId": 0,
- "value": 4,
+ "timestamp": 1526063928194946048,
+ "areaId": 117,
+ "value": 4,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063929596730112,
- "areaId": 0,
- "value": 1,
+ "timestamp": 1526063929596730112,
+ "areaId": 117,
+ "value": 1,
"prop": 356517121
- },
+ },
{
- "timestamp": 1526063931298659072,
- "areaId": 0,
- "value": 4,
+ "timestamp": 1526063931298659072,
+ "areaId": 117,
+ "value": 4,
"prop": 356517121
- },
+ },
{
- "timestamp": 1526063932500180992,
- "areaId": 0,
- "value": 22,
+ "timestamp": 1526063932500180992,
+ "areaId": 49,
+ "value": 22,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063932700491008,
- "areaId": 0,
- "value": 23,
+ "timestamp": 1526063932700491008,
+ "areaId": 49,
+ "value": 23,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063932900928000,
- "areaId": 0,
- "value": 24,
+ "timestamp": 1526063932900928000,
+ "areaId": 49,
+ "value": 24,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063933101340928,
- "areaId": 0,
- "value": 25,
+ "timestamp": 1526063933101340928,
+ "areaId": 49,
+ "value": 25,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063933301820160,
- "areaId": 0,
- "value": 26,
+ "timestamp": 1526063933301820160,
+ "areaId": 49,
+ "value": 26,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063933502290944,
- "areaId": 0,
- "value": 27,
+ "timestamp": 1526063933502290944,
+ "areaId": 49,
+ "value": 27,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063933903042048,
- "areaId": 0,
- "value": 5,
+ "timestamp": 1526063933903042048,
+ "areaId": 117,
+ "value": 5,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063934103492864,
- "areaId": 0,
- "value": 4,
+ "timestamp": 1526063934103492864,
+ "areaId": 117,
+ "value": 4,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063934303913984,
- "areaId": 0,
- "value": 3,
+ "timestamp": 1526063934303913984,
+ "areaId": 117,
+ "value": 3,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063934504412928,
- "areaId": 0,
- "value": 2,
+ "timestamp": 1526063934504412928,
+ "areaId": 117,
+ "value": 2,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063935606041856,
- "areaId": 0,
- "value": 1,
+ "timestamp": 1526063935606041856,
+ "areaId": 117,
+ "value": 1,
"prop": 356517121
- },
+ },
{
- "timestamp": 1526063936807610880,
- "areaId": 0,
- "value": 28,
+ "timestamp": 1526063936807610880,
+ "areaId": 49,
+ "value": 28,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063937008130048,
- "areaId": 0,
- "value": 27,
+ "timestamp": 1526063937008130048,
+ "areaId": 49,
+ "value": 27,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063937208636160,
- "areaId": 0,
- "value": 26,
+ "timestamp": 1526063937208636160,
+ "areaId": 49,
+ "value": 26,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063937409096960,
- "areaId": 0,
- "value": 25,
+ "timestamp": 1526063937409096960,
+ "areaId": 49,
+ "value": 25,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063937609554176,
- "areaId": 0,
- "value": 24,
+ "timestamp": 1526063937609554176,
+ "areaId": 49,
+ "value": 24,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063937810017024,
- "areaId": 0,
- "value": 23,
+ "timestamp": 1526063937810017024,
+ "areaId": 49,
+ "value": 23,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063938210696960,
- "areaId": 0,
- "value": 1,
+ "timestamp": 1526063938210696960,
+ "areaId": 117,
+ "value": 1,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063938411200000,
- "areaId": 0,
- "value": 2,
+ "timestamp": 1526063938411200000,
+ "areaId": 117,
+ "value": 2,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063938611734016,
- "areaId": 0,
- "value": 3,
+ "timestamp": 1526063938611734016,
+ "areaId": 117,
+ "value": 3,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063938812249856,
- "areaId": 0,
- "value": 4,
+ "timestamp": 1526063938812249856,
+ "areaId": 117,
+ "value": 4,
"prop": 356517120
- },
+ },
{
- "timestamp": 1526063940214057984,
- "areaId": 0,
- "value": 1,
+ "timestamp": 1526063940214057984,
+ "areaId": 117,
+ "value": 1,
"prop": 356517121
- },
+ },
{
- "timestamp": 1526063941916071936,
- "areaId": 0,
- "value": 4,
+ "timestamp": 1526063941916071936,
+ "areaId": 117,
+ "value": 4,
"prop": 356517121
- },
+ },
{
- "timestamp": 1526063943123698944,
- "areaId": 0,
- "value": 22,
+ "timestamp": 1526063943123698944,
+ "areaId": 49,
+ "value": 22,
"prop": 358614275
- },
+ },
{
- "timestamp": 1526063943323981056,
- "areaId": 0,
- "value": 23,
+ "timestamp": 1526063943323981056,
+ "areaId": 49,
+ "value": 23,
"prop": 358614275
}
]
\ No newline at end of file
diff --git a/tests/vehiclehal_test/assets/car_property_test.json b/tests/vehiclehal_test/assets/car_property_test.json
new file mode 100644
index 0000000..a09f855
--- /dev/null
+++ b/tests/vehiclehal_test/assets/car_property_test.json
@@ -0,0 +1,26 @@
+[
+ {
+ "timestamp": 100000,
+ "areaId": 0,
+ "value": 8,
+ "prop": 289408000
+ },
+ {
+ "timestamp": -10000000,
+ "areaId": 0,
+ "value": 4,
+ "prop": 289408000
+ },
+ {
+ "timestamp": 100000,
+ "areaId": 0,
+ "value": 16,
+ "prop": 289408000
+ },
+ {
+ "timestamp": -10000000,
+ "areaId": 0,
+ "value": 4,
+ "prop": 289408000
+ }
+]
\ No newline at end of file
diff --git a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/CarPropertyTest.java b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/CarPropertyTest.java
index b78660f..256e922 100644
--- a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/CarPropertyTest.java
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/CarPropertyTest.java
@@ -16,6 +16,7 @@
package com.android.car.vehiclehal.test;
import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -57,11 +58,14 @@
private static final Duration TEST_TIME_OUT = Duration.ofMinutes(10);
private static final String CAR_HVAC_TEST_JSON = "car_hvac_test.json";
+ private static final String CAR_HVAC_TEST_SET_JSON = "car_hvac_test.json";
private static final String CAR_INFO_TEST_JSON = "car_info_test.json";
// kMixedTypePropertyForTest property ID
private static final int MIXED_TYPE_PROPERTY = 0x21e01111;
// kMixedTypePropertyForTest default value
private static final Object[] DEFAULT_VALUE = {"MIXED property", true, 2, 3, 4.5f};
+ private static final String CAR_PROPERTY_TEST_JSON = "car_property_test.json";
+ private static final int GEAR_PROPERTY_ID = 289408000;
private class CarPropertyEventReceiver implements CarPropertyEventCallback {
@@ -100,19 +104,37 @@
}
/**
- * This test will let Default VHAL to generate HVAC data and verify on-the-fly in the test. It
- * is simulating the HVAC actions coming from hard buttons in a car.
+ * This test will use {@link CarPropertyManager#setProperty(Class, int, int, Object)} to turn
+ * on the HVAC_PROWER and then let Default VHAL to generate HVAC data and verify on-the-fly
+ * in the test. It is simulating the HVAC actions coming from hard buttons in a car.
* @throws Exception
*/
@Test
public void testHvacHardButtonOperations() throws Exception {
+
Log.d(TAG, "Prepare HVAC test data");
List<CarPropertyValue> expectedEvents = getExpectedEvents(CAR_HVAC_TEST_JSON);
- VhalEventVerifier verifier = new VhalEventVerifier(expectedEvents);
+ List<CarPropertyValue> expectedSetEvents = getExpectedEvents(CAR_HVAC_TEST_SET_JSON);
CarPropertyManager propMgr = (CarPropertyManager) mCar.getCarManager(Car.PROPERTY_SERVICE);
assertNotNull("CarPropertyManager is null", propMgr);
+ final long waitForSetMillisecond = 2;
+ for (CarPropertyValue expectedEvent : expectedSetEvents) {
+ Class valueClass = expectedEvent.getValue().getClass();
+ propMgr.setProperty(valueClass,
+ expectedEvent.getPropertyId(),
+ expectedEvent.getAreaId(),
+ expectedEvent.getValue());
+ Thread.sleep(waitForSetMillisecond);
+ CarPropertyValue receivedEvent = propMgr.getProperty(valueClass,
+ expectedEvent.getPropertyId(), expectedEvent.getAreaId());
+ assertTrue("Mismatched events, expected: " + expectedEvent + ", received: "
+ + receivedEvent, Utils.areCarPropertyValuesEqual(expectedEvent, receivedEvent));
+ }
+
+ VhalEventVerifier verifier = new VhalEventVerifier(expectedEvents);
+
ArraySet<Integer> props = new ArraySet<>();
for (CarPropertyValue event : expectedEvents) {
if (!props.contains(event.getPropertyId())) {
@@ -147,36 +169,6 @@
}
/**
- * This test will exercise on "set" calls to inject HVAC data in order to test the Car Property
- * API end-to-end functionality.
- * @throws Exception
- */
- @Test
- @SuppressWarnings("unchecked")
- public void testHvacSetGetOperations() throws Exception {
- Log.d(TAG, "Prepare HVAC test data");
- List<CarPropertyValue> expectedEvents = getExpectedEvents(CAR_HVAC_TEST_JSON);
-
- CarPropertyManager propMgr = (CarPropertyManager) mCar.getCarManager(Car.PROPERTY_SERVICE);
- assertNotNull("CarPropertyManager is null", propMgr);
-
- final long waitForSetMillisecond = 2;
- for (CarPropertyValue expectedEvent : expectedEvents) {
- Class valueClass = expectedEvent.getValue().getClass();
- propMgr.setProperty(valueClass,
- expectedEvent.getPropertyId(),
- expectedEvent.getAreaId(),
- expectedEvent.getValue());
-
- Thread.sleep(waitForSetMillisecond);
- CarPropertyValue receivedEvent = propMgr.getProperty(valueClass,
- expectedEvent.getPropertyId(), expectedEvent.getAreaId());
- assertTrue("Mismatched events, expected: " + expectedEvent + ", received: "
- + receivedEvent, Utils.areCarPropertyValuesEqual(expectedEvent, receivedEvent));
- }
- }
-
- /**
* This test will load static vehicle information from test data file and verify them through
* get calls.
* @throws Exception
@@ -249,4 +241,50 @@
assertArrayEquals(expectedValue, result.getValue());
}
+ /**
+ * This test will test the case: vehicle events comes to android out of order.
+ * See the events in car_property_test.json.
+ * @throws Exception
+ */
+ @Test
+ public void testPropertyEventOutOfOrder() throws Exception {
+ CarPropertyManager propMgr = (CarPropertyManager) mCar.getCarManager(Car.PROPERTY_SERVICE);
+ assertNotNull("CarPropertyManager is null", propMgr);
+
+ File sharedJson = makeShareable(CAR_PROPERTY_TEST_JSON);
+ Log.d(TAG, "send command to VHAL to generate events");
+ JsonVhalEventGenerator propertyGenerator =
+ new JsonVhalEventGenerator(mVehicle).setJsonFile(sharedJson);
+
+ GearEventTestCallback cb = new GearEventTestCallback();
+ propMgr.registerCallback(cb, GEAR_PROPERTY_ID, CarPropertyManager.SENSOR_RATE_ONCHANGE);
+ Thread.sleep(2000);
+ propertyGenerator.start();
+ Thread.sleep(2000);
+ propertyGenerator.stop();
+ // check VHAL ignored the last event in car_property_test, because it is out of order.
+ int currentGear = propMgr.getIntProperty(GEAR_PROPERTY_ID, 0);
+ assertEquals(16, currentGear);
+ }
+
+ private class GearEventTestCallback implements CarPropertyEventCallback {
+ private long mTimestamp = 0L;
+
+ @Override
+ public void onChangeEvent(CarPropertyValue carPropertyValue) {
+ if (carPropertyValue.getPropertyId() != GEAR_PROPERTY_ID) {
+ return;
+ }
+ if (carPropertyValue.getStatus() == CarPropertyValue.STATUS_AVAILABLE) {
+ Assert.assertTrue("Received events out of oder",
+ mTimestamp <= carPropertyValue.getTimestamp());
+ mTimestamp = carPropertyValue.getTimestamp();
+ }
+ }
+
+ @Override
+ public void onErrorEvent(final int propertyId, final int zone) {
+ Assert.fail("Error: propertyId: x0" + toHexString(propertyId) + " areaId: " + zone);
+ }
+ }
}