summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/SystemProperties.java5
-rw-r--r--core/java/android/os/image/DynamicSystemManager.java18
-rw-r--r--core/java/android/os/image/IDynamicSystemService.aidl4
-rw-r--r--core/java/android/provider/DeviceConfig.java4
-rw-r--r--core/java/android/text/TextUtils.java47
-rw-r--r--core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java15
-rw-r--r--core/res/res/layout/accessibility_enable_service_warning.xml (renamed from core/res/res/layout/accessibility_enable_service_encryption_warning.xml)8
-rw-r--r--core/res/res/values/strings.xml7
-rw-r--r--core/res/res/values/symbols.xml4
-rw-r--r--core/tests/coretests/src/android/text/TextUtilsTest.java76
-rw-r--r--packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java7
-rw-r--r--packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags1
-rw-r--r--packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java93
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java2
-rw-r--r--services/core/java/com/android/server/DynamicSystemService.java11
-rw-r--r--services/core/java/com/android/server/vcn/VcnGatewayConnection.java14
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java20
-rw-r--r--telephony/java/android/telephony/data/ApnSetting.java4
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl3
-rw-r--r--tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java6
-rw-r--r--tools/aapt2/util/Files.cpp2
21 files changed, 271 insertions, 80 deletions
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index 82d4443ea724..aa283a2d019b 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -226,9 +226,10 @@ public class SystemProperties {
*/
@UnsupportedAppUsage
public static void set(@NonNull String key, @Nullable String val) {
- if (val != null && !key.startsWith("ro.") && val.length() > PROP_VALUE_MAX) {
+ if (val != null && !key.startsWith("ro.") && val.getBytes(StandardCharsets.UTF_8).length
+ > PROP_VALUE_MAX) {
throw new IllegalArgumentException("value of system property '" + key
- + "' is longer than " + PROP_VALUE_MAX + " characters: " + val);
+ + "' is longer than " + PROP_VALUE_MAX + " bytes: " + val);
}
if (TRACK_KEY_ACCESS) onKeyAccess(key);
native_set(key, val);
diff --git a/core/java/android/os/image/DynamicSystemManager.java b/core/java/android/os/image/DynamicSystemManager.java
index e8e47857ecba..9610b16a312c 100644
--- a/core/java/android/os/image/DynamicSystemManager.java
+++ b/core/java/android/os/image/DynamicSystemManager.java
@@ -16,13 +16,16 @@
package android.os.image;
+import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
import android.content.Context;
import android.gsi.AvbPublicKey;
import android.gsi.GsiProgress;
+import android.gsi.IGsiService;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
+import android.util.Pair;
/**
* The DynamicSystemManager offers a mechanism to use a new system image temporarily. After the
@@ -138,17 +141,18 @@ public class DynamicSystemManager {
* @param name The DSU partition name
* @param size Size of the DSU image in bytes
* @param readOnly True if the partition is read only, e.g. system.
- * @return {@code true} if the call succeeds. {@code false} either the device does not contain
- * enough space or a DynamicSystem is currently in use where the {@link #isInUse} would be
- * true.
+ * @return {@code Integer} an IGsiService.INSTALL_* status code. {@link Session} an installation
+ * session object if successful, otherwise {@code null}.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
- public Session createPartition(String name, long size, boolean readOnly) {
+ public @NonNull Pair<Integer, Session> createPartition(
+ String name, long size, boolean readOnly) {
try {
- if (mService.createPartition(name, size, readOnly)) {
- return new Session();
+ int status = mService.createPartition(name, size, readOnly);
+ if (status == IGsiService.INSTALL_OK) {
+ return new Pair<>(status, new Session());
} else {
- return null;
+ return new Pair<>(status, null);
}
} catch (RemoteException e) {
throw new RuntimeException(e.toString());
diff --git a/core/java/android/os/image/IDynamicSystemService.aidl b/core/java/android/os/image/IDynamicSystemService.aidl
index 4e69952fac2f..755368a85c40 100644
--- a/core/java/android/os/image/IDynamicSystemService.aidl
+++ b/core/java/android/os/image/IDynamicSystemService.aidl
@@ -35,10 +35,10 @@ interface IDynamicSystemService
* @param name The DSU partition name
* @param size Size of the DSU image in bytes
* @param readOnly True if this partition is readOnly
- * @return true if the call succeeds
+ * @return IGsiService.INSTALL_* status code
*/
@EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
- boolean createPartition(@utf8InCpp String name, long size, boolean readOnly);
+ int createPartition(@utf8InCpp String name, long size, boolean readOnly);
/**
* Complete the current partition installation.
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 93c1c20f8252..1777f56691a7 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -867,8 +867,8 @@ public final class DeviceConfig {
/**
* Delete a property with the provided name and value in the provided namespace
*
- * @param namespace The namespace containing the property to create or update.
- * @param name The name of the property to create or update.
+ * @param namespace The namespace containing the property to delete.
+ * @param name The name of the property to delete.
* @return True if the property was deleted or it did not exist in the first place.
* False if the storage implementation throws errors.
* @hide
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index d0fd2b393633..509f4d996ae9 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -350,6 +350,53 @@ public class TextUtils {
return ret;
}
+
+ /**
+ * Returns the longest prefix of a string for which the UTF-8 encoding fits into the given
+ * number of bytes, with the additional guarantee that the string is not truncated in the middle
+ * of a valid surrogate pair.
+ *
+ * <p>Unpaired surrogates are counted as taking 3 bytes of storage. However, a subsequent
+ * attempt to actually encode a string containing unpaired surrogates is likely to be rejected
+ * by the UTF-8 implementation.
+ *
+ * (copied from google/thirdparty)
+ *
+ * @param str a string
+ * @param maxbytes the maximum number of UTF-8 encoded bytes
+ * @return the beginning of the string, so that it uses at most maxbytes bytes in UTF-8
+ * @throws IndexOutOfBoundsException if maxbytes is negative
+ *
+ * @hide
+ */
+ public static String truncateStringForUtf8Storage(String str, int maxbytes) {
+ if (maxbytes < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ int bytes = 0;
+ for (int i = 0, len = str.length(); i < len; i++) {
+ char c = str.charAt(i);
+ if (c < 0x80) {
+ bytes += 1;
+ } else if (c < 0x800) {
+ bytes += 2;
+ } else if (c < Character.MIN_SURROGATE
+ || c > Character.MAX_SURROGATE
+ || str.codePointAt(i) < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+ bytes += 3;
+ } else {
+ bytes += 4;
+ i += (bytes > maxbytes) ? 0 : 1;
+ }
+ if (bytes > maxbytes) {
+ return str.substring(0, i);
+ }
+ }
+ return str;
+ }
+
+
/**
* Returns a string containing the tokens joined by delimiters.
*
diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java
index 4a20ad0f33f5..fc2c8cca9796 100644
--- a/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java
+++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java
@@ -33,7 +33,6 @@ import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.os.Build;
-import android.os.storage.StorageManager;
import android.provider.Settings;
import android.text.BidiFormatter;
import android.view.LayoutInflater;
@@ -282,19 +281,7 @@ public final class AccessibilityTargetHelper {
Context.LAYOUT_INFLATER_SERVICE);
final View content = inflater.inflate(
- R.layout.accessibility_enable_service_encryption_warning, /* root= */ null);
-
- final TextView encryptionWarningView = (TextView) content.findViewById(
- R.id.accessibility_encryption_warning);
- if (StorageManager.isNonDefaultBlockEncrypted()) {
- final String text = context.getString(
- R.string.accessibility_enable_service_encryption_warning,
- getServiceName(context, target.getLabel()));
- encryptionWarningView.setText(text);
- encryptionWarningView.setVisibility(View.VISIBLE);
- } else {
- encryptionWarningView.setVisibility(View.GONE);
- }
+ R.layout.accessibility_enable_service_warning, /* root= */ null);
final ImageView dialogIcon = content.findViewById(
R.id.accessibility_permissionDialog_icon);
diff --git a/core/res/res/layout/accessibility_enable_service_encryption_warning.xml b/core/res/res/layout/accessibility_enable_service_warning.xml
index 400051660592..01ef10177c5a 100644
--- a/core/res/res/layout/accessibility_enable_service_encryption_warning.xml
+++ b/core/res/res/layout/accessibility_enable_service_warning.xml
@@ -54,14 +54,6 @@
android:fontFamily="google-sans-medium"/>
<TextView
- android:id="@+id/accessibility_encryption_warning"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:padding="10dip"
- android:textAlignment="viewStart"
- android:textAppearance="?android:attr/textAppearanceMedium"/>
-
- <TextView
android:id="@+id/accessibility_permissionDialog_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 76631926a52a..db0cc277c3af 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4687,13 +4687,6 @@
<xliff:g id="service" example="TalkBack">%1$s</xliff:g> to have full control of your
device?</string>
- <!-- Warning that the device data will not be encrypted with password or PIN if
- enabling an accessibility service and there is a secure lock setup. [CHAR LIMIT=NONE] -->
- <string name="accessibility_enable_service_encryption_warning">If you turn on
- <xliff:g id="service" example="TalkBack">%1$s</xliff:g>, your device won’t use your screen
- lock to enhance data encryption.
- </string>
-
<!-- Warning description that explains that it's appropriate for accessibility
services to have full control to help users with accessibility needs. [CHAR LIMIT=NONE] -->
<string name="accessibility_service_warning_description">Full control is appropriate for apps
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index bacd25d026d4..a296aa5fbae5 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3414,14 +3414,12 @@
<java-symbol type="string" name="accessibility_edit_shortcut_menu_volume_title" />
<java-symbol type="string" name="accessibility_uncheck_legacy_item_warning" />
- <java-symbol type="layout" name="accessibility_enable_service_encryption_warning" />
+ <java-symbol type="layout" name="accessibility_enable_service_warning" />
<java-symbol type="id" name="accessibility_permissionDialog_icon" />
<java-symbol type="id" name="accessibility_permissionDialog_title" />
- <java-symbol type="id" name="accessibility_encryption_warning" />
<java-symbol type="id" name="accessibility_permission_enable_allow_button" />
<java-symbol type="id" name="accessibility_permission_enable_deny_button" />
<java-symbol type="string" name="accessibility_enable_service_title" />
- <java-symbol type="string" name="accessibility_enable_service_encryption_warning" />
<java-symbol type="layout" name="accessibility_shortcut_chooser_item" />
<java-symbol type="id" name="accessibility_shortcut_target_checkbox" />
diff --git a/core/tests/coretests/src/android/text/TextUtilsTest.java b/core/tests/coretests/src/android/text/TextUtilsTest.java
index a0fc34923a4d..c4bcfd4cf117 100644
--- a/core/tests/coretests/src/android/text/TextUtilsTest.java
+++ b/core/tests/coretests/src/android/text/TextUtilsTest.java
@@ -43,6 +43,7 @@ import com.google.android.collect.Lists;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -782,6 +783,81 @@ public class TextUtilsTest {
}
@Test
+ public void truncateStringForUtf8Storage() {
+ assertEquals("", TextUtils.truncateStringForUtf8Storage("abc", 0));
+
+ //================ long normal case ================
+ StringBuilder builder = new StringBuilder();
+
+ int n = 50;
+ for (int i = 0; i < 2 * n; i++) {
+ builder.append("哈");
+ }
+ String initial = builder.toString();
+ String result = TextUtils.truncateStringForUtf8Storage(initial, n);
+
+ // Result should be the beginning of initial
+ assertTrue(initial.startsWith(result));
+
+ // Result should take less than n bytes in UTF-8
+ assertTrue(result.getBytes(StandardCharsets.UTF_8).length <= n);
+
+ // result + the next codePoint should take strictly more than
+ // n bytes in UTF-8
+ assertTrue(initial.substring(0, initial.offsetByCodePoints(result.length(), 1))
+ .getBytes(StandardCharsets.UTF_8).length > n);
+
+ // =================== short normal case =====================
+ String s = "sf\u20ACgk\u00E9ls\u00E9fg";
+ result = TextUtils.truncateStringForUtf8Storage(s, 100);
+ assertEquals(s, result);
+ }
+
+ @Test
+ public void testTruncateInMiddleOfSurrogate() {
+ StringBuilder builder = new StringBuilder();
+ String beginning = "a";
+ builder.append(beginning);
+ builder.append(Character.toChars(0x1D11E));
+
+ String result = TextUtils.truncateStringForUtf8Storage(builder.toString(), 3);
+
+ // \u1D11E is a surrogate and needs 4 bytes in UTF-8. beginning == "a" uses
+ // only 1 bytes in UTF8
+ // As we allow only 3 bytes for the whole string, so just 2 for this
+ // codePoint, there is not enough place and the string will be truncated
+ // just before it
+ assertEquals(beginning, result);
+ }
+
+ @Test
+ public void testTruncateInMiddleOfChar() {
+ StringBuilder builder = new StringBuilder();
+ String beginning = "a";
+ builder.append(beginning);
+ builder.append(Character.toChars(0x20AC));
+
+ String result = TextUtils.truncateStringForUtf8Storage(builder.toString(), 3);
+
+ // Like above, \u20AC uses 3 bytes in UTF-8, with "beginning", that makes
+ // 4 bytes so it is too big and should be truncated
+ assertEquals(beginning, result);
+ }
+
+ @Test
+ public void testTruncateSubString() {
+ String test = "sdgkl;hjsl;gjhdgkljdfhglkdj";
+ String sub = test.substring(10, 20);
+ String res = TextUtils.truncateStringForUtf8Storage(sub, 255);
+ assertEquals(sub, res);
+ }
+
+ @Test(expected = IndexOutOfBoundsException.class)
+ public void truncateStringForUtf8StorageThrowsExceptionForNegativeSize() {
+ TextUtils.truncateStringForUtf8Storage("abc", -1);
+ }
+
+ @Test
public void length() {
assertEquals(0, TextUtils.length(null));
assertEquals(0, TextUtils.length(""));
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index 3a3565941489..55626844594d 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -110,6 +110,7 @@ public class DynamicSystemInstallationService extends Service
private static final int EVENT_DSU_PROGRESS_UPDATE = 120000;
private static final int EVENT_DSU_INSTALL_COMPLETE = 120001;
private static final int EVENT_DSU_INSTALL_FAILED = 120002;
+ private static final int EVENT_DSU_INSTALL_INSUFFICIENT_SPACE = 120003;
protected static void logEventProgressUpdate(
String partitionName,
@@ -136,6 +137,10 @@ public class DynamicSystemInstallationService extends Service
EventLog.writeEvent(EVENT_DSU_INSTALL_FAILED, cause);
}
+ protected static void logEventInsufficientSpace() {
+ EventLog.writeEvent(EVENT_DSU_INSTALL_INSUFFICIENT_SPACE);
+ }
+
/*
* IPC
*/
@@ -258,6 +263,8 @@ public class DynamicSystemInstallationService extends Service
if (result == RESULT_CANCELLED) {
logEventFailed("Dynamic System installation task is canceled by the user.");
+ } else if (detail instanceof InstallationAsyncTask.InsufficientSpaceException) {
+ logEventInsufficientSpace();
} else {
logEventFailed("error: " + detail);
}
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags
index 407314384be8..8d8be1030b8e 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags
@@ -5,3 +5,4 @@ option java_package com.android.dynsystem
120000 dsu_progress_update (partition_name|3),(installed_bytes|2|5),(total_bytes|2|5),(partition_number|1|5),(total_partition_number|1|5),(total_progress_percentage|1|5)
120001 dsu_install_complete
120002 dsu_install_failed (cause|3)
+120003 dsu_install_insufficient_space
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
index 38d851eb76aa..62e53d62fd2a 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
@@ -18,6 +18,7 @@ package com.android.dynsystem;
import android.content.Context;
import android.gsi.AvbPublicKey;
+import android.gsi.IGsiService;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
@@ -27,6 +28,7 @@ import android.os.SystemProperties;
import android.os.image.DynamicSystemManager;
import android.service.persistentdata.PersistentDataBlockManager;
import android.util.Log;
+import android.util.Pair;
import android.util.Range;
import android.webkit.URLUtil;
@@ -106,8 +108,15 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
}
}
+ static class InsufficientSpaceException extends IOException {
+ InsufficientSpaceException(String message) {
+ super(message);
+ }
+ }
+
/** UNSET means the installation is not completed */
static final int RESULT_UNSET = 0;
+
static final int RESULT_OK = 1;
static final int RESULT_CANCELLED = 2;
static final int RESULT_ERROR_IO = 3;
@@ -157,6 +166,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
private final boolean mIsNetworkUrl;
private final boolean mIsDeviceBootloaderUnlocked;
private final boolean mWantScratchPartition;
+ private int mCreatePartitionStatus;
private DynamicSystemManager.Session mInstallationSession;
private KeyRevocationList mKeyRevocationList;
@@ -364,7 +374,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
mIsZip = true;
} else {
throw new UnsupportedFormatException(
- String.format(Locale.US, "Unsupported file format: %s", mUrl));
+ String.format(Locale.US, "Unsupported file format: %s", mUrl));
}
if (mIsNetworkUrl) {
@@ -435,14 +445,19 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
throws IOException {
Log.d(TAG, "Creating writable partition: " + partitionName + ", size: " + partitionSize);
- Thread thread = new Thread() {
- @Override
- public void run() {
- mInstallationSession =
- mDynSystem.createPartition(
- partitionName, partitionSize, /* readOnly= */ false);
- }
- };
+ mCreatePartitionStatus = 0;
+ mInstallationSession = null;
+ Thread thread =
+ new Thread() {
+ @Override
+ public void run() {
+ Pair<Integer, DynamicSystemManager.Session> result =
+ mDynSystem.createPartition(
+ partitionName, partitionSize, /* readOnly = */ false);
+ mCreatePartitionStatus = result.first;
+ mInstallationSession = result.second;
+ }
+ };
initPartitionProgress(partitionName, partitionSize, /* readonly = */ false);
publishProgress(/* installedSize = */ 0L);
@@ -468,13 +483,17 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
}
}
- if (prevInstalledSize != partitionSize) {
- publishProgress(partitionSize);
- }
-
if (mInstallationSession == null) {
- throw new IOException(
- "Failed to start installation with requested size: " + partitionSize);
+ if (mCreatePartitionStatus == IGsiService.INSTALL_ERROR_NO_SPACE
+ || mCreatePartitionStatus == IGsiService.INSTALL_ERROR_FILE_SYSTEM_CLUTTERED) {
+ throw new InsufficientSpaceException(
+ "Failed to create "
+ + partitionName
+ + " partition: storage media has insufficient free space");
+ } else {
+ throw new IOException(
+ "Failed to start installation with requested size: " + partitionSize);
+ }
}
// Reset installation session and verify that installation completes successfully.
@@ -482,6 +501,11 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
if (!mDynSystem.closePartition()) {
throw new IOException("Failed to complete partition installation: " + partitionName);
}
+
+ // Ensure a 100% mark is published.
+ if (prevInstalledSize != partitionSize) {
+ publishProgress(partitionSize);
+ }
}
private void installScratch() throws IOException {
@@ -606,10 +630,19 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
throw new IOException("Cannot get raw size for " + partitionName);
}
- Thread thread = new Thread(() -> {
- mInstallationSession =
- mDynSystem.createPartition(partitionName, partitionSize, true);
- });
+ mCreatePartitionStatus = 0;
+ mInstallationSession = null;
+ Thread thread =
+ new Thread() {
+ @Override
+ public void run() {
+ Pair<Integer, DynamicSystemManager.Session> result =
+ mDynSystem.createPartition(
+ partitionName, partitionSize, /* readOnly = */ true);
+ mCreatePartitionStatus = result.first;
+ mInstallationSession = result.second;
+ }
+ };
Log.d(TAG, "Start creating partition: " + partitionName);
thread.start();
@@ -627,8 +660,16 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
}
if (mInstallationSession == null) {
- throw new IOException(
- "Failed to start installation with requested size: " + partitionSize);
+ if (mCreatePartitionStatus == IGsiService.INSTALL_ERROR_NO_SPACE
+ || mCreatePartitionStatus == IGsiService.INSTALL_ERROR_FILE_SYSTEM_CLUTTERED) {
+ throw new InsufficientSpaceException(
+ "Failed to create "
+ + partitionName
+ + " partition: storage media has insufficient free space");
+ } else {
+ throw new IOException(
+ "Failed to start installation with requested size: " + partitionSize);
+ }
}
Log.d(TAG, "Start installing: " + partitionName);
@@ -688,11 +729,6 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
installedSize += numBytesRead;
}
- // Ensure a 100% mark is published.
- if (prevInstalledSize != partitionSize) {
- publishProgress(partitionSize);
- }
-
AvbPublicKey avbPublicKey = new AvbPublicKey();
if (!mInstallationSession.getAvbPublicKey(avbPublicKey)) {
imageValidationThrowOrWarning(new PublicKeyException("getAvbPublicKey() failed"));
@@ -708,6 +744,11 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
if (!mDynSystem.closePartition()) {
throw new IOException("Failed to complete partition installation: " + partitionName);
}
+
+ // Ensure a 100% mark is published.
+ if (prevInstalledSize != partitionSize) {
+ publishProgress(partitionSize);
+ }
}
private static String toHexString(byte[] bytes) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
index e9dea65c2078..d558336a1285 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
@@ -237,7 +237,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
- sharingIntent.setType("image/png");
+ sharingIntent.setDataAndType(uri, "image/png");
sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
// Include URI in ClipData also, so that grantPermission picks it up.
// We don't use setData here because some apps interpret this as "to:".
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index e924012c8892..99e12a8f9f55 100644
--- a/services/core/java/com/android/server/DynamicSystemService.java
+++ b/services/core/java/com/android/server/DynamicSystemService.java
@@ -119,14 +119,13 @@ public class DynamicSystemService extends IDynamicSystemService.Stub {
@Override
@EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
- public boolean createPartition(String name, long size, boolean readOnly)
- throws RemoteException {
+ public int createPartition(String name, long size, boolean readOnly) throws RemoteException {
IGsiService service = getGsiService();
- if (service.createPartition(name, size, readOnly) != 0) {
- Slog.i(TAG, "Failed to install " + name);
- return false;
+ int status = service.createPartition(name, size, readOnly);
+ if (status != IGsiService.INSTALL_OK) {
+ Slog.i(TAG, "Failed to create partition: " + name);
}
- return true;
+ return status;
}
@Override
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 597f7f284730..be38005abb63 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -544,6 +544,7 @@ public class VcnGatewayConnection extends StateMachine {
private final boolean mIsMobileDataEnabled;
@NonNull private final IpSecManager mIpSecManager;
+ @NonNull private final ConnectivityManager mConnectivityManager;
@Nullable private IpSecTunnelInterface mTunnelIface = null;
@@ -701,6 +702,7 @@ public class VcnGatewayConnection extends StateMachine {
mLastSnapshot,
mUnderlyingNetworkControllerCallback);
mIpSecManager = mVcnContext.getContext().getSystemService(IpSecManager.class);
+ mConnectivityManager = mVcnContext.getContext().getSystemService(ConnectivityManager.class);
addState(mDisconnectedState);
addState(mDisconnectingState);
@@ -1683,6 +1685,14 @@ public class VcnGatewayConnection extends StateMachine {
clearFailedAttemptCounterAndSafeModeAlarm();
break;
case NetworkAgent.VALIDATION_STATUS_NOT_VALID:
+ // Trigger re-validation of underlying networks; if it
+ // fails, the VCN will attempt to migrate away.
+ if (mUnderlying != null) {
+ mConnectivityManager.reportNetworkConnectivity(
+ mUnderlying.network,
+ false /* hasConnectivity */);
+ }
+
// Will only set a new alarm if no safe mode alarm is
// currently scheduled.
setSafeModeAlarm();
@@ -1869,6 +1879,10 @@ public class VcnGatewayConnection extends StateMachine {
IpSecManager.DIRECTION_OUT);
updateNetworkAgent(mTunnelIface, mNetworkAgent, mChildConfig);
+
+ // Trigger re-validation after migration events.
+ mConnectivityManager.reportNetworkConnectivity(
+ mNetworkAgent.getNetwork(), false /* hasConnectivity */);
}
private void handleUnderlyingNetworkChanged(@NonNull Message msg) {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a5adf52051b9..b4825153bf0a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -11487,7 +11487,25 @@ public class TelephonyManager {
if (SubscriptionManager.isValidPhoneId(phoneId)) {
List<String> newList = updateTelephonyProperty(
TelephonyProperties.operator_alpha(), phoneId, name);
- TelephonyProperties.operator_alpha(newList);
+ try {
+ TelephonyProperties.operator_alpha(newList);
+ } catch (IllegalArgumentException e) { //property value is longer than the byte limit
+ Log.e(TAG, "setNetworkOperatorNameForPhone: ", e);
+
+ int numberOfEntries = newList.size();
+ int maxOperatorLength = //save 1 byte for joiner " , "
+ (SystemProperties.PROP_VALUE_MAX - numberOfEntries) / numberOfEntries;
+
+ //examine and truncate every operator and retry
+ for (int i = 0; i < newList.size(); i++) {
+ if (newList.get(i) != null) {
+ newList.set(i, TextUtils
+ .truncateStringForUtf8Storage(newList.get(i), maxOperatorLength));
+ }
+ }
+ TelephonyProperties.operator_alpha(newList);
+ Log.e(TAG, "successfully truncated operator_alpha: " + newList);
+ }
}
}
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 281b018b3395..b0ddf2c28dff 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -369,6 +369,10 @@ public class ApnSetting implements Parcelable {
public @interface AuthType {}
// Possible values for protocol which is defined in TS 27.007 section 10.1.1.
+ /** Unknown protocol.
+ * @hide
+ */
+ public static final int PROTOCOL_UNKNOWN = -1;
/** Internet protocol. */
public static final int PROTOCOL_IP = 0;
/** Internet protocol, version 6. */
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 883e2ad9b76e..7799113c5bf1 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2556,4 +2556,7 @@ interface ITelephony {
* for the slot, or {@code null} if none is resolved
*/
String getCarrierServicePackageNameForLogicalSlot(int logicalSlotIndex);
+
+ /** Check if telephony new data stack is enabled. */
+ boolean isUsingNewDataStack();
}
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index 4cfa93b4ecf9..841b81c2a282 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -252,6 +252,9 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
&& TEST_TCP_BUFFER_SIZES_2.equals(lp.getTcpBufferSizes())));
verify(mNetworkAgent)
.setUnderlyingNetworks(eq(singletonList(TEST_UNDERLYING_NETWORK_RECORD_2.network)));
+
+ // Verify revalidation is triggered on VCN network
+ verify(mConnMgr).reportNetworkConnectivity(eq(mNetworkAgent.getNetwork()), eq(false));
}
private void triggerChildOpened() {
@@ -425,6 +428,9 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
triggerValidation(NetworkAgent.VALIDATION_STATUS_NOT_VALID);
mTestLooper.dispatchAll();
+ verify(mConnMgr)
+ .reportNetworkConnectivity(eq(TEST_UNDERLYING_NETWORK_RECORD_1.network), eq(false));
+
final ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
verify(mDeps, times(2))
.newWakeupMessage(
diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp
index be09545abb45..383be56bb227 100644
--- a/tools/aapt2/util/Files.cpp
+++ b/tools/aapt2/util/Files.cpp
@@ -349,7 +349,7 @@ Maybe<std::vector<std::string>> FindFiles(const android::StringPiece& path, IDia
const std::string root_dir = path.to_string();
std::unique_ptr<DIR, decltype(closedir)*> d(opendir(root_dir.data()), closedir);
if (!d) {
- diag->Error(DiagMessage() << SystemErrorCodeToString(errno));
+ diag->Error(DiagMessage() << SystemErrorCodeToString(errno) << ": " << root_dir);
return {};
}