summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-12 18:53:04 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2022-05-12 18:53:04 +0000
commitfc1458f4f4aa816a11d71dc67c5f1e83e4cf8abb (patch)
tree41f6366d428821fb33bf87e6068ddd0c94140a01
parent2c50a3a7900919d5488db63b9eb8af67afdb4438 (diff)
parent780946834d26003c63c67116ffce0f1272450b84 (diff)
downloadbase-main-cg-testing-release.tar.gz
Merge "Snap for 8580505 from 821acc6177c2c6459d223e0a6ecef7f3d24d8876 to main-cg-testing-release" into main-cg-testing-releasemain-cg-testing-release
-rw-r--r--ApiDocs.bp6
-rw-r--r--api/api.go2
-rw-r--r--core/java/android/app/time/ExternalTimeSuggestion.java64
-rw-r--r--core/java/android/app/timedetector/GnssTimeSuggestion.java71
-rw-r--r--core/java/android/app/timedetector/ManualTimeSuggestion.java69
-rw-r--r--core/java/android/app/timedetector/NetworkTimeSuggestion.java78
-rw-r--r--core/java/android/app/timedetector/TelephonyTimeSuggestion.java57
-rw-r--r--core/java/android/app/timedetector/TimeDetector.java30
-rw-r--r--core/java/android/app/timedetector/TimeSuggestionHelper.java209
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp41
-rw-r--r--core/res/res/values/config_telephony.xml10
-rw-r--r--core/tests/PackageInstallerSessions/Android.bp2
-rw-r--r--core/tests/bugreports/Android.bp2
-rw-r--r--core/tests/coretests/Android.bp2
-rw-r--r--core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java63
-rw-r--r--core/tests/coretests/src/android/app/timedetector/GnssTimeSuggestionTest.java34
-rw-r--r--core/tests/coretests/src/android/app/timedetector/ManualTimeSuggestionTest.java34
-rw-r--r--core/tests/coretests/src/android/app/timedetector/NetworkTimeSuggestionTest.java34
-rw-r--r--core/tests/coretests/src/android/app/timedetector/TelephonyTimeSuggestionTest.java43
-rw-r--r--core/tests/coretests/src/android/app/timezonedetector/ShellCommandTestSupport.java6
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java2
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java24
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreEdECPrivateKey.java46
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreEdECPublicKey.java145
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java6
-rw-r--r--keystore/tests/src/android/security/keystore2/AndroidKeyStoreEdECPublicKeyTest.java123
-rw-r--r--packages/Shell/AndroidManifest.xml6
-rw-r--r--packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java2
-rw-r--r--services/core/OWNERS1
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceBroker.java7
-rw-r--r--services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java85
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java6
-rw-r--r--services/core/java/com/android/server/display/BrightnessTracker.java32
-rw-r--r--services/core/java/com/android/server/timedetector/EnvironmentImpl.java6
-rw-r--r--services/core/java/com/android/server/timedetector/TimeDetectorShellCommand.java85
-rw-r--r--services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java20
-rw-r--r--services/proguard.flags5
-rw-r--r--services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp2
-rw-r--r--services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java58
-rw-r--r--telephony/java/android/telephony/AnomalyReporter.java22
-rw-r--r--telephony/java/android/telephony/DataFailCause.java9
-rw-r--r--telephony/java/android/telephony/PhysicalChannelConfig.java34
-rw-r--r--telephony/java/android/telephony/data/ApnSetting.java11
-rw-r--r--telephony/java/android/telephony/data/DataCallResponse.java2
-rw-r--r--tests/ApkVerityTest/AndroidTest.xml2
47 files changed, 1358 insertions, 249 deletions
diff --git a/ApiDocs.bp b/ApiDocs.bp
index 39f055b578ab..a542c5cf245c 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -134,11 +134,7 @@ droidstubs {
defaults: ["android-non-updatable-doc-stubs-defaults"],
srcs: [":all-modules-public-stubs-source"],
args: metalava_framework_docs_args,
- api_levels_annotations_enabled: true,
- api_levels_annotations_dirs: [
- "sdk-dir",
- "api-versions-jars-dir",
- ],
+ api_levels_module: "api_versions_public",
aidl: {
include_dirs: [
"packages/modules/Connectivity/framework/aidl-export",
diff --git a/api/api.go b/api/api.go
index 9cd0132e2c6c..93f1354ce9e4 100644
--- a/api/api.go
+++ b/api/api.go
@@ -179,7 +179,7 @@ func createFilteredApiVersions(ctx android.LoadHookContext, modules []string) {
// Note: order matters: first parameter is the full api-versions.xml
// after that the stubs files in any order
// stubs files are all modules that export API surfaces EXCEPT ART
- props.Srcs = append([]string{":framework-doc-stubs{.api_versions.xml}"}, createSrcs(modules, ".stubs{.jar}")...)
+ props.Srcs = append([]string{":api_versions_public{.api_versions.xml}"}, createSrcs(modules, ".stubs{.jar}")...)
props.Dists = []android.Dist{{Targets: []string{"sdk"}}}
ctx.CreateModule(genrule.GenRuleFactory, &props)
}
diff --git a/core/java/android/app/time/ExternalTimeSuggestion.java b/core/java/android/app/time/ExternalTimeSuggestion.java
index a7c0e5c79607..a7828ab4c9dc 100644
--- a/core/java/android/app/time/ExternalTimeSuggestion.java
+++ b/core/java/android/app/time/ExternalTimeSuggestion.java
@@ -19,15 +19,14 @@ package android.app.time;
import android.annotation.CurrentTimeMillisLong;
import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.app.timedetector.TimeSuggestionHelper;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.ShellCommand;
import android.os.TimestampedValue;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
+import java.io.PrintWriter;
import java.util.List;
import java.util.Objects;
@@ -75,7 +74,9 @@ public final class ExternalTimeSuggestion implements Parcelable {
public static final @NonNull Creator<ExternalTimeSuggestion> CREATOR =
new Creator<ExternalTimeSuggestion>() {
public ExternalTimeSuggestion createFromParcel(Parcel in) {
- return ExternalTimeSuggestion.createFromParcel(in);
+ TimeSuggestionHelper helper = TimeSuggestionHelper.handleCreateFromParcel(
+ ExternalTimeSuggestion.class, in);
+ return new ExternalTimeSuggestion(helper);
}
public ExternalTimeSuggestion[] newArray(int size) {
@@ -83,10 +84,7 @@ public final class ExternalTimeSuggestion implements Parcelable {
}
};
- @NonNull
- private final TimestampedValue<Long> mUnixEpochTime;
- @Nullable
- private ArrayList<String> mDebugInfo;
+ @NonNull private final TimeSuggestionHelper mTimeSuggestionHelper;
/**
* Creates a time suggestion cross-referenced to the elapsed realtime clock. See {@link
@@ -98,17 +96,12 @@ public final class ExternalTimeSuggestion implements Parcelable {
*/
public ExternalTimeSuggestion(@ElapsedRealtimeLong long elapsedRealtimeMillis,
@CurrentTimeMillisLong long suggestionMillis) {
- mUnixEpochTime = new TimestampedValue(elapsedRealtimeMillis, suggestionMillis);
+ mTimeSuggestionHelper = new TimeSuggestionHelper(ExternalTimeSuggestion.class,
+ new TimestampedValue<>(elapsedRealtimeMillis, suggestionMillis));
}
- private static ExternalTimeSuggestion createFromParcel(Parcel in) {
- TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
- ExternalTimeSuggestion suggestion =
- new ExternalTimeSuggestion(utcTime.getReferenceTimeMillis(), utcTime.getValue());
- @SuppressWarnings("unchecked")
- ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
- suggestion.mDebugInfo = debugInfo;
- return suggestion;
+ private ExternalTimeSuggestion(@NonNull TimeSuggestionHelper helper) {
+ mTimeSuggestionHelper = Objects.requireNonNull(helper);
}
@Override
@@ -118,8 +111,7 @@ public final class ExternalTimeSuggestion implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(mUnixEpochTime, 0);
- dest.writeList(mDebugInfo);
+ mTimeSuggestionHelper.handleWriteToParcel(dest, flags);
}
/**
@@ -127,7 +119,7 @@ public final class ExternalTimeSuggestion implements Parcelable {
*/
@NonNull
public TimestampedValue<Long> getUnixEpochTime() {
- return mUnixEpochTime;
+ return mTimeSuggestionHelper.getUnixEpochTime();
}
/**
@@ -135,9 +127,7 @@ public final class ExternalTimeSuggestion implements Parcelable {
*/
@NonNull
public List<String> getDebugInfo() {
- return mDebugInfo == null
- ? Collections.emptyList()
- : Collections.unmodifiableList(mDebugInfo);
+ return mTimeSuggestionHelper.getDebugInfo();
}
/**
@@ -146,10 +136,7 @@ public final class ExternalTimeSuggestion implements Parcelable {
* #equals(Object)} and {@link #hashCode()}.
*/
public void addDebugInfo(@NonNull String... debugInfos) {
- if (mDebugInfo == null) {
- mDebugInfo = new ArrayList<>();
- }
- mDebugInfo.addAll(Arrays.asList(debugInfos));
+ mTimeSuggestionHelper.addDebugInfo(debugInfos);
}
@Override
@@ -161,18 +148,29 @@ public final class ExternalTimeSuggestion implements Parcelable {
return false;
}
ExternalTimeSuggestion that = (ExternalTimeSuggestion) o;
- return Objects.equals(mUnixEpochTime, that.mUnixEpochTime);
+ return mTimeSuggestionHelper.handleEquals(that.mTimeSuggestionHelper);
}
@Override
public int hashCode() {
- return Objects.hash(mUnixEpochTime);
+ return mTimeSuggestionHelper.hashCode();
}
@Override
public String toString() {
- return "ExternalTimeSuggestion{" + "mUnixEpochTime=" + mUnixEpochTime
- + ", mDebugInfo=" + mDebugInfo
- + '}';
+ return mTimeSuggestionHelper.handleToString();
+ }
+
+ /** @hide */
+ public static ExternalTimeSuggestion parseCommandLineArg(@NonNull ShellCommand cmd)
+ throws IllegalArgumentException {
+ return new ExternalTimeSuggestion(
+ TimeSuggestionHelper.handleParseCommandLineArg(ExternalTimeSuggestion.class, cmd));
+ }
+
+ /** @hide */
+ public static void printCommandLineOpts(PrintWriter pw) {
+ TimeSuggestionHelper.handlePrintCommandLineOpts(
+ pw, "External", ExternalTimeSuggestion.class);
}
}
diff --git a/core/java/android/app/timedetector/GnssTimeSuggestion.java b/core/java/android/app/timedetector/GnssTimeSuggestion.java
index 34f4565fb410..3531b19d0f65 100644
--- a/core/java/android/app/timedetector/GnssTimeSuggestion.java
+++ b/core/java/android/app/timedetector/GnssTimeSuggestion.java
@@ -17,30 +17,19 @@
package android.app.timedetector;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.ShellCommand;
import android.os.TimestampedValue;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
+import java.io.PrintWriter;
import java.util.List;
import java.util.Objects;
/**
* A time signal from a GNSS source.
*
- * <p>{@code unixEpochTime} is the suggested time. The {@code unixEpochTime.value} is the number of
- * milliseconds elapsed since 1/1/1970 00:00:00 UTC according to the Unix time system. The {@code
- * unixEpochTime.referenceTimeMillis} is the value of the elapsed realtime clock when the {@code
- * unixEpochTime.value} was established. Note that the elapsed realtime clock is considered accurate
- * but it is volatile, so time suggestions cannot be persisted across device resets.
- *
- * <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
- * record why the suggestion exists and how it was entered. This information exists only to aid in
- * debugging and therefore is used by {@link #toString()}, but it is not for use in detection
- * logic and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
+ * <p>See {@link TimeSuggestionHelper} for property information.
*
* @hide
*/
@@ -49,7 +38,9 @@ public final class GnssTimeSuggestion implements Parcelable {
public static final @NonNull Creator<GnssTimeSuggestion> CREATOR =
new Creator<GnssTimeSuggestion>() {
public GnssTimeSuggestion createFromParcel(Parcel in) {
- return GnssTimeSuggestion.createFromParcel(in);
+ TimeSuggestionHelper helper = TimeSuggestionHelper.handleCreateFromParcel(
+ GnssTimeSuggestion.class, in);
+ return new GnssTimeSuggestion(helper);
}
public GnssTimeSuggestion[] newArray(int size) {
@@ -57,21 +48,14 @@ public final class GnssTimeSuggestion implements Parcelable {
}
};
- @NonNull private final TimestampedValue<Long> mUnixEpochTime;
- @Nullable private ArrayList<String> mDebugInfo;
+ @NonNull private final TimeSuggestionHelper mTimeSuggestionHelper;
public GnssTimeSuggestion(@NonNull TimestampedValue<Long> unixEpochTime) {
- mUnixEpochTime = Objects.requireNonNull(unixEpochTime);
- Objects.requireNonNull(unixEpochTime.getValue());
+ mTimeSuggestionHelper = new TimeSuggestionHelper(GnssTimeSuggestion.class, unixEpochTime);
}
- private static GnssTimeSuggestion createFromParcel(Parcel in) {
- TimestampedValue<Long> unixEpochTime = in.readParcelable(null /* classLoader */);
- GnssTimeSuggestion suggestion = new GnssTimeSuggestion(unixEpochTime);
- @SuppressWarnings("unchecked")
- ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
- suggestion.mDebugInfo = debugInfo;
- return suggestion;
+ private GnssTimeSuggestion(@NonNull TimeSuggestionHelper helper) {
+ mTimeSuggestionHelper = Objects.requireNonNull(helper);
}
@Override
@@ -81,19 +65,17 @@ public final class GnssTimeSuggestion implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(mUnixEpochTime, 0);
- dest.writeList(mDebugInfo);
+ mTimeSuggestionHelper.handleWriteToParcel(dest, flags);
}
@NonNull
public TimestampedValue<Long> getUnixEpochTime() {
- return mUnixEpochTime;
+ return mTimeSuggestionHelper.getUnixEpochTime();
}
@NonNull
public List<String> getDebugInfo() {
- return mDebugInfo == null
- ? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
+ return mTimeSuggestionHelper.getDebugInfo();
}
/**
@@ -102,10 +84,7 @@ public final class GnssTimeSuggestion implements Parcelable {
* {@link #equals(Object)} and {@link #hashCode()}.
*/
public void addDebugInfo(String... debugInfos) {
- if (mDebugInfo == null) {
- mDebugInfo = new ArrayList<>();
- }
- mDebugInfo.addAll(Arrays.asList(debugInfos));
+ mTimeSuggestionHelper.addDebugInfo(debugInfos);
}
@Override
@@ -117,19 +96,29 @@ public final class GnssTimeSuggestion implements Parcelable {
return false;
}
GnssTimeSuggestion that = (GnssTimeSuggestion) o;
- return Objects.equals(mUnixEpochTime, that.mUnixEpochTime);
+ return mTimeSuggestionHelper.handleEquals(that.mTimeSuggestionHelper);
}
@Override
public int hashCode() {
- return Objects.hash(mUnixEpochTime);
+ return mTimeSuggestionHelper.hashCode();
}
@Override
public String toString() {
- return "GnssTimeSuggestion{"
- + "mUnixEpochTime=" + mUnixEpochTime
- + ", mDebugInfo=" + mDebugInfo
- + '}';
+ return mTimeSuggestionHelper.handleToString();
+ }
+
+ /** Parses command line args to create a {@link GnssTimeSuggestion}. */
+ public static GnssTimeSuggestion parseCommandLineArg(@NonNull ShellCommand cmd)
+ throws IllegalArgumentException {
+ TimeSuggestionHelper suggestionHelper =
+ TimeSuggestionHelper.handleParseCommandLineArg(GnssTimeSuggestion.class, cmd);
+ return new GnssTimeSuggestion(suggestionHelper);
+ }
+
+ /** Prints the command line args needed to create a {@link GnssTimeSuggestion}. */
+ public static void printCommandLineOpts(PrintWriter pw) {
+ TimeSuggestionHelper.handlePrintCommandLineOpts(pw, "GNSS", GnssTimeSuggestion.class);
}
}
diff --git a/core/java/android/app/timedetector/ManualTimeSuggestion.java b/core/java/android/app/timedetector/ManualTimeSuggestion.java
index 76db33b1c32b..b447799eb84c 100644
--- a/core/java/android/app/timedetector/ManualTimeSuggestion.java
+++ b/core/java/android/app/timedetector/ManualTimeSuggestion.java
@@ -20,27 +20,17 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.ShellCommand;
import android.os.TimestampedValue;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
+import java.io.PrintWriter;
import java.util.List;
import java.util.Objects;
/**
* A time signal from a manual (user provided) source.
*
- * <p>{@code unixEpochTime} is the suggested time. The {@code unixEpochTime.value} is the number of
- * milliseconds elapsed since 1/1/1970 00:00:00 UTC. The {@code unixEpochTime.referenceTimeMillis}
- * is the value of the elapsed realtime clock when the {@code unixEpochTime.value} was established.
- * Note that the elapsed realtime clock is considered accurate but it is volatile, so time
- * suggestions cannot be persisted across device resets.
- *
- * <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
- * record why the suggestion exists and how it was entered. This information exists only to aid in
- * debugging and therefore is used by {@link #toString()}, but it is not for use in detection
- * logic and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
+ * <p>See {@link TimeSuggestionHelper} for property information.
*
* @hide
*/
@@ -49,7 +39,9 @@ public final class ManualTimeSuggestion implements Parcelable {
public static final @NonNull Creator<ManualTimeSuggestion> CREATOR =
new Creator<ManualTimeSuggestion>() {
public ManualTimeSuggestion createFromParcel(Parcel in) {
- return ManualTimeSuggestion.createFromParcel(in);
+ TimeSuggestionHelper helper = TimeSuggestionHelper.handleCreateFromParcel(
+ ManualTimeSuggestion.class, in);
+ return new ManualTimeSuggestion(helper);
}
public ManualTimeSuggestion[] newArray(int size) {
@@ -57,21 +49,14 @@ public final class ManualTimeSuggestion implements Parcelable {
}
};
- @NonNull private final TimestampedValue<Long> mUnixEpochTime;
- @Nullable private ArrayList<String> mDebugInfo;
+ @NonNull private final TimeSuggestionHelper mTimeSuggestionHelper;
public ManualTimeSuggestion(@NonNull TimestampedValue<Long> unixEpochTime) {
- mUnixEpochTime = Objects.requireNonNull(unixEpochTime);
- Objects.requireNonNull(unixEpochTime.getValue());
+ mTimeSuggestionHelper = new TimeSuggestionHelper(ManualTimeSuggestion.class, unixEpochTime);
}
- private static ManualTimeSuggestion createFromParcel(Parcel in) {
- TimestampedValue<Long> unixEpochTime = in.readParcelable(null /* classLoader */);
- ManualTimeSuggestion suggestion = new ManualTimeSuggestion(unixEpochTime);
- @SuppressWarnings("unchecked")
- ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
- suggestion.mDebugInfo = debugInfo;
- return suggestion;
+ private ManualTimeSuggestion(@NonNull TimeSuggestionHelper helper) {
+ mTimeSuggestionHelper = Objects.requireNonNull(helper);
}
@Override
@@ -81,19 +66,17 @@ public final class ManualTimeSuggestion implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(mUnixEpochTime, 0);
- dest.writeList(mDebugInfo);
+ mTimeSuggestionHelper.handleWriteToParcel(dest, flags);
}
@NonNull
public TimestampedValue<Long> getUnixEpochTime() {
- return mUnixEpochTime;
+ return mTimeSuggestionHelper.getUnixEpochTime();
}
@NonNull
public List<String> getDebugInfo() {
- return mDebugInfo == null
- ? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
+ return mTimeSuggestionHelper.getDebugInfo();
}
/**
@@ -102,10 +85,7 @@ public final class ManualTimeSuggestion implements Parcelable {
* {@link #equals(Object)} and {@link #hashCode()}.
*/
public void addDebugInfo(String... debugInfos) {
- if (mDebugInfo == null) {
- mDebugInfo = new ArrayList<>();
- }
- mDebugInfo.addAll(Arrays.asList(debugInfos));
+ mTimeSuggestionHelper.addDebugInfo(debugInfos);
}
@Override
@@ -117,19 +97,28 @@ public final class ManualTimeSuggestion implements Parcelable {
return false;
}
ManualTimeSuggestion that = (ManualTimeSuggestion) o;
- return Objects.equals(mUnixEpochTime, that.mUnixEpochTime);
+ return mTimeSuggestionHelper.handleEquals(that.mTimeSuggestionHelper);
}
@Override
public int hashCode() {
- return Objects.hash(mUnixEpochTime);
+ return mTimeSuggestionHelper.hashCode();
}
@Override
public String toString() {
- return "ManualTimeSuggestion{"
- + "mUnixEpochTime=" + mUnixEpochTime
- + ", mDebugInfo=" + mDebugInfo
- + '}';
+ return mTimeSuggestionHelper.handleToString();
+ }
+
+ /** @hide */
+ public static ManualTimeSuggestion parseCommandLineArg(@NonNull ShellCommand cmd)
+ throws IllegalArgumentException {
+ return new ManualTimeSuggestion(
+ TimeSuggestionHelper.handleParseCommandLineArg(ManualTimeSuggestion.class, cmd));
+ }
+
+ /** @hide */
+ public static void printCommandLineOpts(PrintWriter pw) {
+ TimeSuggestionHelper.handlePrintCommandLineOpts(pw, "Manual", ManualTimeSuggestion.class);
}
}
diff --git a/core/java/android/app/timedetector/NetworkTimeSuggestion.java b/core/java/android/app/timedetector/NetworkTimeSuggestion.java
index e22f1d6ea8be..e93c75cb0a0c 100644
--- a/core/java/android/app/timedetector/NetworkTimeSuggestion.java
+++ b/core/java/android/app/timedetector/NetworkTimeSuggestion.java
@@ -17,31 +17,19 @@
package android.app.timedetector;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.ShellCommand;
import android.os.TimestampedValue;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
+import java.io.PrintWriter;
import java.util.List;
import java.util.Objects;
/**
* A time signal from a network time source like NTP.
*
- * <p>{@code unixEpochTime} contains the suggested time. The {@code unixEpochTime.value} is the
- * number of milliseconds elapsed since 1/1/1970 00:00:00 UTC according to the Unix time system.
- * The {@code unixEpochTime.referenceTimeMillis} is the value of the elapsed realtime clock when
- * the {@code unixEpochTime.value} was established. Note that the elapsed realtime clock is
- * considered accurate but it is volatile, so time suggestions cannot be persisted across device
- * resets.
- *
- * <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
- * record why the suggestion exists and how it was determined. This information exists only to aid
- * in debugging and therefore is used by {@link #toString()}, but it is not for use in detection
- * logic and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
+ * <p>See {@link TimeSuggestionHelper} for property information.
*
* @hide
*/
@@ -50,7 +38,9 @@ public final class NetworkTimeSuggestion implements Parcelable {
public static final @NonNull Creator<NetworkTimeSuggestion> CREATOR =
new Creator<NetworkTimeSuggestion>() {
public NetworkTimeSuggestion createFromParcel(Parcel in) {
- return NetworkTimeSuggestion.createFromParcel(in);
+ TimeSuggestionHelper helper = TimeSuggestionHelper.handleCreateFromParcel(
+ NetworkTimeSuggestion.class, in);
+ return new NetworkTimeSuggestion(helper);
}
public NetworkTimeSuggestion[] newArray(int size) {
@@ -58,21 +48,15 @@ public final class NetworkTimeSuggestion implements Parcelable {
}
};
- @NonNull private final TimestampedValue<Long> mUnixEpochTime;
- @Nullable private ArrayList<String> mDebugInfo;
+ @NonNull private final TimeSuggestionHelper mTimeSuggestionHelper;
public NetworkTimeSuggestion(@NonNull TimestampedValue<Long> unixEpochTime) {
- mUnixEpochTime = Objects.requireNonNull(unixEpochTime);
- Objects.requireNonNull(unixEpochTime.getValue());
+ mTimeSuggestionHelper = new TimeSuggestionHelper(
+ NetworkTimeSuggestion.class, unixEpochTime);
}
- private static NetworkTimeSuggestion createFromParcel(Parcel in) {
- TimestampedValue<Long> unixEpochTime = in.readParcelable(null /* classLoader */);
- NetworkTimeSuggestion suggestion = new NetworkTimeSuggestion(unixEpochTime);
- @SuppressWarnings("unchecked")
- ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
- suggestion.mDebugInfo = debugInfo;
- return suggestion;
+ private NetworkTimeSuggestion(@NonNull TimeSuggestionHelper helper) {
+ mTimeSuggestionHelper = Objects.requireNonNull(helper);
}
@Override
@@ -82,35 +66,30 @@ public final class NetworkTimeSuggestion implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(mUnixEpochTime, 0);
- dest.writeList(mDebugInfo);
+ mTimeSuggestionHelper.handleWriteToParcel(dest, flags);
}
@NonNull
public TimestampedValue<Long> getUnixEpochTime() {
- return mUnixEpochTime;
+ return mTimeSuggestionHelper.getUnixEpochTime();
}
@NonNull
public List<String> getDebugInfo() {
- return mDebugInfo == null
- ? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
+ return mTimeSuggestionHelper.getDebugInfo();
}
/**
* Associates information with the instance that can be useful for debugging / logging. The
- * information is present in {@link #toString()} but is not considered for
- * {@link #equals(Object)} and {@link #hashCode()}.
+ * information is present in {@link #toString()} but is not considered for {@link
+ * #equals(Object)} and {@link #hashCode()}.
*/
public void addDebugInfo(String... debugInfos) {
- if (mDebugInfo == null) {
- mDebugInfo = new ArrayList<>();
- }
- mDebugInfo.addAll(Arrays.asList(debugInfos));
+ mTimeSuggestionHelper.addDebugInfo(debugInfos);
}
@Override
- public boolean equals(@Nullable Object o) {
+ public boolean equals(Object o) {
if (this == o) {
return true;
}
@@ -118,19 +97,28 @@ public final class NetworkTimeSuggestion implements Parcelable {
return false;
}
NetworkTimeSuggestion that = (NetworkTimeSuggestion) o;
- return Objects.equals(mUnixEpochTime, that.mUnixEpochTime);
+ return mTimeSuggestionHelper.handleEquals(that.mTimeSuggestionHelper);
}
@Override
public int hashCode() {
- return Objects.hash(mUnixEpochTime);
+ return mTimeSuggestionHelper.hashCode();
}
@Override
public String toString() {
- return "NetworkTimeSuggestion{"
- + "mUnixEpochTime=" + mUnixEpochTime
- + ", mDebugInfo=" + mDebugInfo
- + '}';
+ return mTimeSuggestionHelper.handleToString();
+ }
+
+ /** @hide */
+ public static NetworkTimeSuggestion parseCommandLineArg(@NonNull ShellCommand cmd)
+ throws IllegalArgumentException {
+ return new NetworkTimeSuggestion(
+ TimeSuggestionHelper.handleParseCommandLineArg(NetworkTimeSuggestion.class, cmd));
+ }
+
+ /** @hide */
+ public static void printCommandLineOpts(PrintWriter pw) {
+ TimeSuggestionHelper.handlePrintCommandLineOpts(pw, "Network", NetworkTimeSuggestion.class);
}
}
diff --git a/core/java/android/app/timedetector/TelephonyTimeSuggestion.java b/core/java/android/app/timedetector/TelephonyTimeSuggestion.java
index 4ff75174ab57..6f204d661004 100644
--- a/core/java/android/app/timedetector/TelephonyTimeSuggestion.java
+++ b/core/java/android/app/timedetector/TelephonyTimeSuggestion.java
@@ -20,8 +20,10 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.ShellCommand;
import android.os.TimestampedValue;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -88,6 +90,61 @@ public final class TelephonyTimeSuggestion implements Parcelable {
return suggestion;
}
+ /** @hide */
+ public static TelephonyTimeSuggestion parseCommandLineArg(@NonNull ShellCommand cmd)
+ throws IllegalArgumentException {
+ Integer slotIndex = null;
+ Long referenceTimeMillis = null;
+ Long unixEpochTimeMillis = null;
+ String opt;
+ while ((opt = cmd.getNextArg()) != null) {
+ switch (opt) {
+ case "--slot_index": {
+ slotIndex = Integer.parseInt(cmd.getNextArgRequired());
+ break;
+ }
+ case "--reference_time": {
+ referenceTimeMillis = Long.parseLong(cmd.getNextArgRequired());
+ break;
+ }
+ case "--unix_epoch_time": {
+ unixEpochTimeMillis = Long.parseLong(cmd.getNextArgRequired());
+ break;
+ }
+ default: {
+ throw new IllegalArgumentException("Unknown option: " + opt);
+ }
+ }
+ }
+
+ if (slotIndex == null) {
+ throw new IllegalArgumentException("No slotIndex specified.");
+ }
+ if (referenceTimeMillis == null) {
+ throw new IllegalArgumentException("No referenceTimeMillis specified.");
+ }
+ if (unixEpochTimeMillis == null) {
+ throw new IllegalArgumentException("No unixEpochTimeMillis specified.");
+ }
+
+ TimestampedValue<Long> timeSignal =
+ new TimestampedValue<>(referenceTimeMillis, unixEpochTimeMillis);
+ Builder builder = new Builder(slotIndex)
+ .setUnixEpochTime(timeSignal)
+ .addDebugInfo("Command line injection");
+ return builder.build();
+ }
+
+ /** @hide */
+ public static void printCommandLineOpts(PrintWriter pw) {
+ pw.println("Telephony suggestion options:");
+ pw.println(" --slot_index <number>");
+ pw.println(" --reference_time <elapsed realtime millis>");
+ pw.println(" --unix_epoch_time <Unix epoch time millis>");
+ pw.println();
+ pw.println("See " + TelephonyTimeSuggestion.class.getName() + " for more information");
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java
index a3562301cde7..f0d777611620 100644
--- a/core/java/android/app/timedetector/TimeDetector.java
+++ b/core/java/android/app/timedetector/TimeDetector.java
@@ -44,6 +44,36 @@ public interface TimeDetector {
String SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED = "is_auto_detection_enabled";
/**
+ * A shell command that injects a manual time suggestion.
+ * @hide
+ */
+ String SHELL_COMMAND_SUGGEST_MANUAL_TIME = "suggest_manual_time";
+
+ /**
+ * A shell command that injects a telephony time suggestion.
+ * @hide
+ */
+ String SHELL_COMMAND_SUGGEST_TELEPHONY_TIME = "suggest_telephony_time";
+
+ /**
+ * A shell command that injects a network time suggestion.
+ * @hide
+ */
+ String SHELL_COMMAND_SUGGEST_NETWORK_TIME = "suggest_network_time";
+
+ /**
+ * A shell command that injects a GNSS time suggestion.
+ * @hide
+ */
+ String SHELL_COMMAND_SUGGEST_GNSS_TIME = "suggest_gnss_time";
+
+ /**
+ * A shell command that injects a external time suggestion.
+ * @hide
+ */
+ String SHELL_COMMAND_SUGGEST_EXTERNAL_TIME = "suggest_external_time";
+
+ /**
* A shared utility method to create a {@link ManualTimeSuggestion}.
*
* @hide
diff --git a/core/java/android/app/timedetector/TimeSuggestionHelper.java b/core/java/android/app/timedetector/TimeSuggestionHelper.java
new file mode 100644
index 000000000000..9b99be61b3c8
--- /dev/null
+++ b/core/java/android/app/timedetector/TimeSuggestionHelper.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.app.timedetector;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.ShellCommand;
+import android.os.TimestampedValue;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A delegate class to support time suggestion classes that could diverge in the future. This class
+ * exists purely for code re-use and provides support methods. It avoids class inheritance
+ * deliberately to allow each suggestion to evolve in different directions later without affecting
+ * SDK APIs.
+ *
+ * <p>{@code unixEpochTime} is the suggested time. The {@code unixEpochTime.value} is the number of
+ * milliseconds elapsed since 1/1/1970 00:00:00 UTC according to the Unix time system. The {@code
+ * unixEpochTime.referenceTimeMillis} is the value of the elapsed realtime clock when the {@code
+ * unixEpochTime.value} was established. Note that the elapsed realtime clock is considered accurate
+ * but it is volatile, so time suggestions cannot be persisted across device resets.
+ *
+ * <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
+ * record why the suggestion exists and how it was entered. This information exists only to aid in
+ * debugging and therefore is used by {@link #toString()}, but it is not for use in detection
+ * logic and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
+ *
+ * @hide
+ */
+public final class TimeSuggestionHelper {
+
+ @NonNull private final Class<?> mHelpedClass;
+ @NonNull private final TimestampedValue<Long> mUnixEpochTime;
+ @Nullable private ArrayList<String> mDebugInfo;
+
+ /** Creates a helper for the specified class, containing the supplied properties. */
+ public TimeSuggestionHelper(@NonNull Class<?> helpedClass,
+ @NonNull TimestampedValue<Long> unixEpochTime) {
+ mHelpedClass = Objects.requireNonNull(helpedClass);
+ mUnixEpochTime = Objects.requireNonNull(unixEpochTime);
+ Objects.requireNonNull(unixEpochTime.getValue());
+ }
+
+ /** See {@link TimeSuggestionHelper} for property details. */
+ @NonNull
+ public TimestampedValue<Long> getUnixEpochTime() {
+ return mUnixEpochTime;
+ }
+
+ /** See {@link TimeSuggestionHelper} for information about {@code debugInfo}. */
+ @NonNull
+ public List<String> getDebugInfo() {
+ return mDebugInfo == null
+ ? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
+ }
+
+ /**
+ * Associates information with the instance that can be useful for debugging / logging.
+ *
+ * <p>See {@link TimeSuggestionHelper} for more information about {@code debugInfo}.
+ */
+ public void addDebugInfo(@NonNull String debugInfo) {
+ if (mDebugInfo == null) {
+ mDebugInfo = new ArrayList<>();
+ }
+ mDebugInfo.add(debugInfo);
+ }
+
+ /**
+ * Associates information with the instance that can be useful for debugging / logging. The
+ * information is present in {@link #toString()} but is not considered for
+ * {@link #equals(Object)} and {@link #hashCode()}.
+ */
+ public void addDebugInfo(String... debugInfos) {
+ addDebugInfo(Arrays.asList(debugInfos));
+ }
+
+ /**
+ * Associates information with the instance that can be useful for debugging / logging.
+ *
+ * <p>See {@link TimeSuggestionHelper} for more information about {@code debugInfo}.
+ */
+ public void addDebugInfo(@NonNull List<String> debugInfo) {
+ if (mDebugInfo == null) {
+ mDebugInfo = new ArrayList<>(debugInfo.size());
+ }
+ mDebugInfo.addAll(debugInfo);
+ }
+
+ /**
+ * Implemented in case users call this insteam of {@link #handleEquals(TimeSuggestionHelper)}.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ TimeSuggestionHelper that = (TimeSuggestionHelper) o;
+ return handleEquals(that);
+ }
+
+ /** Used to implement {@link Object#equals(Object)}. */
+ public boolean handleEquals(TimeSuggestionHelper o) {
+ return Objects.equals(mHelpedClass, o.mHelpedClass)
+ && Objects.equals(mUnixEpochTime, o.mUnixEpochTime);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mUnixEpochTime);
+ }
+
+ /** Used to implement {@link Object#toString()}. */
+ public String handleToString() {
+ return mHelpedClass.getSimpleName() + "{"
+ + "mUnixEpochTime=" + mUnixEpochTime
+ + ", mDebugInfo=" + mDebugInfo
+ + '}';
+ }
+
+ /** Constructs a helper with suggestion state from a Parcel. */
+ public static TimeSuggestionHelper handleCreateFromParcel(@NonNull Class<?> helpedClass,
+ @NonNull Parcel in) {
+ @SuppressWarnings("unchecked")
+ TimestampedValue<Long> unixEpochTime = in.readParcelable(
+ null /* classLoader */, TimestampedValue.class);
+ TimeSuggestionHelper suggestionHelper =
+ new TimeSuggestionHelper(helpedClass, unixEpochTime);
+ suggestionHelper.mDebugInfo = in.readArrayList(null /* classLoader */, String.class);
+ return suggestionHelper;
+ }
+
+ /** Writes the helper suggestion state to a Parcel. */
+ public void handleWriteToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeParcelable(mUnixEpochTime, 0);
+ dest.writeList(mDebugInfo);
+ }
+
+ /** Parses command line args to create a {@link TimeSuggestionHelper}. */
+ public static TimeSuggestionHelper handleParseCommandLineArg(
+ @NonNull Class<?> helpedClass, @NonNull ShellCommand cmd)
+ throws IllegalArgumentException {
+ Long referenceTimeMillis = null;
+ Long unixEpochTimeMillis = null;
+ String opt;
+ while ((opt = cmd.getNextArg()) != null) {
+ switch (opt) {
+ case "--reference_time": {
+ referenceTimeMillis = Long.parseLong(cmd.getNextArgRequired());
+ break;
+ }
+ case "--unix_epoch_time": {
+ unixEpochTimeMillis = Long.parseLong(cmd.getNextArgRequired());
+ break;
+ }
+ default: {
+ throw new IllegalArgumentException("Unknown option: " + opt);
+ }
+ }
+ }
+
+ if (referenceTimeMillis == null) {
+ throw new IllegalArgumentException("No referenceTimeMillis specified.");
+ }
+ if (unixEpochTimeMillis == null) {
+ throw new IllegalArgumentException("No unixEpochTimeMillis specified.");
+ }
+
+ TimestampedValue<Long> timeSignal =
+ new TimestampedValue<>(referenceTimeMillis, unixEpochTimeMillis);
+ TimeSuggestionHelper suggestionHelper = new TimeSuggestionHelper(helpedClass, timeSignal);
+ suggestionHelper.addDebugInfo("Command line injection");
+ return suggestionHelper;
+ }
+
+ /** Prints the command line args needed to create a {@link TimeSuggestionHelper}. */
+ public static void handlePrintCommandLineOpts(
+ @NonNull PrintWriter pw, @NonNull String typeName, @NonNull Class<?> clazz) {
+ pw.printf("%s suggestion options:\n", typeName);
+ pw.println(" --reference_time <elapsed realtime millis>");
+ pw.println(" --unix_epoch_time <Unix epoch time millis>");
+ pw.println();
+ pw.println("See " + clazz.getName() + " for more information");
+ }
+}
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index f4f9f9437eb0..1122c20dda22 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1153,8 +1153,8 @@ static void relabelDir(const char* path, const char* context, fail_fn_t fail_fn)
}
}
-// Relabel all directories under a path non-recursively.
-static void relabelAllDirs(const char* path, const char* context, fail_fn_t fail_fn) {
+// Relabel the subdirectories and symlinks in the given directory, non-recursively.
+static void relabelSubdirs(const char* path, const char* context, fail_fn_t fail_fn) {
DIR* dir = opendir(path);
if (dir == nullptr) {
fail_fn(CREATE_ERROR("Failed to opendir %s", path));
@@ -1231,11 +1231,19 @@ static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_d
snprintf(internalDePath, PATH_MAX, "/data/user_de");
snprintf(externalPrivateMountPath, PATH_MAX, "/mnt/expand");
- char* dataDataContext = nullptr;
- if (getfilecon(internalDePath, &dataDataContext) < 0) {
- fail_fn(CREATE_ERROR("Unable to getfilecon on %s %s", internalDePath,
+ // Get the "u:object_r:system_userdir_file:s0" security context. This can be
+ // gotten from several different places; we use /data/user.
+ char* dataUserdirContext = nullptr;
+ if (getfilecon(internalCePath, &dataUserdirContext) < 0) {
+ fail_fn(CREATE_ERROR("Unable to getfilecon on %s %s", internalCePath,
strerror(errno)));
}
+ // Get the "u:object_r:system_data_file:s0" security context. This can be
+ // gotten from several different places; we use /data/misc.
+ char* dataFileContext = nullptr;
+ if (getfilecon("/data/misc", &dataFileContext) < 0) {
+ fail_fn(CREATE_ERROR("Unable to getfilecon on /data/misc %s", strerror(errno)));
+ }
MountAppDataTmpFs(internalLegacyCePath, fail_fn);
MountAppDataTmpFs(internalCePath, fail_fn);
@@ -1330,19 +1338,19 @@ static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_d
// the file operations on tmpfs. If we set the label when we mount
// tmpfs, SELinux will not happy as we are changing system_data_files.
// Relabel dir under /data/user, including /data/user/0
- relabelAllDirs(internalCePath, dataDataContext, fail_fn);
+ relabelSubdirs(internalCePath, dataFileContext, fail_fn);
// Relabel /data/user
- relabelDir(internalCePath, dataDataContext, fail_fn);
+ relabelDir(internalCePath, dataUserdirContext, fail_fn);
// Relabel /data/data
- relabelDir(internalLegacyCePath, dataDataContext, fail_fn);
+ relabelDir(internalLegacyCePath, dataFileContext, fail_fn);
- // Relabel dir under /data/user_de
- relabelAllDirs(internalDePath, dataDataContext, fail_fn);
+ // Relabel subdirectories of /data/user_de
+ relabelSubdirs(internalDePath, dataFileContext, fail_fn);
// Relabel /data/user_de
- relabelDir(internalDePath, dataDataContext, fail_fn);
+ relabelDir(internalDePath, dataUserdirContext, fail_fn);
// Relabel CE and DE dirs under /mnt/expand
dir = opendir(externalPrivateMountPath);
@@ -1355,14 +1363,15 @@ static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_d
auto cePath = StringPrintf("%s/user", volPath.c_str());
auto dePath = StringPrintf("%s/user_de", volPath.c_str());
- relabelAllDirs(cePath.c_str(), dataDataContext, fail_fn);
- relabelDir(cePath.c_str(), dataDataContext, fail_fn);
- relabelAllDirs(dePath.c_str(), dataDataContext, fail_fn);
- relabelDir(dePath.c_str(), dataDataContext, fail_fn);
+ relabelSubdirs(cePath.c_str(), dataFileContext, fail_fn);
+ relabelDir(cePath.c_str(), dataUserdirContext, fail_fn);
+ relabelSubdirs(dePath.c_str(), dataFileContext, fail_fn);
+ relabelDir(dePath.c_str(), dataUserdirContext, fail_fn);
}
closedir(dir);
- freecon(dataDataContext);
+ freecon(dataUserdirContext);
+ freecon(dataFileContext);
}
static void insertPackagesToMergedList(JNIEnv* env,
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index b3851a5ffbf2..d24a95db3cd9 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -35,7 +35,7 @@
rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max
If this is configured as an empty string, the system default will be applied.
-->
- <string name="config_tcp_buffers" translatable="false"></string>
+ <string name="config_tcp_buffers" translatable="false">2097152,6291456,16777216,512000,2097152,8388608</string>
<java-symbol type="string" name="config_tcp_buffers" />
<!-- What source to use to estimate link upstream and downstream bandwidth capacities.
@@ -109,4 +109,12 @@
<!-- Telephony qualified networks service class name to bind to by default. -->
<string name="config_qualified_networks_service_class" translatable="false"></string>
<java-symbol type="string" name="config_qualified_networks_service_class" />
+
+ <!-- Whether enhanced IWLAN handover check is enabled. If enabled, telephony frameworks
+ will not perform handover if the target transport is out of service, or VoPS not
+ supported. The network will be torn down on the source transport, and will be
+ re-established on the target transport when condition is allowed for bringing up a
+ new network. -->
+ <bool name="config_enhanced_iwlan_handover_check">true</bool>
+ <java-symbol type="bool" name="config_enhanced_iwlan_handover_check" />
</resources>
diff --git a/core/tests/PackageInstallerSessions/Android.bp b/core/tests/PackageInstallerSessions/Android.bp
index de2a013df999..6f2366e32574 100644
--- a/core/tests/PackageInstallerSessions/Android.bp
+++ b/core/tests/PackageInstallerSessions/Android.bp
@@ -50,6 +50,6 @@ android_test {
":PackageManagerTestAppVersion1",
],
- platform_apis: true,
+ sdk_version: "core_platform",
test_suites: ["device-tests"],
}
diff --git a/core/tests/bugreports/Android.bp b/core/tests/bugreports/Android.bp
index 43a96793447d..2b34ee2646f3 100644
--- a/core/tests/bugreports/Android.bp
+++ b/core/tests/bugreports/Android.bp
@@ -35,7 +35,7 @@ android_test {
"truth-prebuilt",
],
test_suites: ["general-tests"],
- platform_apis: true,
+ sdk_version: "test_current",
}
filegroup {
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index b52118425a2d..f971af1466c3 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -72,7 +72,7 @@ android_test {
"libpowermanagertest_jni",
],
- platform_apis: true,
+ sdk_version: "core_platform",
test_suites: ["device-tests"],
certificate: "platform",
diff --git a/core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java b/core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java
new file mode 100644
index 000000000000..90b33058d4e8
--- /dev/null
+++ b/core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.app.time;
+
+import static android.app.timezonedetector.ShellCommandTestSupport.createShellCommandWithArgsAndOptions;
+
+import static org.junit.Assert.assertEquals;
+
+import android.os.ShellCommand;
+
+import org.junit.Test;
+
+/**
+ * Tests for non-SDK methods on {@link ExternalTimeSuggestion}.
+ * Also see {@link android.app.time.cts.ExternalTimeSuggestionTest}
+ */
+public class ExternalTimeSuggestionTest {
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_noReferenceTime() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--unix_epoch_time 12345");
+ ExternalTimeSuggestion.parseCommandLineArg(testShellCommand);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_noUnixEpochTime() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--reference_time 54321");
+ ExternalTimeSuggestion.parseCommandLineArg(testShellCommand);
+ }
+
+ @Test
+ public void testParseCommandLineArg_validSuggestion() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--reference_time 54321 --unix_epoch_time 12345");
+ ExternalTimeSuggestion expectedSuggestion = new ExternalTimeSuggestion(54321L, 12345L);
+ ExternalTimeSuggestion actualSuggestion =
+ ExternalTimeSuggestion.parseCommandLineArg(testShellCommand);
+ assertEquals(expectedSuggestion, actualSuggestion);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_unknownArgument() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--reference_time 54321 --unix_epoch_time 12345 --bad_arg 0");
+ ExternalTimeSuggestion.parseCommandLineArg(testShellCommand);
+ }
+}
diff --git a/core/tests/coretests/src/android/app/timedetector/GnssTimeSuggestionTest.java b/core/tests/coretests/src/android/app/timedetector/GnssTimeSuggestionTest.java
index e248010319e1..af403a20ae7b 100644
--- a/core/tests/coretests/src/android/app/timedetector/GnssTimeSuggestionTest.java
+++ b/core/tests/coretests/src/android/app/timedetector/GnssTimeSuggestionTest.java
@@ -18,10 +18,12 @@ package android.app.timedetector;
import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable;
+import static android.app.timezonedetector.ShellCommandTestSupport.createShellCommandWithArgsAndOptions;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
+import android.os.ShellCommand;
import android.os.TimestampedValue;
import org.junit.Test;
@@ -63,4 +65,36 @@ public class GnssTimeSuggestionTest {
GnssTimeSuggestion rtSuggestion = roundTripParcelable(suggestion);
assertEquals(suggestion.getDebugInfo(), rtSuggestion.getDebugInfo());
}
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_noReferenceTime() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--unix_epoch_time 12345");
+ GnssTimeSuggestion.parseCommandLineArg(testShellCommand);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_noUnixEpochTime() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--reference_time 54321");
+ GnssTimeSuggestion.parseCommandLineArg(testShellCommand);
+ }
+
+ @Test
+ public void testParseCommandLineArg_validSuggestion() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--reference_time 54321 --unix_epoch_time 12345");
+ TimestampedValue<Long> timeSignal = new TimestampedValue<>(54321L, 12345L);
+ GnssTimeSuggestion expectedSuggestion = new GnssTimeSuggestion(timeSignal);
+ GnssTimeSuggestion actualSuggestion =
+ GnssTimeSuggestion.parseCommandLineArg(testShellCommand);
+ assertEquals(expectedSuggestion, actualSuggestion);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_unknownArgument() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--reference_time 54321 --unix_epoch_time 12345 --bad_arg 0");
+ GnssTimeSuggestion.parseCommandLineArg(testShellCommand);
+ }
}
diff --git a/core/tests/coretests/src/android/app/timedetector/ManualTimeSuggestionTest.java b/core/tests/coretests/src/android/app/timedetector/ManualTimeSuggestionTest.java
index 750ffa1c9a54..94218cdea0ed 100644
--- a/core/tests/coretests/src/android/app/timedetector/ManualTimeSuggestionTest.java
+++ b/core/tests/coretests/src/android/app/timedetector/ManualTimeSuggestionTest.java
@@ -18,10 +18,12 @@ package android.app.timedetector;
import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable;
+import static android.app.timezonedetector.ShellCommandTestSupport.createShellCommandWithArgsAndOptions;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
+import android.os.ShellCommand;
import android.os.TimestampedValue;
import org.junit.Test;
@@ -63,4 +65,36 @@ public class ManualTimeSuggestionTest {
ManualTimeSuggestion rtSuggestion = roundTripParcelable(suggestion);
assertEquals(suggestion.getDebugInfo(), rtSuggestion.getDebugInfo());
}
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_noReferenceTime() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--unix_epoch_time 12345");
+ ManualTimeSuggestion.parseCommandLineArg(testShellCommand);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_noUnixEpochTime() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--reference_time 54321");
+ ManualTimeSuggestion.parseCommandLineArg(testShellCommand);
+ }
+
+ @Test
+ public void testParseCommandLineArg_validSuggestion() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--reference_time 54321 --unix_epoch_time 12345");
+ TimestampedValue<Long> timeSignal = new TimestampedValue<>(54321L, 12345L);
+ ManualTimeSuggestion expectedSuggestion = new ManualTimeSuggestion(timeSignal);
+ ManualTimeSuggestion actualSuggestion =
+ ManualTimeSuggestion.parseCommandLineArg(testShellCommand);
+ assertEquals(expectedSuggestion, actualSuggestion);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_unknownArgument() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--reference_time 54321 --unix_epoch_time 12345 --bad_arg 0");
+ ManualTimeSuggestion.parseCommandLineArg(testShellCommand);
+ }
}
diff --git a/core/tests/coretests/src/android/app/timedetector/NetworkTimeSuggestionTest.java b/core/tests/coretests/src/android/app/timedetector/NetworkTimeSuggestionTest.java
index b88c36f20bc6..0e09dd3e9aab 100644
--- a/core/tests/coretests/src/android/app/timedetector/NetworkTimeSuggestionTest.java
+++ b/core/tests/coretests/src/android/app/timedetector/NetworkTimeSuggestionTest.java
@@ -18,10 +18,12 @@ package android.app.timedetector;
import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable;
+import static android.app.timezonedetector.ShellCommandTestSupport.createShellCommandWithArgsAndOptions;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
+import android.os.ShellCommand;
import android.os.TimestampedValue;
import org.junit.Test;
@@ -63,4 +65,36 @@ public class NetworkTimeSuggestionTest {
NetworkTimeSuggestion rtSuggestion = roundTripParcelable(suggestion);
assertEquals(suggestion.getDebugInfo(), rtSuggestion.getDebugInfo());
}
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_noReferenceTime() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--unix_epoch_time 12345");
+ NetworkTimeSuggestion.parseCommandLineArg(testShellCommand);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_noUnixEpochTime() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--reference_time 54321");
+ NetworkTimeSuggestion.parseCommandLineArg(testShellCommand);
+ }
+
+ @Test
+ public void testParseCommandLineArg_validSuggestion() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--reference_time 54321 --unix_epoch_time 12345");
+ TimestampedValue<Long> timeSignal = new TimestampedValue<>(54321L, 12345L);
+ NetworkTimeSuggestion expectedSuggestion = new NetworkTimeSuggestion(timeSignal);
+ NetworkTimeSuggestion actualSuggestion =
+ NetworkTimeSuggestion.parseCommandLineArg(testShellCommand);
+ assertEquals(expectedSuggestion, actualSuggestion);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_unknownArgument() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--reference_time 54321 --unix_epoch_time 12345 --bad_arg 0");
+ NetworkTimeSuggestion.parseCommandLineArg(testShellCommand);
+ }
}
diff --git a/core/tests/coretests/src/android/app/timedetector/TelephonyTimeSuggestionTest.java b/core/tests/coretests/src/android/app/timedetector/TelephonyTimeSuggestionTest.java
index cc7557977e80..bb995a852637 100644
--- a/core/tests/coretests/src/android/app/timedetector/TelephonyTimeSuggestionTest.java
+++ b/core/tests/coretests/src/android/app/timedetector/TelephonyTimeSuggestionTest.java
@@ -18,10 +18,12 @@ package android.app.timedetector;
import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable;
+import static android.app.timezonedetector.ShellCommandTestSupport.createShellCommandWithArgsAndOptions;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
+import android.os.ShellCommand;
import android.os.TimestampedValue;
import org.junit.Test;
@@ -95,4 +97,45 @@ public class TelephonyTimeSuggestionTest {
assertEquals(suggestion1.getDebugInfo(), rtSuggestion1.getDebugInfo());
}
}
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_noSlotIndex() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--reference_time 54321 --unix_epoch_time 12345");
+ TelephonyTimeSuggestion.parseCommandLineArg(testShellCommand);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_noReferenceTime() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--slot_index 0 --unix_epoch_time 12345");
+ TelephonyTimeSuggestion.parseCommandLineArg(testShellCommand);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_noUnixEpochTime() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--slot_index 0 --reference_time 54321");
+ TelephonyTimeSuggestion.parseCommandLineArg(testShellCommand);
+ }
+
+ @Test
+ public void testParseCommandLineArg_validSuggestion() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--slot_index 0 --reference_time 54321 --unix_epoch_time 12345");
+ TelephonyTimeSuggestion expectedSuggestion =
+ new TelephonyTimeSuggestion.Builder(0)
+ .setUnixEpochTime(new TimestampedValue<>(54321L, 12345L))
+ .build();
+ TelephonyTimeSuggestion actualSuggestion =
+ TelephonyTimeSuggestion.parseCommandLineArg(testShellCommand);
+ assertEquals(expectedSuggestion, actualSuggestion);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_unknownArgument() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--slot_index 0 --reference_time 54321 --unix_epoch_time 12345 --bad_arg 0");
+ TelephonyTimeSuggestion.parseCommandLineArg(testShellCommand);
+ }
}
diff --git a/core/tests/coretests/src/android/app/timezonedetector/ShellCommandTestSupport.java b/core/tests/coretests/src/android/app/timezonedetector/ShellCommandTestSupport.java
index 8d8290c7bdc9..4efaed11168e 100644
--- a/core/tests/coretests/src/android/app/timezonedetector/ShellCommandTestSupport.java
+++ b/core/tests/coretests/src/android/app/timezonedetector/ShellCommandTestSupport.java
@@ -26,14 +26,14 @@ import java.util.Arrays;
import java.util.List;
/** Utility methods related to {@link ShellCommand} objects used in several tests. */
-final class ShellCommandTestSupport {
+public final class ShellCommandTestSupport {
private ShellCommandTestSupport() {}
- static ShellCommand createShellCommandWithArgsAndOptions(String argsWithSpaces) {
+ public static ShellCommand createShellCommandWithArgsAndOptions(String argsWithSpaces) {
return createShellCommandWithArgsAndOptions(Arrays.asList(argsWithSpaces.split(" ")));
}
- static ShellCommand createShellCommandWithArgsAndOptions(List<String> args) {
+ public static ShellCommand createShellCommandWithArgsAndOptions(List<String> args) {
ShellCommand command = mock(ShellCommand.class);
class ArgProvider {
private int mCount;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java
index 9ad6f3adbd33..6fff52a20062 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java
@@ -206,6 +206,8 @@ class AndroidKeyStoreBCWorkaroundProvider extends Provider {
putSignatureImpl("NONEwithECDSA",
PACKAGE_NAME + ".AndroidKeyStoreECDSASignatureSpi$NONE");
+ putSignatureImpl("Ed25519",
+ PACKAGE_NAME + ".AndroidKeyStoreECDSASignatureSpi$Ed25519");
putSignatureImpl("SHA1withECDSA", PACKAGE_NAME + ".AndroidKeyStoreECDSASignatureSpi$SHA1");
put("Alg.Alias.Signature.ECDSA", "SHA1withECDSA");
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
index 8289671de212..5216a908826b 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
@@ -29,7 +29,10 @@ import libcore.util.EmptyArray;
import java.io.ByteArrayOutputStream;
import java.security.InvalidKeyException;
import java.security.SignatureSpi;
+import java.security.spec.NamedParameterSpec;
+import java.util.Arrays;
import java.util.List;
+import java.util.Set;
/**
* Base class for {@link SignatureSpi} providing Android KeyStore backed ECDSA signatures.
@@ -37,6 +40,10 @@ import java.util.List;
* @hide
*/
abstract class AndroidKeyStoreECDSASignatureSpi extends AndroidKeyStoreSignatureSpiBase {
+ private static final Set<String> ACCEPTED_SIGNING_SCHEMES = Set.of(
+ KeyProperties.KEY_ALGORITHM_EC.toLowerCase(),
+ NamedParameterSpec.ED25519.getName().toLowerCase(),
+ "eddsa");
public final static class NONE extends AndroidKeyStoreECDSASignatureSpi {
public NONE() {
@@ -114,6 +121,18 @@ abstract class AndroidKeyStoreECDSASignatureSpi extends AndroidKeyStoreSignature
}
}
+ public static final class Ed25519 extends AndroidKeyStoreECDSASignatureSpi {
+ public Ed25519() {
+ // Ed25519 uses an internal digest system.
+ super(KeymasterDefs.KM_DIGEST_NONE);
+ }
+
+ @Override
+ protected String getAlgorithm() {
+ return NamedParameterSpec.ED25519.getName();
+ }
+ }
+
public final static class SHA1 extends AndroidKeyStoreECDSASignatureSpi {
public SHA1() {
super(KeymasterDefs.KM_DIGEST_SHA1);
@@ -174,9 +193,10 @@ abstract class AndroidKeyStoreECDSASignatureSpi extends AndroidKeyStoreSignature
@Override
protected final void initKey(AndroidKeyStoreKey key) throws InvalidKeyException {
- if (!KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(key.getAlgorithm())) {
+ if (!ACCEPTED_SIGNING_SCHEMES.contains(key.getAlgorithm().toLowerCase())) {
throw new InvalidKeyException("Unsupported key algorithm: " + key.getAlgorithm()
- + ". Only" + KeyProperties.KEY_ALGORITHM_EC + " supported");
+ + ". Only" + Arrays.toString(ACCEPTED_SIGNING_SCHEMES.stream().toArray())
+ + " supported");
}
long keySizeBits = -1;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreEdECPrivateKey.java b/keystore/java/android/security/keystore2/AndroidKeyStoreEdECPrivateKey.java
new file mode 100644
index 000000000000..4855ad0f7293
--- /dev/null
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreEdECPrivateKey.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.security.keystore2;
+
+import android.annotation.NonNull;
+import android.security.KeyStoreSecurityLevel;
+import android.system.keystore2.Authorization;
+import android.system.keystore2.KeyDescriptor;
+
+import java.security.PrivateKey;
+import java.security.interfaces.EdECKey;
+import java.security.spec.NamedParameterSpec;
+
+/**
+ * EdEC private key (instance of {@link PrivateKey} and {@link EdECKey}) backed by keystore.
+ *
+ * @hide
+ */
+public class AndroidKeyStoreEdECPrivateKey extends AndroidKeyStorePrivateKey implements EdECKey {
+ public AndroidKeyStoreEdECPrivateKey(
+ @NonNull KeyDescriptor descriptor, long keyId,
+ @NonNull Authorization[] authorizations,
+ @NonNull String algorithm,
+ @NonNull KeyStoreSecurityLevel securityLevel) {
+ super(descriptor, keyId, authorizations, algorithm, securityLevel);
+ }
+
+ @Override
+ public NamedParameterSpec getParams() {
+ return NamedParameterSpec.ED25519;
+ }
+}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreEdECPublicKey.java b/keystore/java/android/security/keystore2/AndroidKeyStoreEdECPublicKey.java
new file mode 100644
index 000000000000..642e08813291
--- /dev/null
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreEdECPublicKey.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.security.keystore2;
+
+import android.annotation.NonNull;
+import android.security.KeyStoreSecurityLevel;
+import android.system.keystore2.KeyDescriptor;
+import android.system.keystore2.KeyMetadata;
+
+import java.math.BigInteger;
+import java.security.interfaces.EdECPublicKey;
+import java.security.spec.EdECPoint;
+import java.security.spec.NamedParameterSpec;
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * {@link EdECPublicKey} backed by keystore.
+ *
+ * @hide
+ */
+public class AndroidKeyStoreEdECPublicKey extends AndroidKeyStorePublicKey
+ implements EdECPublicKey {
+ /**
+ * DER sequence, as defined in https://datatracker.ietf.org/doc/html/rfc8410#section-4 and
+ * https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.
+ * SEQUENCE (2 elem)
+ * SEQUENCE (1 elem)
+ * OBJECT IDENTIFIER 1.3.101.112 curveEd25519 (EdDSA 25519 signature algorithm)
+ * as defined in https://datatracker.ietf.org/doc/html/rfc8410#section-3
+ * BIT STRING (256 bit) as defined in
+ * https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.2
+ */
+ private static final byte[] DER_KEY_PREFIX = new byte[] {
+ 0x30,
+ 0x2a,
+ 0x30,
+ 0x05,
+ 0x06,
+ 0x03,
+ 0x2b,
+ 0x65,
+ 0x70,
+ 0x03,
+ 0x21,
+ 0x00,
+ };
+ private static final int ED25519_KEY_SIZE_BYTES = 32;
+
+ private byte[] mEncodedKey;
+ private EdECPoint mPoint;
+
+ public AndroidKeyStoreEdECPublicKey(
+ @NonNull KeyDescriptor descriptor,
+ @NonNull KeyMetadata metadata,
+ @NonNull String algorithm,
+ @NonNull KeyStoreSecurityLevel iSecurityLevel,
+ @NonNull byte[] encodedKey) {
+ super(descriptor, metadata, encodedKey, algorithm, iSecurityLevel);
+ mEncodedKey = encodedKey;
+
+ int preambleLength = matchesPreamble(DER_KEY_PREFIX, encodedKey);
+ if (preambleLength == 0) {
+ throw new IllegalArgumentException("Key size is not correct size");
+ }
+
+ mPoint = pointFromKeyByteArray(
+ Arrays.copyOfRange(encodedKey, preambleLength, encodedKey.length));
+ }
+
+ @Override
+ AndroidKeyStorePrivateKey getPrivateKey() {
+ return new AndroidKeyStoreEdECPrivateKey(
+ getUserKeyDescriptor(),
+ getKeyIdDescriptor().nspace,
+ getAuthorizations(),
+ "EdDSA",
+ getSecurityLevel());
+ }
+
+ @Override
+ public NamedParameterSpec getParams() {
+ return NamedParameterSpec.ED25519;
+ }
+
+ @Override
+ public EdECPoint getPoint() {
+ return mPoint;
+ }
+
+ private static int matchesPreamble(byte[] preamble, byte[] encoded) {
+ if (encoded.length != (preamble.length + ED25519_KEY_SIZE_BYTES)) {
+ return 0;
+ }
+ if (Arrays.compare(preamble, Arrays.copyOf(encoded, preamble.length)) != 0) {
+ return 0;
+ }
+ return preamble.length;
+ }
+
+ private static EdECPoint pointFromKeyByteArray(byte[] coordinates) {
+ Objects.requireNonNull(coordinates);
+
+ // Oddity of the key is the most-significant bit of the last byte.
+ boolean isOdd = (0x80 & coordinates[coordinates.length - 1]) != 0;
+ // Zero out the oddity bit.
+ coordinates[coordinates.length - 1] &= (byte) 0x7f;
+ // Representation of Y is in little-endian, according to rfc8032 section-3.1.
+ reverse(coordinates);
+ // The integer representing Y starts from the first bit in the coordinates array.
+ BigInteger y = new BigInteger(1, coordinates);
+ return new EdECPoint(isOdd, y);
+ }
+
+ private static void reverse(byte[] coordinateArray) {
+ int start = 0;
+ int end = coordinateArray.length - 1;
+ while (start < end) {
+ byte tmp = coordinateArray[start];
+ coordinateArray[start] = coordinateArray[end];
+ coordinateArray[end] = tmp;
+ start++;
+ end--;
+ }
+ }
+
+ @Override
+ public byte[] getEncoded() {
+ return mEncodedKey.clone();
+ }
+}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
index d31499e8b36d..0355628b8135 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
@@ -224,7 +224,6 @@ public class AndroidKeyStoreProvider extends Provider {
String jcaKeyAlgorithm = publicKey.getAlgorithm();
- KeyStoreSecurityLevel securityLevel = iSecurityLevel;
if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(jcaKeyAlgorithm)) {
return new AndroidKeyStoreECPublicKey(descriptor, metadata,
iSecurityLevel, (ECPublicKey) publicKey);
@@ -232,8 +231,9 @@ public class AndroidKeyStoreProvider extends Provider {
return new AndroidKeyStoreRSAPublicKey(descriptor, metadata,
iSecurityLevel, (RSAPublicKey) publicKey);
} else if (ED25519_OID.equalsIgnoreCase(jcaKeyAlgorithm)) {
- //TODO(b/214203951) missing classes in conscrypt
- throw new ProviderException("Curve " + ED25519_OID + " not supported yet");
+ final byte[] publicKeyEncoded = publicKey.getEncoded();
+ return new AndroidKeyStoreEdECPublicKey(descriptor, metadata, ED25519_OID,
+ iSecurityLevel, publicKeyEncoded);
} else if (X25519_ALIAS.equalsIgnoreCase(jcaKeyAlgorithm)) {
//TODO(b/214203951) missing classes in conscrypt
throw new ProviderException("Curve " + X25519_ALIAS + " not supported yet");
diff --git a/keystore/tests/src/android/security/keystore2/AndroidKeyStoreEdECPublicKeyTest.java b/keystore/tests/src/android/security/keystore2/AndroidKeyStoreEdECPublicKeyTest.java
new file mode 100644
index 000000000000..5bd5797859c9
--- /dev/null
+++ b/keystore/tests/src/android/security/keystore2/AndroidKeyStoreEdECPublicKeyTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.security.keystore2;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import android.security.KeyStoreSecurityLevel;
+import android.system.keystore2.Authorization;
+import android.system.keystore2.Domain;
+import android.system.keystore2.KeyDescriptor;
+import android.system.keystore2.KeyMetadata;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+import java.math.BigInteger;
+import java.util.Base64;
+
+@RunWith(AndroidJUnit4.class)
+public class AndroidKeyStoreEdECPublicKeyTest {
+ private static KeyDescriptor descriptor() {
+ final KeyDescriptor keyDescriptor = new KeyDescriptor();
+ keyDescriptor.alias = "key";
+ keyDescriptor.blob = null;
+ keyDescriptor.domain = Domain.APP;
+ keyDescriptor.nspace = -1;
+ return keyDescriptor;
+ }
+
+ private static KeyMetadata metadata(byte[] cert, byte[] certChain) {
+ KeyMetadata metadata = new KeyMetadata();
+ metadata.authorizations = new Authorization[0];
+ metadata.certificate = cert;
+ metadata.certificateChain = certChain;
+ metadata.key = descriptor();
+ metadata.modificationTimeMs = 0;
+ metadata.keySecurityLevel = 1;
+ return metadata;
+ }
+
+ @Mock
+ private KeyStoreSecurityLevel mKeystoreSecurityLevel;
+
+ private static class EdECTestVector {
+ public final byte[] encodedKeyBytes;
+ public final boolean isOdd;
+ public final BigInteger yValue;
+
+ EdECTestVector(String b64KeyBytes, boolean isOdd, String yValue) {
+ this.encodedKeyBytes = Base64.getDecoder().decode(b64KeyBytes);
+ this.isOdd = isOdd;
+ this.yValue = new BigInteger(yValue);
+ }
+ }
+
+ private static final EdECTestVector[] ED_EC_TEST_VECTORS = new EdECTestVector[]{
+ new EdECTestVector("MCowBQYDK2VwAyEADE+wvQqNHxaERPhAZ0rCFlgFbfWLs/YonPXdSTw0VSo=",
+ false,
+ "19147682157189290216699341180089409126316261024914226007941553249095116672780"
+ ),
+ new EdECTestVector("MCowBQYDK2VwAyEA/0E1IRNzGj85Ot/TPeXqifkqTkdk4voleH0hIq59D9w=",
+ true,
+ "41640152188550647350742178040529506688513911269563908889464821205156322689535"
+ ),
+ new EdECTestVector("MCowBQYDK2VwAyEAunOvGuenetl9GQSXGVo5L3RIr4OOIpFIv/Zre8qTc/8=",
+ true,
+ "57647939198144376128225770417635248407428273266444593100194116168980378907578"
+ ),
+ new EdECTestVector("MCowBQYDK2VwAyEA2hHqaZ5IolswN1Yd58Y4hzhmUMCCqc4PW5A/SFLmTX8=",
+ false,
+ "57581368614046789120409806291852629847774713088410311752049592044694364885466"
+ ),
+ };
+
+ @Test
+ public void testParsingOfValidKeys() {
+ for (EdECTestVector testVector : ED_EC_TEST_VECTORS) {
+ AndroidKeyStoreEdECPublicKey pkey = new AndroidKeyStoreEdECPublicKey(descriptor(),
+ metadata(null, null), "EdDSA", mKeystoreSecurityLevel,
+ testVector.encodedKeyBytes);
+
+ assertEquals(pkey.getPoint().isXOdd(), testVector.isOdd);
+ assertEquals(pkey.getPoint().getY(), testVector.yValue);
+ }
+ }
+
+ @Test
+ public void testFailedParsingOfKeysWithDifferentOid() {
+ final byte[] testVectorWithIncorrectOid = Base64.getDecoder().decode(
+ "MCowBQYDLGVwAyEADE+wvQqNHxaERPhAZ0rCFlgFbfWLs/YonPXdSTw0VSo=");
+ assertThrows("OID should be unrecognized", IllegalArgumentException.class,
+ () -> new AndroidKeyStoreEdECPublicKey(descriptor(), metadata(null, null), "EdDSA",
+ mKeystoreSecurityLevel, testVectorWithIncorrectOid));
+ }
+
+ @Test
+ public void testFailedParsingOfKeysWithWrongSize() {
+ final byte[] testVectorWithIncorrectKeySize = Base64.getDecoder().decode(
+ "MCwwBQYDK2VwAyMADE+wvQqNHxaERPhAZ0rCFlgFbfWLs/YonPXdSTw0VSrOzg==");
+ assertThrows("Key length should be invalid", IllegalArgumentException.class,
+ () -> new AndroidKeyStoreEdECPublicKey(descriptor(), metadata(null, null), "EdDSA",
+ mKeystoreSecurityLevel, testVectorWithIncorrectKeySize));
+ }
+}
+
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index ff4c2c63f8b4..c4d4261ba080 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -478,6 +478,12 @@
<uses-permission android:name="android.permission.MANAGE_TIME_AND_ZONE_DETECTION" />
<uses-permission android:name="android.permission.SUGGEST_EXTERNAL_TIME" />
+ <!-- Permissions used for manual testing of time detection behavior. -->
+ <uses-permission android:name="android.permission.SUGGEST_MANUAL_TIME" />
+ <uses-permission android:name="android.permission.SUGGEST_TELEPHONY_TIME" />
+ <uses-permission android:name="android.permission.SUGGEST_NETWORK_TIME" />
+ <uses-permission android:name="android.permission.SUGGEST_GNSS_TIME" />
+
<!-- Permission required for CTS test - android.server.biometrics -->
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index 9676a57b2df9..91c7a24afaf7 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -376,7 +376,7 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
Log.w(TAG, String.format("onActiveChanged(%d,%d,%s,%s,%d,%d)", code, uid, packageName,
Boolean.toString(active), attributionChainId, attributionFlags));
}
- if (attributionChainId != AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE
+ if (active && attributionChainId != AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE
&& attributionFlags != AppOpsManager.ATTRIBUTION_FLAGS_NONE
&& (attributionFlags & AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR) == 0
&& (attributionFlags & AppOpsManager.ATTRIBUTION_FLAG_TRUSTED) == 0) {
diff --git a/services/core/OWNERS b/services/core/OWNERS
deleted file mode 100644
index 88d0b61a2ab6..000000000000
--- a/services/core/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-per-file Android.bp = file:platform/build/soong:/OWNERS
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 406ff9b00686..a81699fa82c3 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1202,8 +1202,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
break;
case MSG_L_SET_BT_ACTIVE_DEVICE:
synchronized (mDeviceStateLock) {
- mDeviceInventory.onSetBtActiveDevice((BtDeviceInfo) msg.obj,
- mAudioService.getBluetoothContextualVolumeStream());
+ BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj;
+ mDeviceInventory.onSetBtActiveDevice(btInfo,
+ (btInfo.mProfile != BluetoothProfile.LE_AUDIO || btInfo.mIsLeOutput)
+ ? mAudioService.getBluetoothContextualVolumeStream()
+ : AudioSystem.STREAM_DEFAULT);
}
break;
case MSG_BT_HEADSET_CNCT_FAILED:
diff --git a/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java b/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java
index 28c7cad3b184..44822a3f7429 100644
--- a/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java
+++ b/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java
@@ -18,6 +18,7 @@ package com.android.server.clipboard;
import android.annotation.Nullable;
import android.content.ClipData;
+import android.os.PersistableBundle;
import android.os.SystemProperties;
import android.system.ErrnoException;
import android.system.Os;
@@ -25,6 +26,7 @@ import android.system.OsConstants;
import android.system.VmSocketAddress;
import android.util.Slog;
+import java.io.EOFException;
import java.io.FileDescriptor;
import java.io.InterruptedIOException;
import java.net.SocketException;
@@ -58,11 +60,11 @@ class EmulatorClipboardMonitor implements Consumer<ClipData> {
return mPipe;
}
- private synchronized boolean openPipe() {
- if (mPipe != null) {
- return true;
- }
+ private synchronized void setPipeFD(final FileDescriptor fd) {
+ mPipe = fd;
+ }
+ private static FileDescriptor openPipeImpl() {
try {
final FileDescriptor fd = Os.socket(OsConstants.AF_VSOCK, OsConstants.SOCK_STREAM, 0);
@@ -70,16 +72,33 @@ class EmulatorClipboardMonitor implements Consumer<ClipData> {
Os.connect(fd, new VmSocketAddress(HOST_PORT, OsConstants.VMADDR_CID_HOST));
final byte[] handshake = createOpenHandshake();
- Os.write(fd, handshake, 0, handshake.length);
- mPipe = fd;
- return true;
+ writeFully(fd, handshake, 0, handshake.length);
+ return fd;
} catch (ErrnoException | SocketException | InterruptedIOException e) {
Os.close(fd);
}
} catch (ErrnoException e) {
}
- return false;
+ return null;
+ }
+
+ private void openPipe() throws InterruptedException {
+ FileDescriptor fd = getPipeFD();
+
+ if (fd == null) {
+ fd = openPipeImpl();
+
+ // There's no guarantee that QEMU pipes will be ready at the moment
+ // this method is invoked. We simply try to get the pipe open and
+ // retry on failure indefinitely.
+ while (fd == null) {
+ Thread.sleep(100);
+ fd = openPipeImpl();
+ }
+ }
+
+ setPipeFD(fd);
}
private synchronized void closePipe() {
@@ -93,16 +112,16 @@ class EmulatorClipboardMonitor implements Consumer<ClipData> {
}
}
- private byte[] receiveMessage() throws ErrnoException, InterruptedIOException {
+ private byte[] receiveMessage() throws ErrnoException, InterruptedIOException, EOFException {
final byte[] lengthBits = new byte[4];
- Os.read(mPipe, lengthBits, 0, lengthBits.length);
+ readFully(mPipe, lengthBits, 0, lengthBits.length);
final ByteBuffer bb = ByteBuffer.wrap(lengthBits);
bb.order(ByteOrder.LITTLE_ENDIAN);
final int msgLen = bb.getInt();
final byte[] msg = new byte[msgLen];
- Os.read(mPipe, msg, 0, msg.length);
+ readFully(mPipe, msg, 0, msg.length);
return msg;
}
@@ -115,20 +134,15 @@ class EmulatorClipboardMonitor implements Consumer<ClipData> {
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.putInt(msg.length);
- Os.write(fd, lengthBits, 0, lengthBits.length);
- Os.write(fd, msg, 0, msg.length);
+ writeFully(fd, lengthBits, 0, lengthBits.length);
+ writeFully(fd, msg, 0, msg.length);
}
EmulatorClipboardMonitor(final Consumer<ClipData> setAndroidClipboard) {
this.mHostMonitorThread = new Thread(() -> {
while (!Thread.interrupted()) {
try {
- // There's no guarantee that QEMU pipes will be ready at the moment
- // this method is invoked. We simply try to get the pipe open and
- // retry on failure indefinitely.
- while (!openPipe()) {
- Thread.sleep(100);
- }
+ openPipe();
final byte[] receivedData = receiveMessage();
@@ -136,12 +150,15 @@ class EmulatorClipboardMonitor implements Consumer<ClipData> {
final ClipData clip = new ClipData("host clipboard",
new String[]{"text/plain"},
new ClipData.Item(str));
+ final PersistableBundle bundle = new PersistableBundle();
+ bundle.putBoolean("com.android.systemui.SUPPRESS_CLIPBOARD_OVERLAY", true);
+ clip.getDescription().setExtras(bundle);
if (LOG_CLIBOARD_ACCESS) {
Slog.i(TAG, "Setting the guest clipboard to '" + str + "'");
}
setAndroidClipboard.accept(clip);
- } catch (ErrnoException | InterruptedIOException e) {
+ } catch (ErrnoException | EOFException | InterruptedIOException e) {
closePipe();
} catch (InterruptedException | IllegalArgumentException e) {
}
@@ -182,4 +199,32 @@ class EmulatorClipboardMonitor implements Consumer<ClipData> {
t.start();
}
}
+
+ private static void readFully(final FileDescriptor fd,
+ final byte[] buf, int offset, int size)
+ throws ErrnoException, InterruptedIOException, EOFException {
+ while (size > 0) {
+ final int r = Os.read(fd, buf, offset, size);
+ if (r > 0) {
+ offset += r;
+ size -= r;
+ } else {
+ throw new EOFException();
+ }
+ }
+ }
+
+ private static void writeFully(final FileDescriptor fd,
+ final byte[] buf, int offset, int size)
+ throws ErrnoException, InterruptedIOException {
+ while (size > 0) {
+ final int r = Os.write(fd, buf, offset, size);
+ if (r > 0) {
+ offset += r;
+ size -= r;
+ } else {
+ throw new ErrnoException("write", OsConstants.EIO);
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index d07f151f25bd..18efe5375942 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1621,11 +1621,17 @@ public class Vpn {
}
// Note: Return type guarantees results are deduped and sorted, which callers require.
+ // This method also adds the SDK sandbox UIDs corresponding to the applications by default,
+ // since apps are generally not aware of them, yet they should follow the VPN configuration
+ // of the app they belong to.
private SortedSet<Integer> getAppsUids(List<String> packageNames, int userId) {
SortedSet<Integer> uids = new TreeSet<>();
for (String app : packageNames) {
int uid = getAppUid(app, userId);
if (uid != -1) uids.add(uid);
+ if (Process.isApplicationUid(uid)) {
+ uids.add(Process.toSdkSandboxUid(uid));
+ }
}
return uids;
}
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 2c2a2bf24cfd..7d8a22a9b563 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -505,12 +505,36 @@ public class BrightnessTracker {
}
}
+ // Return the path to the given file, either the new path
+ // /data/system/$filename, or the old path /data/system_de/$filename if the
+ // file exists there but not at the new path. Only use this for EVENTS_FILE
+ // and AMBIENT_BRIGHTNESS_STATS_FILE.
+ //
+ // Explanation: this service previously incorrectly stored these two files
+ // directly in /data/system_de, instead of in /data/system where they should
+ // have been. As system_server no longer has write access to
+ // /data/system_de itself, these files were moved to /data/system. To
+ // lazily migrate the files, we simply read from the old path if it exists
+ // and the new one doesn't, and always write to the new path. Note that
+ // system_server doesn't have permission to delete the old files.
+ private AtomicFile getFileWithLegacyFallback(String filename) {
+ AtomicFile file = mInjector.getFile(filename);
+ if (file != null && !file.exists()) {
+ AtomicFile legacyFile = mInjector.getLegacyFile(filename);
+ if (legacyFile != null && legacyFile.exists()) {
+ Slog.i(TAG, "Reading " + filename + " from old location");
+ return legacyFile;
+ }
+ }
+ return file;
+ }
+
private void readEvents() {
synchronized (mEventsLock) {
// Read might prune events so mark as dirty.
mEventsDirty = true;
mEvents.clear();
- final AtomicFile readFrom = mInjector.getFile(EVENTS_FILE);
+ final AtomicFile readFrom = getFileWithLegacyFallback(EVENTS_FILE);
if (readFrom != null && readFrom.exists()) {
FileInputStream input = null;
try {
@@ -528,7 +552,7 @@ public class BrightnessTracker {
private void readAmbientBrightnessStats() {
mAmbientBrightnessStatsTracker = new AmbientBrightnessStatsTracker(mUserManager, null);
- final AtomicFile readFrom = mInjector.getFile(AMBIENT_BRIGHTNESS_STATS_FILE);
+ final AtomicFile readFrom = getFileWithLegacyFallback(AMBIENT_BRIGHTNESS_STATS_FILE);
if (readFrom != null && readFrom.exists()) {
FileInputStream input = null;
try {
@@ -1095,6 +1119,10 @@ public class BrightnessTracker {
}
public AtomicFile getFile(String filename) {
+ return new AtomicFile(new File(Environment.getDataSystemDirectory(), filename));
+ }
+
+ public AtomicFile getLegacyFile(String filename) {
return new AtomicFile(new File(Environment.getDataSystemDeDirectory(), filename));
}
diff --git a/services/core/java/com/android/server/timedetector/EnvironmentImpl.java b/services/core/java/com/android/server/timedetector/EnvironmentImpl.java
index 7649958fe6c9..9d263516db3a 100644
--- a/services/core/java/com/android/server/timedetector/EnvironmentImpl.java
+++ b/services/core/java/com/android/server/timedetector/EnvironmentImpl.java
@@ -22,6 +22,7 @@ import android.app.AlarmManager;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
+import android.os.Build;
import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock;
@@ -166,6 +167,11 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
mWakeLock.release();
}
+ @Override
+ public boolean deviceHasY2038Issue() {
+ return Build.SUPPORTED_32_BIT_ABIS.length > 0;
+ }
+
private void checkWakeLockHeld() {
if (!mWakeLock.isHeld()) {
Slog.wtf(LOG_TAG, "WakeLock " + mWakeLock + " not held");
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorShellCommand.java b/services/core/java/com/android/server/timedetector/TimeDetectorShellCommand.java
index 721986bc6e93..cc5e6fe433fa 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorShellCommand.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorShellCommand.java
@@ -17,14 +17,26 @@ package com.android.server.timedetector;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SERVICE_NAME;
+import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_EXTERNAL_TIME;
+import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_GNSS_TIME;
+import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_MANUAL_TIME;
+import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_NETWORK_TIME;
+import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_TELEPHONY_TIME;
import static android.provider.DeviceConfig.NAMESPACE_SYSTEM_TIME;
import static com.android.server.timedetector.ServerFlags.KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE;
import static com.android.server.timedetector.ServerFlags.KEY_TIME_DETECTOR_ORIGIN_PRIORITIES_OVERRIDE;
+import android.app.time.ExternalTimeSuggestion;
+import android.app.timedetector.GnssTimeSuggestion;
+import android.app.timedetector.ManualTimeSuggestion;
+import android.app.timedetector.NetworkTimeSuggestion;
+import android.app.timedetector.TelephonyTimeSuggestion;
import android.os.ShellCommand;
import java.io.PrintWriter;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
/** Implements the shell command interface for {@link TimeDetectorService}. */
class TimeDetectorShellCommand extends ShellCommand {
@@ -44,6 +56,16 @@ class TimeDetectorShellCommand extends ShellCommand {
switch (cmd) {
case SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED:
return runIsAutoDetectionEnabled();
+ case SHELL_COMMAND_SUGGEST_MANUAL_TIME:
+ return runSuggestManualTime();
+ case SHELL_COMMAND_SUGGEST_TELEPHONY_TIME:
+ return runSuggestTelephonyTime();
+ case SHELL_COMMAND_SUGGEST_NETWORK_TIME:
+ return runSuggestNetworkTime();
+ case SHELL_COMMAND_SUGGEST_GNSS_TIME:
+ return runSuggestGnssTime();
+ case SHELL_COMMAND_SUGGEST_EXTERNAL_TIME:
+ return runSuggestExternalTime();
default: {
return handleDefaultCommands(cmd);
}
@@ -59,6 +81,53 @@ class TimeDetectorShellCommand extends ShellCommand {
return 0;
}
+ private int runSuggestManualTime() {
+ return runSuggestTime(
+ () -> ManualTimeSuggestion.parseCommandLineArg(this),
+ mInterface::suggestManualTime);
+ }
+
+ private int runSuggestTelephonyTime() {
+ return runSuggestTime(
+ () -> TelephonyTimeSuggestion.parseCommandLineArg(this),
+ mInterface::suggestTelephonyTime);
+ }
+
+ private int runSuggestNetworkTime() {
+ return runSuggestTime(
+ () -> NetworkTimeSuggestion.parseCommandLineArg(this),
+ mInterface::suggestNetworkTime);
+ }
+
+ private int runSuggestGnssTime() {
+ return runSuggestTime(
+ () -> GnssTimeSuggestion.parseCommandLineArg(this),
+ mInterface::suggestGnssTime);
+ }
+
+ private int runSuggestExternalTime() {
+ return runSuggestTime(
+ () -> ExternalTimeSuggestion.parseCommandLineArg(this),
+ mInterface::suggestExternalTime);
+ }
+
+ private <T> int runSuggestTime(Supplier<T> suggestionParser, Consumer<T> invoker) {
+ final PrintWriter pw = getOutPrintWriter();
+ try {
+ T suggestion = suggestionParser.get();
+ if (suggestion == null) {
+ pw.println("Error: suggestion not specified");
+ return 1;
+ }
+ invoker.accept(suggestion);
+ pw.println("Suggestion " + suggestion + " injected.");
+ return 0;
+ } catch (RuntimeException e) {
+ pw.println(e);
+ return 1;
+ }
+ }
+
@Override
public void onHelp() {
final PrintWriter pw = getOutPrintWriter();
@@ -68,6 +137,22 @@ class TimeDetectorShellCommand extends ShellCommand {
pw.printf(" %s\n", SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED);
pw.printf(" Prints true/false according to the automatic time detection setting.\n");
pw.println();
+ pw.printf(" %s <manual suggestion opts>\n", SHELL_COMMAND_SUGGEST_MANUAL_TIME);
+ pw.printf(" %s <telephony suggestion opts>\n", SHELL_COMMAND_SUGGEST_TELEPHONY_TIME);
+ pw.printf(" %s <network suggestion opts>\n", SHELL_COMMAND_SUGGEST_NETWORK_TIME);
+ pw.printf(" %s <gnss suggestion opts>\n", SHELL_COMMAND_SUGGEST_GNSS_TIME);
+ pw.printf(" %s <external suggestion opts>\n", SHELL_COMMAND_SUGGEST_EXTERNAL_TIME);
+ pw.println();
+ ManualTimeSuggestion.printCommandLineOpts(pw);
+ pw.println();
+ TelephonyTimeSuggestion.printCommandLineOpts(pw);
+ pw.println();
+ NetworkTimeSuggestion.printCommandLineOpts(pw);
+ pw.println();
+ GnssTimeSuggestion.printCommandLineOpts(pw);
+ pw.println();
+ ExternalTimeSuggestion.printCommandLineOpts(pw);
+ pw.println();
pw.printf("This service is also affected by the following device_config flags in the"
+ " %s namespace:\n", NAMESPACE_SYSTEM_TIME);
pw.printf(" %s\n", KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE);
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index ae4d46c387b9..33ab1047c763 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -85,6 +85,9 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
*/
private static final int KEEP_SUGGESTION_HISTORY_SIZE = 10;
+ /** The value in Unix epoch milliseconds of the Y2038 issue. */
+ private static final long Y2038_LIMIT_IN_MILLIS = 1000L * Integer.MAX_VALUE;
+
/**
* A log that records the decisions / decision metadata that affected the device's system clock
* time. This is logged in bug reports to assist with debugging issues with detection.
@@ -185,6 +188,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
/** Release the wake lock acquired by a call to {@link #acquireWakeLock()}. */
void releaseWakeLock();
+
+ /**
+ * Returns {@code true} if the device may be at risk of time_t overflow (because bionic
+ * defines time_t as a 32-bit signed integer for 32-bit processes).
+ */
+ boolean deviceHasY2038Issue();
}
static TimeDetectorStrategy create(
@@ -333,6 +342,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
.mapToObj(TimeDetectorStrategy::originToString)
.collect(joining(",", "[", "]"));
ipw.println("mEnvironment.autoOriginPriorities()=" + priorities);
+ ipw.println("mEnvironment.deviceHasY2038Issue()=" + mEnvironment.deviceHasY2038Issue());
ipw.println("Time change log:");
ipw.increaseIndent(); // level 2
@@ -413,6 +423,16 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
+ ", suggestion=" + suggestion);
return false;
}
+
+ if (newUnixEpochTime.getValue() > Y2038_LIMIT_IN_MILLIS
+ && mEnvironment.deviceHasY2038Issue()) {
+ // This check won't prevent a device's system clock exceeding Integer.MAX_VALUE Unix
+ // seconds through the normal passage of time, but it will stop it jumping above 2038
+ // because of a "bad" suggestion. b/204193177
+ Slog.w(LOG_TAG, "Suggested value is above max time supported by this device."
+ + " suggestion=" + suggestion);
+ return false;
+ }
return true;
}
diff --git a/services/proguard.flags b/services/proguard.flags
index 425da6c11177..bad02b47031c 100644
--- a/services/proguard.flags
+++ b/services/proguard.flags
@@ -33,6 +33,11 @@
public <init>(...);
}
+# Accessed from com.android.compos APEX
+-keep,allowoptimization,allowaccessmodification class com.android.internal.art.ArtStatsLog {
+ public static void write(...);
+}
+
# Binder interfaces
-keep,allowoptimization,allowaccessmodification class * extends android.os.IInterface
-keep,allowoptimization,allowaccessmodification class * extends android.os.IHwInterface
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
index 0a033380e6c9..2617f4d09ee7 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
@@ -25,6 +25,7 @@ package {
android_test_helper_app {
name: "PackageManagerServiceDeviceSideTests",
+ sdk_version: "test_current",
srcs: ["src/**/*.kt"],
libs: [
"android.test.base",
@@ -37,5 +38,4 @@ android_test_helper_app {
"androidx.test.rules",
"truth-prebuilt",
],
- platform_apis: true,
}
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
index bdf94f3a2882..3151552fc4c9 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -1037,6 +1037,12 @@ public class BrightnessTrackerTest {
}
@Override
+ public AtomicFile getLegacyFile(String filename) {
+ // Don't have the test write / read from anywhere.
+ return null;
+ }
+
+ @Override
public long currentTimeMillis() {
return mCurrentTimeMillis;
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index a227cd3c6f5c..035249e32d74 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -70,6 +70,7 @@ import com.google.common.collect.ImmutableMap;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -516,6 +517,7 @@ public class RecoverableKeyStoreManagerTest {
}
}
+ @Ignore("Causing breakages so ignoring to resolve, b/231667368")
@Test
public void initRecoveryService_alwaysUpdatesCertsWhenTestRootCertIsUsed() throws Exception {
int uid = Binder.getCallingUid();
@@ -539,6 +541,7 @@ public class RecoverableKeyStoreManagerTest {
testRootCertAlias)).isEqualTo(TestData.getInsecureCertPathForEndpoint2());
}
+ @Ignore("Causing breakages so ignoring to resolve, b/231667368")
@Test
public void initRecoveryService_updatesCertsIndependentlyForDifferentRoots() throws Exception {
int uid = Binder.getCallingUid();
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index 2d9903f9cf60..2248ddb9e69a 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -1131,6 +1131,49 @@ public class TimeDetectorStrategyImplTest {
.verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli());
}
+ @Test
+ public void manualY2038SuggestionsAreRejectedOnAffectedDevices() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(false)
+ .pokeAutoOriginPriorities(ORIGIN_TELEPHONY)
+ .pokeDeviceHasY2038Issues(true);
+
+ Instant y2038IssueTime = Instant.ofEpochMilli((1L + Integer.MAX_VALUE) * 1000L);
+ ManualTimeSuggestion timeSuggestion = mScript.generateManualTimeSuggestion(y2038IssueTime);
+ mScript.simulateManualTimeSuggestion(timeSuggestion, false /* expectedResult */)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void telephonyY2038SuggestionsAreRejectedOnAffectedDevices() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true)
+ .pokeAutoOriginPriorities(ORIGIN_TELEPHONY)
+ .pokeDeviceHasY2038Issues(true);
+
+ final int slotIndex = 0;
+ Instant y2038IssueTime = Instant.ofEpochMilli((1L + Integer.MAX_VALUE) * 1000L);
+ TelephonyTimeSuggestion timeSuggestion =
+ mScript.generateTelephonyTimeSuggestion(slotIndex, y2038IssueTime);
+ mScript.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void telephonyY2038SuggestionsAreNotRejectedOnUnaffectedDevices() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true)
+ .pokeAutoOriginPriorities(ORIGIN_TELEPHONY)
+ .pokeDeviceHasY2038Issues(false);
+
+ final int slotIndex = 0;
+ Instant y2038IssueTime = Instant.ofEpochMilli((1L + Integer.MAX_VALUE) * 1000L);
+ TelephonyTimeSuggestion timeSuggestion =
+ mScript.generateTelephonyTimeSuggestion(slotIndex, y2038IssueTime);
+ mScript.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(y2038IssueTime.toEpochMilli());
+ }
+
/**
* A fake implementation of {@link TimeDetectorStrategyImpl.Environment}. Besides tracking
* changes and behaving like the real thing should, it also asserts preconditions.
@@ -1143,6 +1186,7 @@ public class TimeDetectorStrategyImplTest {
private int mSystemClockUpdateThresholdMillis = 2000;
private int[] mAutoOriginPriorities = PROVIDERS_PRIORITY;
private ConfigurationChangeListener mConfigChangeListener;
+ private boolean mDeviceHas2038Issues = false;
// Tracking operations.
private boolean mSystemClockWasSet;
@@ -1208,6 +1252,15 @@ public class TimeDetectorStrategyImplTest {
mWakeLockAcquired = false;
}
+ public void setDeviceHas2038Issues(boolean hasIssues) {
+ mDeviceHas2038Issues = hasIssues;
+ }
+
+ @Override
+ public boolean deviceHasY2038Issue() {
+ return mDeviceHas2038Issues;
+ }
+
// Methods below are for managing the fake's behavior.
void pokeSystemClockUpdateThreshold(int thresholdMillis) {
@@ -1304,6 +1357,11 @@ public class TimeDetectorStrategyImplTest {
return this;
}
+ Script pokeDeviceHasY2038Issues(boolean hasIssues) {
+ mFakeEnvironment.setDeviceHas2038Issues(hasIssues);
+ return this;
+ }
+
long peekElapsedRealtimeMillis() {
return mFakeEnvironment.peekElapsedRealtimeMillis();
}
diff --git a/telephony/java/android/telephony/AnomalyReporter.java b/telephony/java/android/telephony/AnomalyReporter.java
index f47cf3384791..e7d95e4f53b3 100644
--- a/telephony/java/android/telephony/AnomalyReporter.java
+++ b/telephony/java/android/telephony/AnomalyReporter.java
@@ -16,6 +16,8 @@
package android.telephony;
+import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
+
import static com.android.internal.telephony.TelephonyStatsLog.TELEPHONY_ANOMALY_DETECTED;
import android.annotation.NonNull;
@@ -73,6 +75,7 @@ public final class AnomalyReporter {
*
* This method sends the {@link TelephonyManager#ACTION_ANOMALY_REPORTED} broadcast, which is
* system protected. Invoking this method unless you are the system will result in an error.
+ * Carrier Id will be set as UNKNOWN_CARRIER_ID.
*
* @param eventId a fixed event ID that will be sent for each instance of the same event. This
* ID should be generated randomly.
@@ -81,6 +84,23 @@ public final class AnomalyReporter {
* static and must not contain any sensitive information (especially PII).
*/
public static void reportAnomaly(@NonNull UUID eventId, String description) {
+ reportAnomaly(eventId, description, UNKNOWN_CARRIER_ID);
+ }
+
+ /**
+ * If enabled, build and send an intent to a Debug Service for logging.
+ *
+ * This method sends the {@link TelephonyManager#ACTION_ANOMALY_REPORTED} broadcast, which is
+ * system protected. Invoking this method unless you are the system will result in an error.
+ *
+ * @param eventId a fixed event ID that will be sent for each instance of the same event. This
+ * ID should be generated randomly.
+ * @param description an optional description, that if included will be used as the subject for
+ * identification and discussion of this event. This description should ideally be
+ * static and must not contain any sensitive information (especially PII).
+ * @param carrierId the carrier of the id associated with this event.
+ */
+ public static void reportAnomaly(@NonNull UUID eventId, String description, int carrierId) {
if (sContext == null) {
Rlog.w(TAG, "AnomalyReporter not yet initialized, dropping event=" + eventId);
return;
@@ -88,7 +108,7 @@ public final class AnomalyReporter {
TelephonyStatsLog.write(
TELEPHONY_ANOMALY_DETECTED,
- 0, // TODO: carrier id needs to be populated
+ carrierId,
eventId.getLeastSignificantBits(),
eventId.getMostSignificantBits());
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index 3a3b3632dc9b..ac1f376cf6b5 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -1661,8 +1661,8 @@ public final class DataFailCause {
/** @hide */
public static String toString(@DataFailureCause int dataFailCause) {
- int cause = getFailCause(dataFailCause);
- return (cause == UNKNOWN) ? "UNKNOWN(" + dataFailCause + ")" : sFailCauseMap.get(cause);
+ return sFailCauseMap.getOrDefault(dataFailCause, "UNKNOWN") + "(0x"
+ + Integer.toHexString(dataFailCause) + ")";
}
/** @hide */
@@ -1673,4 +1673,9 @@ public final class DataFailCause {
return UNKNOWN;
}
}
+
+ /** @hide */
+ public static boolean isFailCauseExisting(@DataFailureCause int failCause) {
+ return sFailCauseMap.containsKey(failCause);
+ }
}
diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java
index d91134e33ef3..d978f5701eca 100644
--- a/telephony/java/android/telephony/PhysicalChannelConfig.java
+++ b/telephony/java/android/telephony/PhysicalChannelConfig.java
@@ -23,16 +23,12 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.Annotation.NetworkType;
-import com.android.telephony.Rlog;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Objects;
public final class PhysicalChannelConfig implements Parcelable {
- static final String TAG = "PhysicalChannelConfig";
-
// TODO(b/72993578) consolidate these enums in a central location.
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -571,21 +567,19 @@ public final class PhysicalChannelConfig implements Parcelable {
public @NonNull Builder setNetworkType(@NetworkType int networkType) {
if (!TelephonyManager.isNetworkTypeValid(networkType)) {
- Rlog.e(TAG, "Builder.setNetworkType: Network type " + networkType + " is invalid.");
- } else {
- mNetworkType = networkType;
+ throw new IllegalArgumentException("Network type " + networkType + " is invalid.");
}
+ mNetworkType = networkType;
return this;
}
public @NonNull Builder setFrequencyRange(int frequencyRange) {
if (!ServiceState.isFrequencyRangeValid(frequencyRange)
&& frequencyRange != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
- Rlog.e(TAG, "Builder.setFrequencyRange: Frequency range " + frequencyRange
+ throw new IllegalArgumentException("Frequency range " + frequencyRange
+ " is invalid.");
- } else {
- mFrequencyRange = frequencyRange;
}
+ mFrequencyRange = frequencyRange;
return this;
}
@@ -601,21 +595,19 @@ public final class PhysicalChannelConfig implements Parcelable {
public @NonNull Builder setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz) {
if (cellBandwidthDownlinkKhz < CELL_BANDWIDTH_UNKNOWN) {
- Rlog.e(TAG, "Builder.setCellBandwidthDownlinkKhz: Cell downlink bandwidth(kHz) "
+ throw new IllegalArgumentException("Cell downlink bandwidth(kHz) "
+ cellBandwidthDownlinkKhz + " is invalid.");
- } else {
- mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz;
}
+ mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz;
return this;
}
public @NonNull Builder setCellBandwidthUplinkKhz(int cellBandwidthUplinkKhz) {
if (cellBandwidthUplinkKhz < CELL_BANDWIDTH_UNKNOWN) {
- Rlog.e(TAG, "Builder.setCellBandwidthUplinkKhz: Cell uplink bandwidth(kHz) "
+ throw new IllegalArgumentException("Cell uplink bandwidth(kHz) "
+ cellBandwidthUplinkKhz + " is invalid.");
- } else {
- mCellBandwidthUplinkKhz = cellBandwidthUplinkKhz;
}
+ mCellBandwidthUplinkKhz = cellBandwidthUplinkKhz;
return this;
}
@@ -632,20 +624,18 @@ public final class PhysicalChannelConfig implements Parcelable {
public @NonNull Builder setPhysicalCellId(int physicalCellId) {
if (physicalCellId > PHYSICAL_CELL_ID_MAXIMUM_VALUE) {
- Rlog.e(TAG, "Builder.setPhysicalCellId: Physical cell ID " + physicalCellId
+ throw new IllegalArgumentException("Physical cell ID " + physicalCellId
+ " is over limit.");
- } else {
- mPhysicalCellId = physicalCellId;
}
+ mPhysicalCellId = physicalCellId;
return this;
}
public @NonNull Builder setBand(int band) {
if (band <= BAND_UNKNOWN) {
- Rlog.e(TAG, "Builder.setBand: Band " + band + " is invalid.");
- } else {
- mBand = band;
+ throw new IllegalArgumentException("Band " + band + " is invalid.");
}
+ mBand = band;
return this;
}
}
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index b0ddf2c28dff..a710e38538ce 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1290,8 +1290,8 @@ public class ApnSetting implements Parcelable {
&& Objects.equals(this.mOperatorNumeric, other.mOperatorNumeric)
&& Objects.equals(this.mProtocol, other.mProtocol)
&& Objects.equals(this.mRoamingProtocol, other.mRoamingProtocol)
- && xorEqualsInt(this.mMtuV4, other.mMtuV4)
- && xorEqualsInt(this.mMtuV6, other.mMtuV6)
+ && mtuUnsetOrEquals(this.mMtuV4, other.mMtuV4)
+ && mtuUnsetOrEquals(this.mMtuV6, other.mMtuV6)
&& Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
&& Objects.equals(this.mNetworkTypeBitmask, other.mNetworkTypeBitmask)
&& Objects.equals(this.mLingeringNetworkTypeBitmask,
@@ -1319,7 +1319,12 @@ public class ApnSetting implements Parcelable {
// Equal or one is not specified.
private boolean xorEqualsInt(int first, int second) {
return first == UNSPECIFIED_INT || second == UNSPECIFIED_INT
- || Objects.equals(first, second);
+ || first == second;
+ }
+
+ // Equal or one is not specified. Specific to MTU where <= 0 indicates unset.
+ private boolean mtuUnsetOrEquals(int first, int second) {
+ return first <= 0 || second <= 0 || first == second;
}
private String nullToEmpty(String stringValue) {
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index ef02589abaf8..4afaf537f7c3 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -428,7 +428,7 @@ public final class DataCallResponse implements Parcelable {
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("DataCallResponse: {")
- .append(" cause=").append(mCause)
+ .append(" cause=").append(DataFailCause.toString(mCause))
.append(" retry=").append(mSuggestedRetryTime)
.append(" cid=").append(mId)
.append(" linkStatus=").append(mLinkStatus)
diff --git a/tests/ApkVerityTest/AndroidTest.xml b/tests/ApkVerityTest/AndroidTest.xml
index 55704eda905e..3c8e1ed99604 100644
--- a/tests/ApkVerityTest/AndroidTest.xml
+++ b/tests/ApkVerityTest/AndroidTest.xml
@@ -35,6 +35,8 @@
<option name="push" value="ApkVerityTestCert.der->/data/local/tmp/ApkVerityTestCert.der" />
</target_preparer>
+ <!-- Skip on HWASan. TODO(b/232288278): Re-enable -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.SkipHWASanModuleController" />
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
<option name="jar" value="ApkVerityTest.jar" />
</test>