Merge "MediaCodec: don't cache buffers until requested"
diff --git a/ApiDocs.bp b/ApiDocs.bp
index 39f055b..a542c5c 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -134,11 +134,7 @@
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/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java b/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
index 517e3ce..31c92ba 100644
--- a/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
@@ -70,6 +70,9 @@
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
ZipFile zf = new ZipFile(mFile);
+ state.pauseTiming();
+ zf.close();
+ state.resumeTiming();
}
}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java
index 32117dc..03c9d43 100644
--- a/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java
@@ -141,15 +141,6 @@
}
@Test
- public void timeNumberFormatTrivialFormatLong() {
- NumberFormat nf = NumberFormat.getInstance(Locale.US);
- BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- while (state.keepRunning()) {
- nf.format(1024L);
- }
- }
-
- @Test
public void timeLongToString() {
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/HostnameVerifierPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/HostnameVerifierPerfTest.java
deleted file mode 100644
index f2b7fdf..0000000
--- a/apct-tests/perftests/core/src/android/libcore/regression/HostnameVerifierPerfTest.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * 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.libcore.regression;
-
-import android.perftests.utils.BenchmarkState;
-import android.perftests.utils.PerfStatusReporter;
-import android.test.suitebuilder.annotation.LargeTest;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-import java.io.ByteArrayInputStream;
-import java.net.URL;
-import java.security.Principal;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateFactory;
-import java.util.Arrays;
-import java.util.Collection;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSessionContext;
-
-/**
- * This benchmark makes a real HTTP connection to a handful of hosts and
- * captures the served certificates as a byte array. It then verifies each
- * certificate in the benchmark loop, being careful to convert from the
- * byte[] to the certificate each time. Otherwise the certificate class
- * caches previous results which skews the results of the benchmark: In practice
- * each certificate instance is verified once and then released.
- */
-@RunWith(Parameterized.class)
-@LargeTest
-public final class HostnameVerifierPerfTest {
- @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
-
- @Parameters(name = "mHost({0})")
- public static Collection<Object[]> data() {
- return Arrays.asList(
- new Object[][] {
- {"m.google.com"},
- {"www.google.com"},
- {"www.amazon.com"},
- {"www.ubs.com"}
- });
- }
-
- @Parameterized.Parameter(0)
- public String mHost;
-
-
- private String mHostname;
- private HostnameVerifier mHostnameVerifier;
- private byte[][] mEncodedCertificates;
-
- @Before
- public void setUp() throws Exception {
- URL url = new URL("https", mHost, "/");
- mHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
- HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
- connection.setHostnameVerifier(new HostnameVerifier() {
- public boolean verify(String mHostname, SSLSession sslSession) {
- try {
- mEncodedCertificates = certificatesToBytes(sslSession.getPeerCertificates());
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- HostnameVerifierPerfTest.this.mHostname = mHostname;
- return true;
- }
- });
- connection.getInputStream();
- connection.disconnect();
- }
-
- @Test
- public void timeVerify() throws Exception {
- BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- while (state.keepRunning()) {
- final Certificate[] certificates = bytesToCertificates(mEncodedCertificates);
- FakeSSLSession sslSession = new FakeSSLSession() {
- @Override public Certificate[] getPeerCertificates() {
- return certificates;
- }
- };
- mHostnameVerifier.verify(mHostname, sslSession);
- }
- }
-
- private byte[][] certificatesToBytes(Certificate[] certificates) throws Exception {
- byte[][] result = new byte[certificates.length][];
- for (int i = 0, certificatesLength = certificates.length; i < certificatesLength; i++) {
- result[i] = certificates[i].getEncoded();
- }
- return result;
- }
-
- private Certificate[] bytesToCertificates(byte[][] encodedCertificates) throws Exception {
- CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
- Certificate[] result = new Certificate[encodedCertificates.length];
- for (int i = 0; i < encodedCertificates.length; i++) {
- result[i] = certificateFactory.generateCertificate(
- new ByteArrayInputStream(encodedCertificates[i]));
- }
- return result;
- }
-
- private static class FakeSSLSession implements SSLSession {
- public int getApplicationBufferSize() {
- throw new UnsupportedOperationException();
- }
- public String getCipherSuite() {
- throw new UnsupportedOperationException();
- }
- public long getCreationTime() {
- throw new UnsupportedOperationException();
- }
- public byte[] getId() {
- throw new UnsupportedOperationException();
- }
- public long getLastAccessedTime() {
- throw new UnsupportedOperationException();
- }
- public Certificate[] getLocalCertificates() {
- throw new UnsupportedOperationException();
- }
- public Principal getLocalPrincipal() {
- throw new UnsupportedOperationException();
- }
- public int getPacketBufferSize() {
- throw new UnsupportedOperationException();
- }
- public javax.security.cert.X509Certificate[] getPeerCertificateChain() {
- throw new UnsupportedOperationException();
- }
- public Certificate[] getPeerCertificates() {
- throw new UnsupportedOperationException();
- }
- public String getPeerHost() {
- throw new UnsupportedOperationException();
- }
- public int getPeerPort() {
- throw new UnsupportedOperationException();
- }
- public Principal getPeerPrincipal() {
- throw new UnsupportedOperationException();
- }
- public String getProtocol() {
- throw new UnsupportedOperationException();
- }
- public SSLSessionContext getSessionContext() {
- throw new UnsupportedOperationException();
- }
- public Object getValue(String name) {
- throw new UnsupportedOperationException();
- }
- public String[] getValueNames() {
- throw new UnsupportedOperationException();
- }
- public void invalidate() {
- throw new UnsupportedOperationException();
- }
- public boolean isValid() {
- throw new UnsupportedOperationException();
- }
- public void putValue(String name, Object value) {
- throw new UnsupportedOperationException();
- }
- public void removeValue(String name) {
- throw new UnsupportedOperationException();
- }
- }
-}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/NumberFormatTrivialFormatLongPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/NumberFormatTrivialFormatLongPerfTest.java
new file mode 100644
index 0000000..5ff2b22
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/NumberFormatTrivialFormatLongPerfTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.text.NumberFormat;
+import java.util.Locale;
+
+/**
+ * Benchmarks creation and cloning various expensive objects.
+ */
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class NumberFormatTrivialFormatLongPerfTest {
+ @Rule
+ public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ @Test
+ public void timeNumberFormatTrivialFormatLong() {
+ NumberFormat nf = NumberFormat.getInstance(Locale.US);
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ nf.format(1024L);
+ }
+ }
+}
diff --git a/api/api.go b/api/api.go
index 9cd0132..93f1354 100644
--- a/api/api.go
+++ b/api/api.go
@@ -179,7 +179,7 @@
// 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/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 52fd7be..6582623 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -509,7 +509,8 @@
resolution = limitSurfaceSize(resolution.width, resolution.height);
// create the native surface
sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
- resolution.getWidth(), resolution.getHeight(), PIXEL_FORMAT_RGB_565);
+ resolution.getWidth(), resolution.getHeight(), PIXEL_FORMAT_RGB_565,
+ ISurfaceComposerClient::eOpaque);
SurfaceComposerClient::Transaction t;
diff --git a/core/api/current.txt b/core/api/current.txt
index e4fc9f3..18286eb 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -11473,7 +11473,7 @@
field public static final String FEATURE_CAMERA_LEVEL_FULL = "android.hardware.camera.level.full";
field public static final String FEATURE_CANT_SAVE_STATE = "android.software.cant_save_state";
field public static final String FEATURE_COMPANION_DEVICE_SETUP = "android.software.companion_device_setup";
- field public static final String FEATURE_CONNECTION_SERVICE = "android.software.connectionservice";
+ field @Deprecated public static final String FEATURE_CONNECTION_SERVICE = "android.software.connectionservice";
field public static final String FEATURE_CONSUMER_IR = "android.hardware.consumerir";
field public static final String FEATURE_CONTROLS = "android.software.controls";
field public static final String FEATURE_DEVICE_ADMIN = "android.software.device_admin";
@@ -11544,12 +11544,18 @@
field public static final String FEATURE_SIP = "android.software.sip";
field public static final String FEATURE_SIP_VOIP = "android.software.sip.voip";
field public static final String FEATURE_STRONGBOX_KEYSTORE = "android.hardware.strongbox_keystore";
+ field public static final String FEATURE_TELECOM = "android.software.telecom";
field public static final String FEATURE_TELEPHONY = "android.hardware.telephony";
+ field public static final String FEATURE_TELEPHONY_CALLING = "android.hardware.telephony.calling";
field public static final String FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma";
+ field public static final String FEATURE_TELEPHONY_DATA = "android.hardware.telephony.data";
field public static final String FEATURE_TELEPHONY_EUICC = "android.hardware.telephony.euicc";
field public static final String FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm";
field public static final String FEATURE_TELEPHONY_IMS = "android.hardware.telephony.ims";
field public static final String FEATURE_TELEPHONY_MBMS = "android.hardware.telephony.mbms";
+ field public static final String FEATURE_TELEPHONY_MESSAGING = "android.hardware.telephony.messaging";
+ field public static final String FEATURE_TELEPHONY_RADIO_ACCESS = "android.hardware.telephony.radio";
+ field public static final String FEATURE_TELEPHONY_SUBSCRIPTION = "android.hardware.telephony.subscription";
field @Deprecated public static final String FEATURE_TELEVISION = "android.hardware.type.television";
field public static final String FEATURE_TOUCHSCREEN = "android.hardware.touchscreen";
field public static final String FEATURE_TOUCHSCREEN_MULTITOUCH = "android.hardware.touchscreen.multitouch";
@@ -21438,6 +21444,7 @@
field public static final String KEY_VIDEO_QP_P_MAX = "video-qp-p-max";
field public static final String KEY_VIDEO_QP_P_MIN = "video-qp-p-min";
field public static final String KEY_WIDTH = "width";
+ field public static final String LOG_SESSION_ID = "log-session-id";
field public static final String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
field public static final String MIMETYPE_AUDIO_AC3 = "audio/ac3";
field public static final String MIMETYPE_AUDIO_AC4 = "audio/ac4";
@@ -41215,8 +41222,11 @@
field public static final String MMS_CONFIG_UA_PROF_URL = "uaProfUrl";
field public static final String MMS_CONFIG_USER_AGENT = "userAgent";
field public static final int MMS_ERROR_CONFIGURATION_ERROR = 7; // 0x7
+ field public static final int MMS_ERROR_DATA_DISABLED = 11; // 0xb
field public static final int MMS_ERROR_HTTP_FAILURE = 4; // 0x4
+ field public static final int MMS_ERROR_INACTIVE_SUBSCRIPTION = 10; // 0xa
field public static final int MMS_ERROR_INVALID_APN = 2; // 0x2
+ field public static final int MMS_ERROR_INVALID_SUBSCRIPTION_ID = 9; // 0x9
field public static final int MMS_ERROR_IO_ERROR = 5; // 0x5
field public static final int MMS_ERROR_NO_DATA_NETWORK = 8; // 0x8
field public static final int MMS_ERROR_RETRY = 6; // 0x6
diff --git a/core/java/android/app/time/ExternalTimeSuggestion.java b/core/java/android/app/time/ExternalTimeSuggestion.java
index a7c0e5c..a7828ab 100644
--- a/core/java/android/app/time/ExternalTimeSuggestion.java
+++ b/core/java/android/app/time/ExternalTimeSuggestion.java
@@ -19,15 +19,14 @@
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 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 @@
}
};
- @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 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 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(mUnixEpochTime, 0);
- dest.writeList(mDebugInfo);
+ mTimeSuggestionHelper.handleWriteToParcel(dest, flags);
}
/**
@@ -127,7 +119,7 @@
*/
@NonNull
public TimestampedValue<Long> getUnixEpochTime() {
- return mUnixEpochTime;
+ return mTimeSuggestionHelper.getUnixEpochTime();
}
/**
@@ -135,9 +127,7 @@
*/
@NonNull
public List<String> getDebugInfo() {
- return mDebugInfo == null
- ? Collections.emptyList()
- : Collections.unmodifiableList(mDebugInfo);
+ return mTimeSuggestionHelper.getDebugInfo();
}
/**
@@ -146,10 +136,7 @@
* #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 @@
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 34f4565..3531b19 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 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 @@
}
};
- @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 @@
@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 @@
* {@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 @@
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 76db33b..b447799 100644
--- a/core/java/android/app/timedetector/ManualTimeSuggestion.java
+++ b/core/java/android/app/timedetector/ManualTimeSuggestion.java
@@ -20,27 +20,17 @@
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 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 @@
}
};
- @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 @@
@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 @@
* {@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 @@
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 e22f1d6e..e93c75c 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 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 @@
}
};
- @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 @@
@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 @@
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 4ff7517..6f204d6 100644
--- a/core/java/android/app/timedetector/TelephonyTimeSuggestion.java
+++ b/core/java/android/app/timedetector/TelephonyTimeSuggestion.java
@@ -20,8 +20,10 @@
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 @@
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 a356230..f0d77761 100644
--- a/core/java/android/app/timedetector/TimeDetector.java
+++ b/core/java/android/app/timedetector/TimeDetector.java
@@ -44,6 +44,36 @@
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 0000000..9b99be6
--- /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/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 5119010..ce21214 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2929,6 +2929,8 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device has a CDMA telephony stack.
+ *
+ * <p>This feature should only be defined if {@link #FEATURE_TELEPHONY} has been defined.
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma";
@@ -2936,6 +2938,8 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device has a GSM telephony stack.
+ *
+ * <p>This feature should only be defined if {@link #FEATURE_TELEPHONY} has been defined.
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm";
@@ -2947,6 +2951,9 @@
* <p>Devices declaring this feature must have an implementation of the
* {@link android.telephony.TelephonyManager#getAllowedCarriers} and
* {@link android.telephony.TelephonyManager#setAllowedCarriers}.
+ *
+ * This feature should only be defined if {@link #FEATURE_TELEPHONY_SUBSCRIPTION}
+ * has been defined.
* @hide
*/
@SystemApi
@@ -2957,6 +2964,9 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device
* supports embedded subscriptions on eUICCs.
+ *
+ * This feature should only be defined if {@link #FEATURE_TELEPHONY_SUBSCRIPTION}
+ * has been defined.
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_TELEPHONY_EUICC = "android.hardware.telephony.euicc";
@@ -2964,6 +2974,9 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device
* supports cell-broadcast reception using the MBMS APIs.
+ *
+ * <p>This feature should only be defined if both {@link #FEATURE_TELEPHONY_SUBSCRIPTION}
+ * and {@link #FEATURE_TELEPHONY_RADIO_ACCESS} have been defined.
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_TELEPHONY_MBMS = "android.hardware.telephony.mbms";
@@ -2971,6 +2984,8 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device
* supports attaching to IMS implementations using the ImsService API in telephony.
+ *
+ * <p>This feature should only be defined if {@link #FEATURE_TELEPHONY_DATA} has been defined.
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_TELEPHONY_IMS = "android.hardware.telephony.ims";
@@ -3007,6 +3022,62 @@
"android.hardware.telephony.ims.singlereg";
/**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device supports Telecom Service APIs.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_TELECOM = "android.software.telecom";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device supports Telephony APIs for calling service.
+ *
+ * <p>This feature should only be defined if {@link #FEATURE_TELEPHONY_RADIO_ACCESS},
+ * {@link #FEATURE_TELEPHONY_SUBSCRIPTION}, and {@link #FEATURE_TELECOM} have been defined.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_TELEPHONY_CALLING = "android.hardware.telephony.calling";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device supports Telephony APIs for data service.
+ *
+ * <p>This feature should only be defined if both {@link #FEATURE_TELEPHONY_SUBSCRIPTION}
+ * and {@link #FEATURE_TELEPHONY_RADIO_ACCESS} have been defined.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_TELEPHONY_DATA = "android.hardware.telephony.data";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device supports Telephony APIs for SMS and MMS.
+ *
+ * <p>This feature should only be defined if both {@link #FEATURE_TELEPHONY_SUBSCRIPTION}
+ * and {@link #FEATURE_TELEPHONY_RADIO_ACCESS} have been defined.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_TELEPHONY_MESSAGING = "android.hardware.telephony.messaging";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device supports Telephony APIs for the radio access.
+ *
+ * <p>This feature should only be defined if {@link #FEATURE_TELEPHONY} has been defined.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_TELEPHONY_RADIO_ACCESS = "android.hardware.telephony.radio";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device supports Telephony APIs for the subscription.
+ *
+ * <p>This feature should only be defined if {@link #FEATURE_TELEPHONY} has been defined.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_TELEPHONY_SUBSCRIPTION =
+ "android.hardware.telephony.subscription";
+
+ /**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device is capable of communicating with
* other devices via ultra wideband.
@@ -3047,7 +3118,9 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The Connection Service API is enabled on the device.
+ * @deprecated use {@link #FEATURE_TELECOM} instead.
*/
+ @Deprecated
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_CONNECTION_SERVICE = "android.software.connectionservice";
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index b3851a5..d24a95d 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 c112cbb..6f2366e 100644
--- a/core/tests/PackageInstallerSessions/Android.bp
+++ b/core/tests/PackageInstallerSessions/Android.bp
@@ -50,7 +50,6 @@
":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 f87797a..2b34ee2 100644
--- a/core/tests/bugreports/Android.bp
+++ b/core/tests/bugreports/Android.bp
@@ -36,7 +36,6 @@
],
test_suites: ["general-tests"],
sdk_version: "test_current",
- platform_apis: true,
}
filegroup {
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 05ec00f..f971af1 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -72,7 +72,6 @@
"libpowermanagertest_jni",
],
- platform_apis: true,
sdk_version: "core_platform",
test_suites: ["device-tests"],
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 0000000..90b3305
--- /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 e248010..af403a2 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 @@
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 @@
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 750ffa1..94218cd 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 @@
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 @@
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 b88c36f..0e09dd3 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 @@
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 @@
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 cc75579..bb995a8 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 @@
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 @@
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 8d8290c..4efaed1 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.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 9ad6f3a..6fff52a 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java
@@ -206,6 +206,8 @@
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 8289671..5216a90 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
@@ -29,7 +29,10 @@
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 @@
* @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 @@
}
}
+ 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 @@
@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 0000000..4855ad0
--- /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 0000000..642e088
--- /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/AndroidKeyStoreKeyAgreementSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyAgreementSpi.java
index fc963a8..b1338d1 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyAgreementSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyAgreementSpi.java
@@ -61,6 +61,17 @@
}
}
+ /**
+ * X25519 key agreement support.
+ *
+ * @hide
+ */
+ public static class XDH extends AndroidKeyStoreKeyAgreementSpi {
+ public XDH() {
+ super(Algorithm.EC);
+ }
+ }
+
private final int mKeymintAlgorithm;
// Fields below are populated by engineInit and should be preserved after engineDoFinal.
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
index d31499e..9947d34 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
@@ -104,6 +104,7 @@
// javax.crypto.KeyAgreement
put("KeyAgreement.ECDH", PACKAGE_NAME + ".AndroidKeyStoreKeyAgreementSpi$ECDH");
+ put("KeyAgreement.XDH", PACKAGE_NAME + ".AndroidKeyStoreKeyAgreementSpi$XDH");
// java.security.SecretKeyFactory
putSecretKeyFactoryImpl("AES");
@@ -224,7 +225,6 @@
String jcaKeyAlgorithm = publicKey.getAlgorithm();
- KeyStoreSecurityLevel securityLevel = iSecurityLevel;
if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(jcaKeyAlgorithm)) {
return new AndroidKeyStoreECPublicKey(descriptor, metadata,
iSecurityLevel, (ECPublicKey) publicKey);
@@ -232,11 +232,12 @@
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");
+ return new AndroidKeyStoreXDHPublicKey(descriptor, metadata, X25519_ALIAS,
+ iSecurityLevel, publicKey.getEncoded());
} else {
throw new ProviderException("Unsupported Android Keystore public key algorithm: "
+ jcaKeyAlgorithm);
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreXDHPrivateKey.java b/keystore/java/android/security/keystore2/AndroidKeyStoreXDHPrivateKey.java
new file mode 100644
index 0000000..42589640
--- /dev/null
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreXDHPrivateKey.java
@@ -0,0 +1,47 @@
+/*
+ * 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;
+
+/**
+ * X25519 Private Key backed by Keystore.
+ * instance of {@link PrivateKey} and {@link EdECKey}
+ *
+ * @hide
+ */
+public class AndroidKeyStoreXDHPrivateKey extends AndroidKeyStorePrivateKey implements EdECKey {
+ public AndroidKeyStoreXDHPrivateKey(
+ @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.X25519;
+ }
+}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreXDHPublicKey.java b/keystore/java/android/security/keystore2/AndroidKeyStoreXDHPublicKey.java
new file mode 100644
index 0000000..9f3df3d
--- /dev/null
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreXDHPublicKey.java
@@ -0,0 +1,120 @@
+/*
+ * 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.XECPublicKey;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.NamedParameterSpec;
+import java.util.Arrays;
+
+/**
+ * {@link XECPublicKey} backed by keystore.
+ * This class re-implements Conscrypt's OpenSSLX25519PublicKey. The reason is that
+ * OpenSSLX25519PublicKey does not implement XECPublicKey and is not a part of Conscrypt's public
+ * interface so it cannot be referred to.
+ *
+ * So the functionality is duplicated here until (likely Android U) one of the things mentioned
+ * above is fixed.
+ *
+ * @hide
+ */
+public class AndroidKeyStoreXDHPublicKey extends AndroidKeyStorePublicKey implements XECPublicKey {
+ private static final byte[] X509_PREAMBLE = new byte[] {
+ 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x6e, 0x03, 0x21, 0x00,
+ };
+
+ private static final byte[] X509_PREAMBLE_WITH_NULL = new byte[] {
+ 0x30, 0x2C, 0x30, 0x07, 0x06, 0x03, 0x2B, 0x65, 0x6E, 0x05, 0x00, 0x03, 0x21, 0x00,
+ };
+
+ private static final int X25519_KEY_SIZE_BYTES = 32;
+
+ private final byte[] mEncodedKey;
+ private final int mPreambleLength;
+
+ public AndroidKeyStoreXDHPublicKey(
+ @NonNull KeyDescriptor descriptor,
+ @NonNull KeyMetadata metadata,
+ @NonNull String algorithm,
+ @NonNull KeyStoreSecurityLevel iSecurityLevel,
+ @NonNull byte[] encodedKey) {
+ super(descriptor, metadata, encodedKey, algorithm, iSecurityLevel);
+ mEncodedKey = encodedKey;
+ if (mEncodedKey == null) {
+ throw new IllegalArgumentException("empty encoded key.");
+ }
+
+ mPreambleLength = matchesPreamble(X509_PREAMBLE, mEncodedKey) | matchesPreamble(
+ X509_PREAMBLE_WITH_NULL, mEncodedKey);
+ if (mPreambleLength == 0) {
+ throw new IllegalArgumentException("Key size is not correct size");
+ }
+ }
+
+ private static int matchesPreamble(byte[] preamble, byte[] encoded) {
+ if (encoded.length != (preamble.length + X25519_KEY_SIZE_BYTES)) {
+ return 0;
+ }
+
+ if (Arrays.compare(preamble, 0, preamble.length, encoded, 0, preamble.length) != 0) {
+ return 0;
+ }
+ return preamble.length;
+ }
+
+ @Override
+ AndroidKeyStorePrivateKey getPrivateKey() {
+ return new AndroidKeyStoreXDHPrivateKey(
+ getUserKeyDescriptor(),
+ getKeyIdDescriptor().nspace,
+ getAuthorizations(),
+ "x25519",
+ getSecurityLevel());
+ }
+
+ @Override
+ public BigInteger getU() {
+ return new BigInteger(Arrays.copyOfRange(mEncodedKey, mPreambleLength, mEncodedKey.length));
+ }
+
+ @Override
+ public byte[] getEncoded() {
+ return mEncodedKey.clone();
+ }
+
+ @Override
+ public String getAlgorithm() {
+ return "XDH";
+ }
+
+ @Override
+ public String getFormat() {
+ return "x.509";
+ }
+
+ @Override
+ public AlgorithmParameterSpec getParams() {
+ return NamedParameterSpec.X25519;
+ }
+}
+
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 0000000..5bd5797
--- /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/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 050ae72..66e2c41 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -230,9 +230,10 @@
/**
* A key describing the log session ID for MediaCodec. The log session ID is a random 32-byte
* hexadecimal string that is used to associate metrics from multiple media codec instances
- * to the same playback or recording session.
+ * to the same playback or recording session. The value is created as
+ * {@link android.media.metrics.LogSessionId LogSessionId}. Sessions are created in
+ * {@link android.media.metrics.MediaMetricsManager MediaMetricsManager}.
* The associated value is a string.
- * @hide
*/
public static final String LOG_SESSION_ID = "log-session-id";
diff --git a/packages/SettingsLib/ActionBarShadow/Android.bp b/packages/SettingsLib/ActionBarShadow/Android.bp
index 4a07d49..2c86201 100644
--- a/packages/SettingsLib/ActionBarShadow/Android.bp
+++ b/packages/SettingsLib/ActionBarShadow/Android.bp
@@ -20,4 +20,8 @@
sdk_version: "system_current",
min_sdk_version: "28",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.permission",
+ ],
}
diff --git a/packages/SettingsLib/AppPreference/Android.bp b/packages/SettingsLib/AppPreference/Android.bp
index 1817a77..122f606 100644
--- a/packages/SettingsLib/AppPreference/Android.bp
+++ b/packages/SettingsLib/AppPreference/Android.bp
@@ -20,4 +20,8 @@
],
sdk_version: "system_current",
min_sdk_version: "21",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.permission",
+ ],
}
diff --git a/packages/SettingsLib/BarChartPreference/Android.bp b/packages/SettingsLib/BarChartPreference/Android.bp
index 4f65373..5c5da98 100644
--- a/packages/SettingsLib/BarChartPreference/Android.bp
+++ b/packages/SettingsLib/BarChartPreference/Android.bp
@@ -19,4 +19,8 @@
sdk_version: "system_current",
min_sdk_version: "21",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.permission",
+ ],
}
diff --git a/packages/SettingsLib/HelpUtils/Android.bp b/packages/SettingsLib/HelpUtils/Android.bp
index 5826047..aea51b1 100644
--- a/packages/SettingsLib/HelpUtils/Android.bp
+++ b/packages/SettingsLib/HelpUtils/Android.bp
@@ -19,4 +19,8 @@
sdk_version: "system_current",
min_sdk_version: "21",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.permission",
+ ],
}
diff --git a/packages/SettingsLib/LayoutPreference/Android.bp b/packages/SettingsLib/LayoutPreference/Android.bp
index 8a4e53d..aaffdc9 100644
--- a/packages/SettingsLib/LayoutPreference/Android.bp
+++ b/packages/SettingsLib/LayoutPreference/Android.bp
@@ -14,9 +14,13 @@
resource_dirs: ["res"],
static_libs: [
- "androidx.preference_preference",
+ "androidx.preference_preference",
],
sdk_version: "system_current",
min_sdk_version: "21",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.permission",
+ ],
}
diff --git a/packages/SettingsLib/ProgressBar/Android.bp b/packages/SettingsLib/ProgressBar/Android.bp
index b5bc8f7..fb3c4e6 100644
--- a/packages/SettingsLib/ProgressBar/Android.bp
+++ b/packages/SettingsLib/ProgressBar/Android.bp
@@ -15,4 +15,8 @@
sdk_version: "system_current",
min_sdk_version: "21",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.permission",
+ ],
}
diff --git a/packages/SettingsLib/RestrictedLockUtils/Android.bp b/packages/SettingsLib/RestrictedLockUtils/Android.bp
index c0623ed..a7dcf8d 100644
--- a/packages/SettingsLib/RestrictedLockUtils/Android.bp
+++ b/packages/SettingsLib/RestrictedLockUtils/Android.bp
@@ -19,4 +19,8 @@
sdk_version: "system_current",
min_sdk_version: "21",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.permission",
+ ],
}
diff --git a/packages/SettingsLib/SearchWidget/Android.bp b/packages/SettingsLib/SearchWidget/Android.bp
index b7367b4..5aaee2a 100644
--- a/packages/SettingsLib/SearchWidget/Android.bp
+++ b/packages/SettingsLib/SearchWidget/Android.bp
@@ -14,4 +14,8 @@
resource_dirs: ["res"],
sdk_version: "system_current",
min_sdk_version: "21",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.permission",
+ ],
}
diff --git a/packages/SettingsLib/SettingsTheme/Android.bp b/packages/SettingsLib/SettingsTheme/Android.bp
index 73459c2..da01f62 100644
--- a/packages/SettingsLib/SettingsTheme/Android.bp
+++ b/packages/SettingsLib/SettingsTheme/Android.bp
@@ -13,13 +13,14 @@
resource_dirs: ["res"],
static_libs: [
- "androidx.preference_preference",
- ],
+ "androidx.preference_preference",
+ ],
sdk_version: "system_current",
min_sdk_version: "21",
apex_available: [
"//apex_available:platform",
"com.android.cellbroadcast",
+ "com.android.permission",
],
}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index ff4c2c6..c4d4261 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 9676a57..91c7a24 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 @@
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 88d0b61..0000000
--- 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 406ff9b..a81699f 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 @@
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 28c7cad..ab3b250 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 @@
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.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 @@
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,39 +72,42 @@
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 synchronized void closePipe() {
- try {
- final FileDescriptor fd = mPipe;
- mPipe = null;
- if (fd != null) {
- Os.close(fd);
- }
- } catch (ErrnoException ignore) {
+ private static FileDescriptor openPipe() throws InterruptedException {
+ FileDescriptor 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();
}
+
+ return fd;
}
- private byte[] receiveMessage() throws ErrnoException, InterruptedIOException {
+ private static byte[] receiveMessage(final FileDescriptor fd) throws ErrnoException,
+ InterruptedIOException, EOFException {
final byte[] lengthBits = new byte[4];
- Os.read(mPipe, lengthBits, 0, lengthBits.length);
+ readFully(fd, 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(fd, msg, 0, msg.length);
return msg;
}
@@ -115,35 +120,46 @@
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(() -> {
+ FileDescriptor fd = null;
+
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);
+ if (fd == null) {
+ fd = openPipe();
+ setPipeFD(fd);
}
- final byte[] receivedData = receiveMessage();
+ final byte[] receivedData = receiveMessage(fd);
final String str = new String(receivedData);
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) {
- closePipe();
- } catch (InterruptedException | IllegalArgumentException e) {
+ } catch (ErrnoException | EOFException | InterruptedIOException
+ | InterruptedException e) {
+ setPipeFD(null);
+
+ try {
+ Os.close(fd);
+ } catch (ErrnoException e2) {
+ // ignore
+ }
+
+ fd = null;
}
}
});
@@ -153,33 +169,70 @@
@Override
public void accept(final @Nullable ClipData clip) {
+ final FileDescriptor fd = getPipeFD();
+ if (fd != null) {
+ setHostClipboard(fd, getClipString(clip));
+ }
+ }
+
+ private String getClipString(final @Nullable ClipData clip) {
if (clip == null) {
- setHostClipboardImpl("");
- } else if (clip.getItemCount() > 0) {
- final CharSequence text = clip.getItemAt(0).getText();
- if (text != null) {
- setHostClipboardImpl(text.toString());
+ return "";
+ }
+
+ if (clip.getItemCount() == 0) {
+ return "";
+ }
+
+ final CharSequence text = clip.getItemAt(0).getText();
+ if (text == null) {
+ return "";
+ }
+
+ return text.toString();
+ }
+
+ private static void setHostClipboard(final FileDescriptor fd, final String value) {
+ Thread t = new Thread(() -> {
+ if (LOG_CLIBOARD_ACCESS) {
+ Slog.i(TAG, "Setting the host clipboard to '" + value + "'");
+ }
+
+ try {
+ sendMessage(fd, value.getBytes());
+ } catch (ErrnoException | InterruptedIOException e) {
+ Slog.e(TAG, "Failed to set host clipboard " + e.getMessage());
+ } catch (IllegalArgumentException e) {
+ }
+ });
+ 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 void setHostClipboardImpl(final String value) {
- final FileDescriptor pipeFD = getPipeFD();
-
- if (pipeFD != null) {
- Thread t = new Thread(() -> {
- if (LOG_CLIBOARD_ACCESS) {
- Slog.i(TAG, "Setting the host clipboard to '" + value + "'");
- }
-
- try {
- sendMessage(pipeFD, value.getBytes());
- } catch (ErrnoException | InterruptedIOException e) {
- Slog.e(TAG, "Failed to set host clipboard " + e.getMessage());
- } catch (IllegalArgumentException e) {
- }
- });
- t.start();
+ 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 d07f151..f0f1870 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1621,11 +1621,19 @@
}
// 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);
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from
+ // ConnectivityServiceTest.
+ if (Process.isApplicationUid(uid) && SdkLevel.isAtLeastT()) {
+ uids.add(Process.toSdkSandboxUid(uid));
+ }
}
return uids;
}
diff --git a/services/core/java/com/android/server/timedetector/EnvironmentImpl.java b/services/core/java/com/android/server/timedetector/EnvironmentImpl.java
index 7649958..9d26351 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.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 @@
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 721986b..cc5e6fe 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 @@
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 @@
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 @@
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 @@
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 ae4d46c..33ab104 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 @@
*/
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 @@
/** 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 @@
.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 @@
+ ", 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/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
index 7e4f0e7..2617f4d 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
@@ -38,5 +38,4 @@
"androidx.test.rules",
"truth-prebuilt",
],
- platform_apis: true,
}
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 a227cd3..035249e 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 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 @@
}
}
+ @Ignore("Causing breakages so ignoring to resolve, b/231667368")
@Test
public void initRecoveryService_alwaysUpdatesCertsWhenTestRootCertIsUsed() throws Exception {
int uid = Binder.getCallingUid();
@@ -539,6 +541,7 @@
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 2d9903f..2248ddb 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 @@
.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 @@
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 @@
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 @@
return this;
}
+ Script pokeDeviceHasY2038Issues(boolean hasIssues) {
+ mFakeEnvironment.setDeviceHas2038Issues(hasIssues);
+ return this;
+ }
+
long peekElapsedRealtimeMillis() {
return mFakeEnvironment.peekElapsedRealtimeMillis();
}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 6122b08..8a8cdb0 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -20,6 +20,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SuppressAutoDoc;
import android.annotation.SuppressLint;
@@ -31,6 +32,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -70,6 +72,7 @@
*/
@SuppressAutoDoc
@SystemService(Context.TELECOM_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_TELECOM)
public class TelecomManager {
/**
diff --git a/telephony/java/android/telephony/AnomalyReporter.java b/telephony/java/android/telephony/AnomalyReporter.java
index f47cf33..e7d95e4 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 @@
*
* 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 @@
* 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 @@
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/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 0d0142c..8956b46 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -20,6 +20,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SuppressAutoDoc;
import android.annotation.SuppressLint;
@@ -28,6 +29,7 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.net.NetworkCapabilities;
import android.net.ipsec.ike.SaProposal;
import android.os.Build;
@@ -55,6 +57,7 @@
* Provides access to telephony configuration values that are carrier-specific.
*/
@SystemService(Context.CARRIER_CONFIG_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public class CarrierConfigManager {
private final static String TAG = "CarrierConfigManager";
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index fa6de1a..ac1f376 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -1673,4 +1673,9 @@
return UNKNOWN;
}
}
+
+ /** @hide */
+ public static boolean isFailCauseExisting(@DataFailureCause int failCause) {
+ return sFailCauseMap.containsKey(failCause);
+ }
}
diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java
index 6b9871c..b0ff949 100644
--- a/telephony/java/android/telephony/ImsManager.java
+++ b/telephony/java/android/telephony/ImsManager.java
@@ -17,11 +17,13 @@
package android.telephony.ims;
import android.annotation.NonNull;
+import android.annotation.RequiresFeature;
import android.annotation.SdkConstant;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.telephony.BinderCacheManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyFrameworkInitializer;
@@ -33,6 +35,7 @@
* Provides access to information about Telephony IMS services on the device.
*/
@SystemService(Context.TELEPHONY_IMS_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_TELEPHONY_IMS)
public class ImsManager {
/**
diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java
index d91134e..d978f57 100644
--- a/telephony/java/android/telephony/PhysicalChannelConfig.java
+++ b/telephony/java/android/telephony/PhysicalChannelConfig.java
@@ -23,16 +23,12 @@
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 @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 @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 @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/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 5171cf9..7df06b0 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -22,6 +22,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SuppressAutoDoc;
import android.annotation.SystemApi;
@@ -32,6 +33,7 @@
import android.compat.annotation.EnabledAfter;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.database.CursorWindow;
import android.net.Uri;
import android.os.Build;
@@ -75,6 +77,7 @@
*
* @see SubscriptionManager#getActiveSubscriptionInfoList()
*/
+@RequiresFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)
public final class SmsManager {
private static final String TAG = "SmsManager";
@@ -2633,6 +2636,19 @@
* sending the message.
* @param sentIntent if not NULL this <code>PendingIntent</code> is
* broadcast when the message is successfully sent, or failed
+ * The result code will be <code>Activity.RESULT_OK</code> for success
+ * or one of these errors:<br>
+ * <code>MMS_ERROR_UNSPECIFIED</code><br>
+ * <code>MMS_ERROR_INVALID_APN</code><br>
+ * <code>MMS_ERROR_UNABLE_CONNECT_MMS</code><br>
+ * <code>MMS_ERROR_HTTP_FAILURE</code><br>
+ * <code>MMS_ERROR_IO_ERROR</code><br>
+ * <code>MMS_ERROR_RETRY</code><br>
+ * <code>MMS_ERROR_CONFIGURATION_ERROR</code><br>
+ * <code>MMS_ERROR_NO_DATA_NETWORK</code><br>
+ * <code>MMS_ERROR_INVALID_SUBSCRIPTION_ID</code><br>
+ * <code>MMS_ERROR_INACTIVE_SUBSCRIPTION</code><br>
+ * <code>MMS_ERROR_DATA_DISABLED</code><br>
* @throws IllegalArgumentException if contentUri is empty
*/
public void sendMultimediaMessage(Context context, Uri contentUri, String locationUrl,
@@ -2661,6 +2677,19 @@
* sending the message.
* @param sentIntent if not NULL this <code>PendingIntent</code> is
* broadcast when the message is successfully sent, or failed
+ * The result code will be <code>Activity.RESULT_OK</code> for success
+ * or one of these errors:<br>
+ * <code>MMS_ERROR_UNSPECIFIED</code><br>
+ * <code>MMS_ERROR_INVALID_APN</code><br>
+ * <code>MMS_ERROR_UNABLE_CONNECT_MMS</code><br>
+ * <code>MMS_ERROR_HTTP_FAILURE</code><br>
+ * <code>MMS_ERROR_IO_ERROR</code><br>
+ * <code>MMS_ERROR_RETRY</code><br>
+ * <code>MMS_ERROR_CONFIGURATION_ERROR</code><br>
+ * <code>MMS_ERROR_NO_DATA_NETWORK</code><br>
+ * <code>MMS_ERROR_INVALID_SUBSCRIPTION_ID</code><br>
+ * <code>MMS_ERROR_INACTIVE_SUBSCRIPTION</code><br>
+ * <code>MMS_ERROR_DATA_DISABLED</code><br>
* @param messageId an id that uniquely identifies the message requested to be sent.
* Used for logging and diagnostics purposes. The id may be 0.
* @throws IllegalArgumentException if contentUri is empty
@@ -2707,6 +2736,19 @@
* downloading the message.
* @param downloadedIntent if not NULL this <code>PendingIntent</code> is
* broadcast when the message is downloaded, or the download is failed
+ * The result code will be <code>Activity.RESULT_OK</code> for success
+ * or one of these errors:<br>
+ * <code>MMS_ERROR_UNSPECIFIED</code><br>
+ * <code>MMS_ERROR_INVALID_APN</code><br>
+ * <code>MMS_ERROR_UNABLE_CONNECT_MMS</code><br>
+ * <code>MMS_ERROR_HTTP_FAILURE</code><br>
+ * <code>MMS_ERROR_IO_ERROR</code><br>
+ * <code>MMS_ERROR_RETRY</code><br>
+ * <code>MMS_ERROR_CONFIGURATION_ERROR</code><br>
+ * <code>MMS_ERROR_NO_DATA_NETWORK</code><br>
+ * <code>MMS_ERROR_INVALID_SUBSCRIPTION_ID</code><br>
+ * <code>MMS_ERROR_INACTIVE_SUBSCRIPTION</code><br>
+ * <code>MMS_ERROR_DATA_DISABLED</code><br>
* @throws IllegalArgumentException if locationUrl or contentUri is empty
*/
public void downloadMultimediaMessage(Context context, String locationUrl, Uri contentUri,
@@ -2737,6 +2779,19 @@
* downloading the message.
* @param downloadedIntent if not NULL this <code>PendingIntent</code> is
* broadcast when the message is downloaded, or the download is failed
+ * The result code will be <code>Activity.RESULT_OK</code> for success
+ * or one of these errors:<br>
+ * <code>MMS_ERROR_UNSPECIFIED</code><br>
+ * <code>MMS_ERROR_INVALID_APN</code><br>
+ * <code>MMS_ERROR_UNABLE_CONNECT_MMS</code><br>
+ * <code>MMS_ERROR_HTTP_FAILURE</code><br>
+ * <code>MMS_ERROR_IO_ERROR</code><br>
+ * <code>MMS_ERROR_RETRY</code><br>
+ * <code>MMS_ERROR_CONFIGURATION_ERROR</code><br>
+ * <code>MMS_ERROR_NO_DATA_NETWORK</code><br>
+ * <code>MMS_ERROR_INVALID_SUBSCRIPTION_ID</code><br>
+ * <code>MMS_ERROR_INACTIVE_SUBSCRIPTION</code><br>
+ * <code>MMS_ERROR_DATA_DISABLED</code><br>
* @param messageId an id that uniquely identifies the message requested to be downloaded.
* Used for logging and diagnostics purposes. The id may be 0.
* @throws IllegalArgumentException if locationUrl or contentUri is empty
@@ -2768,15 +2823,62 @@
}
// MMS send/download failure result codes
+
+ /**
+ * Unspecific MMS error occurred during send/download.
+ */
public static final int MMS_ERROR_UNSPECIFIED = 1;
+
+ /**
+ * ApnException occurred during MMS network setup.
+ */
public static final int MMS_ERROR_INVALID_APN = 2;
+
+ /**
+ * An error occurred during the MMS connection setup.
+ */
public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3;
+
+ /**
+ * An error occurred during the HTTP client setup.
+ */
public static final int MMS_ERROR_HTTP_FAILURE = 4;
+
+ /**
+ * An I/O error occurred reading the PDU.
+ */
public static final int MMS_ERROR_IO_ERROR = 5;
+
+ /**
+ * An error occurred while retrying sending/downloading the MMS.
+ */
public static final int MMS_ERROR_RETRY = 6;
+
+ /**
+ * The carrier-dependent configuration values could not be loaded.
+ */
public static final int MMS_ERROR_CONFIGURATION_ERROR = 7;
+
+ /**
+ * There is no data network.
+ */
public static final int MMS_ERROR_NO_DATA_NETWORK = 8;
+ /**
+ * The subscription id for the send/download is invalid.
+ */
+ public static final int MMS_ERROR_INVALID_SUBSCRIPTION_ID = 9;
+
+ /**
+ * The subscription id for the send/download is inactive.
+ */
+ public static final int MMS_ERROR_INACTIVE_SUBSCRIPTION = 10;
+
+ /**
+ * Data is disabled for the MMS APN.
+ */
+ public static final int MMS_ERROR_DATA_DISABLED = 11;
+
/** Intent extra name for MMS sending result data in byte array type */
public static final String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA";
/** Intent extra name for HTTP status code for MMS HTTP failure in integer type */
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 974392e..d2858ec 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -26,6 +26,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -92,6 +93,7 @@
* and provides information about the current Telephony Subscriptions.
*/
@SystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public class SubscriptionManager {
private static final String LOG_TAG = "SubscriptionManager";
private static final boolean DBG = false;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 87c337d..bbd3c46 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -49,6 +49,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.Uri;
@@ -174,6 +175,7 @@
* that do not implement this feature, the behavior is not reliable.
*/
@SystemService(Context.TELEPHONY_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_TELEPHONY)
public class TelephonyManager {
private static final String TAG = "TelephonyManager";
@@ -2055,6 +2057,7 @@
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_GSM)
public String getImei() {
return getImei(getSlotIndex());
}
@@ -2096,6 +2099,7 @@
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_GSM)
public String getImei(int slotIndex) {
ITelephony telephony = getITelephony();
if (telephony == null) return null;
@@ -2113,6 +2117,7 @@
* Returns the Type Allocation Code from the IMEI. Return null if Type Allocation Code is not
* available.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_GSM)
@Nullable
public String getTypeAllocationCode() {
return getTypeAllocationCode(getSlotIndex());
@@ -2124,6 +2129,7 @@
*
* @param slotIndex of which Type Allocation Code is returned
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_GSM)
@Nullable
public String getTypeAllocationCode(int slotIndex) {
ITelephony telephony = getITelephony();
@@ -2170,6 +2176,7 @@
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
public String getMeid() {
return getMeid(getSlotIndex());
}
@@ -2208,6 +2215,7 @@
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
public String getMeid(int slotIndex) {
ITelephony telephony = getITelephony();
if (telephony == null) return null;
@@ -2231,6 +2239,7 @@
* Returns the Manufacturer Code from the MEID. Return null if Manufacturer Code is not
* available.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
@Nullable
public String getManufacturerCode() {
return getManufacturerCode(getSlotIndex());
@@ -2242,6 +2251,7 @@
*
* @param slotIndex of which Type Allocation Code is returned
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
@Nullable
public String getManufacturerCode(int slotIndex) {
ITelephony telephony = getITelephony();
@@ -2287,6 +2297,7 @@
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String getNai() {
return getNaiBySubscriberId(getSubId());
}
@@ -2620,6 +2631,7 @@
* unreliable on CDMA networks (use {@link #getPhoneType()} to determine if
* on a CDMA network).
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public String getNetworkOperatorName() {
return getNetworkOperatorName(getSubId());
}
@@ -2647,6 +2659,7 @@
* unreliable on CDMA networks (use {@link #getPhoneType()} to determine if
* on a CDMA network).
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public String getNetworkOperator() {
return getNetworkOperatorForPhone(getPhoneId());
}
@@ -2695,6 +2708,7 @@
* @see #createForSubscriptionId(int)
* @see #createForPhoneAccountHandle(PhoneAccountHandle)
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public String getNetworkSpecifier() {
return String.valueOf(getSubId());
}
@@ -2717,6 +2731,7 @@
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@WorkerThread
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public PersistableBundle getCarrierConfig() {
CarrierConfigManager carrierConfigManager = mContext
.getSystemService(CarrierConfigManager.class);
@@ -2729,6 +2744,7 @@
* <p>
* Availability: Only when user registered to a network.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean isNetworkRoaming() {
return isNetworkRoaming(getSubId());
}
@@ -2758,6 +2774,7 @@
* @return the lowercase 2 character ISO-3166-1 alpha-2 country code, or empty string if not
* available.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public String getNetworkCountryIso() {
return getNetworkCountryIso(getSlotIndex());
}
@@ -2780,6 +2797,7 @@
* @throws IllegalArgumentException when the slotIndex is invalid.
*
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
@NonNull
public String getNetworkCountryIso(int slotIndex) {
try {
@@ -2997,6 +3015,7 @@
@RequiresPermission(anyOf = {
android.Manifest.permission.READ_PHONE_STATE,
android.Manifest.permission.READ_BASIC_PHONE_STATE})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public @NetworkType int getDataNetworkType() {
return getDataNetworkType(getSubId(SubscriptionManager.getActiveDataSubscriptionId()));
}
@@ -3042,6 +3061,7 @@
@RequiresPermission(anyOf = {
android.Manifest.permission.READ_PHONE_STATE,
android.Manifest.permission.READ_BASIC_PHONE_STATE})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public @NetworkType int getVoiceNetworkType() {
return getVoiceNetworkType(getSubId());
}
@@ -3381,6 +3401,7 @@
/**
* @return true if a ICC card is present
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public boolean hasIccCard() {
return hasIccCard(getSlotIndex());
}
@@ -3423,6 +3444,7 @@
* @see #SIM_STATE_CARD_IO_ERROR
* @see #SIM_STATE_CARD_RESTRICTED
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @SimState int getSimState() {
int simState = getSimStateIncludingLoaded();
if (simState == SIM_STATE_LOADED) {
@@ -3465,6 +3487,7 @@
* @hide
*/
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @SimState int getSimCardState() {
int simState = getSimState();
return getSimCardStateFromSimState(simState);
@@ -3510,6 +3533,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @SimState int getSimCardState(int physicalSlotIndex, int portIndex) {
int simState = getSimState(getLogicalSlotIndex(physicalSlotIndex, portIndex));
return getSimCardStateFromSimState(simState);
@@ -3566,6 +3590,7 @@
* @hide
*/
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @SimState int getSimApplicationState() {
int simState = getSimStateIncludingLoaded();
return getSimApplicationStateFromSimState(simState);
@@ -3618,6 +3643,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @SimState int getSimApplicationState(int physicalSlotIndex, int portIndex) {
int simState =
SubscriptionManager.getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex,
@@ -3659,6 +3685,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public boolean isApplicationOnUicc(@UiccAppType int appType) {
try {
ITelephony service = getITelephony();
@@ -3687,6 +3714,7 @@
* @see #SIM_STATE_CARD_IO_ERROR
* @see #SIM_STATE_CARD_RESTRICTED
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @SimState int getSimState(int slotIndex) {
int simState = SubscriptionManager.getSimStateForSlotIndex(slotIndex);
if (simState == SIM_STATE_LOADED) {
@@ -3703,6 +3731,7 @@
*
* @see #getSimState
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String getSimOperator() {
return getSimOperatorNumeric();
}
@@ -3787,6 +3816,7 @@
*
* @see #getSimState
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String getSimOperatorName() {
return getSimOperatorNameForPhone(getPhoneId());
}
@@ -3824,6 +3854,7 @@
* @return the lowercase 2 character ISO-3166-1 alpha-2 country code, or empty string is not
* available.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String getSimCountryIso() {
return getSimCountryIsoForPhone(getPhoneId());
}
@@ -3882,6 +3913,7 @@
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String getSimSerialNumber() {
return getSimSerialNumber(getSubId());
}
@@ -3949,6 +3981,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean isLteCdmaEvdoGsmWcdmaEnabled() {
return getLteOnCdmaMode(getSubId()) == PhoneConstants.LTE_ON_CDMA_TRUE;
}
@@ -3992,6 +4025,7 @@
*
* @return card ID of the default eUICC card, if loaded.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_EUICC)
public int getCardIdForDefaultEuicc() {
try {
ITelephony telephony = getITelephony();
@@ -4025,6 +4059,7 @@
* the caller does not have adequate permissions for that card.
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@NonNull
public List<UiccCardInfo> getUiccCardsInfo() {
try {
@@ -4050,6 +4085,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public UiccSlotInfo[] getUiccSlotsInfo() {
try {
ITelephony telephony = getITelephony();
@@ -4192,6 +4228,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public void setSimSlotMapping(@NonNull Collection<UiccSlotMapping> slotMapping) {
try {
ITelephony telephony = getITelephony();
@@ -4255,6 +4292,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@NonNull
public Collection<UiccSlotMapping> getSimSlotMapping() {
List<UiccSlotMapping> slotMap = new ArrayList<>();
@@ -4310,6 +4348,7 @@
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String getSubscriberId() {
return getSubscriberId(getSubId());
}
@@ -4361,6 +4400,7 @@
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@SystemApi
@Nullable
public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(@KeyType int keyType) {
@@ -4405,6 +4445,7 @@
* @hide
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@SystemApi
public void resetCarrierKeysForImsiEncryption() {
try {
@@ -4604,6 +4645,7 @@
* @param callback A callback called when the upload operation terminates, either in success
* or in error.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void uploadCallComposerPicture(@NonNull Path pictureToUpload,
@NonNull String contentType,
@CallbackExecutor @NonNull Executor executor,
@@ -4710,6 +4752,7 @@
* @param callback A callback called when the upload operation terminates, either in success
* or in error.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void uploadCallComposerPicture(@NonNull InputStream pictureToUpload,
@NonNull String contentType,
@CallbackExecutor @NonNull Executor executor,
@@ -4845,6 +4888,7 @@
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String getGroupIdLevel1() {
try {
IPhoneSubInfo info = getSubscriberInfoService();
@@ -5100,6 +5144,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @NonNull String[] getMergedImsisFromGroup() {
try {
ITelephony telephony = getITelephony();
@@ -5179,6 +5224,7 @@
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public String getVoiceMailNumber() {
return getVoiceMailNumber(getSubId());
}
@@ -5214,6 +5260,7 @@
* @param alphaTag The alpha tag to display.
* @param number The voicemail number.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public boolean setVoiceMailNumber(String alphaTag, String number) {
return setVoiceMailNumber(getSubId(), alphaTag, number);
}
@@ -5253,6 +5300,7 @@
* be implemented instead.
*/
@SystemApi
+ @Deprecated
@SuppressLint("RequiresPermission")
public void setVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle, boolean enabled){
}
@@ -5267,6 +5315,7 @@
* be implemented instead.
*/
@SystemApi
+ @Deprecated
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
@SuppressLint("RequiresPermission")
public boolean isVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle){
@@ -5288,6 +5337,7 @@
*/
@SystemApi
@SuppressLint("RequiresPermission")
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
@Nullable
public Bundle getVisualVoicemailSettings(){
try {
@@ -5317,6 +5367,7 @@
@Nullable
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public String getVisualVoicemailPackageName() {
try {
ITelephony telephony = getITelephony();
@@ -5343,6 +5394,7 @@
* @see TelecomManager#getDefaultDialerPackage()
* @see CarrierConfigManager#KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void setVisualVoicemailSmsFilterSettings(VisualVoicemailSmsFilterSettings settings) {
if (settings == null) {
disableVisualVoicemailSmsFilter(mSubId);
@@ -5372,6 +5424,7 @@
* @see SmsManager#sendDataMessage(String, String, short, byte[], PendingIntent, PendingIntent)
* @see SmsManager#sendTextMessage(String, String, String, PendingIntent, PendingIntent)
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void sendVisualVoicemailSms(String number, int port, String text,
PendingIntent sentIntent) {
sendVisualVoicemailSmsForSubscriber(mSubId, number, port, text, sentIntent);
@@ -5559,6 +5612,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void setVoiceActivationState(@SimActivationState int activationState) {
setVoiceActivationState(getSubId(), activationState);
}
@@ -5606,6 +5660,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public void setDataActivationState(@SimActivationState int activationState) {
setDataActivationState(getSubId(), activationState);
}
@@ -5653,6 +5708,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public @SimActivationState int getVoiceActivationState() {
return getVoiceActivationState(getSubId());
}
@@ -5702,6 +5758,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public @SimActivationState int getDataActivationState() {
return getDataActivationState(getSubId());
}
@@ -5778,6 +5835,7 @@
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public String getVoiceMailAlphaTag() {
return getVoiceMailAlphaTag(getSubId());
}
@@ -5860,6 +5918,7 @@
@Nullable
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String getIsimDomain() {
try {
IPhoneSubInfo info = getSubscriberInfoService();
@@ -5960,6 +6019,7 @@
* @return The call state of the subscription associated with this TelephonyManager instance.
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public @CallState int getCallStateForSubscription() {
return getCallState(getSubId());
}
@@ -6058,6 +6118,7 @@
* @see #DATA_ACTIVITY_INOUT
* @see #DATA_ACTIVITY_DORMANT
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public int getDataActivity() {
try {
ITelephony telephony = getITelephony();
@@ -6130,6 +6191,7 @@
* @see #DATA_DISCONNECTING
* @see #DATA_HANDOVER_IN_PROGRESS
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public int getDataState() {
try {
ITelephony telephony = getITelephony();
@@ -6406,6 +6468,7 @@
* on any device with a telephony radio, even if the device is
* data-only.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public boolean isVoiceCapable() {
if (mContext == null) return true;
return mContext.getResources().getBoolean(
@@ -6421,6 +6484,7 @@
* Note: Voicemail waiting sms, cell broadcasting sms, and MMS are
* disabled when device doesn't support sms.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)
public boolean isSmsCapable() {
if (mContext == null) return true;
return mContext.getResources().getBoolean(
@@ -6470,6 +6534,7 @@
* information is unavailable.
*/
@RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public List<CellInfo> getAllCellInfo() {
try {
ITelephony telephony = getITelephony();
@@ -6564,6 +6629,7 @@
* @param callback a callback to receive CellInfo.
*/
@RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public void requestCellInfoUpdate(
@NonNull @CallbackExecutor Executor executor, @NonNull CellInfoCallback callback) {
try {
@@ -6627,6 +6693,7 @@
@SystemApi
@RequiresPermission(allOf = {android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.MODIFY_PHONE_STATE})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public void requestCellInfoUpdate(@NonNull WorkSource workSource,
@NonNull @CallbackExecutor Executor executor, @NonNull CellInfoCallback callback) {
try {
@@ -6708,6 +6775,7 @@
/**
* Returns the MMS user agent.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)
public String getMmsUserAgent() {
try {
ITelephony telephony = getITelephony();
@@ -6723,6 +6791,7 @@
/**
* Returns the MMS user agent profile URL.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)
public String getMmsUAProfUrl() {
try {
ITelephony telephony = getITelephony();
@@ -6784,6 +6853,7 @@
* @deprecated instead use {@link #iccOpenLogicalChannelByPort(int, int, String, int)}
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@SystemApi
@Nullable
@Deprecated
@@ -6883,6 +6953,7 @@
* @param p2 P2 parameter (described in ISO 7816-4).
* @return an IccOpenLogicalChannelResponse object.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID, int p2) {
return iccOpenLogicalChannel(getSubId(), AID, p2);
}
@@ -6951,6 +7022,7 @@
* @deprecated instead use {@link #iccCloseLogicalChannelByPort(int, int, int)}
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@SystemApi
@Deprecated
public boolean iccCloseLogicalChannelBySlot(int slotIndex, int channel) {
@@ -7020,6 +7092,7 @@
* iccOpenLogicalChannel.
* @return true if the channel was closed successfully.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public boolean iccCloseLogicalChannel(int channel) {
return iccCloseLogicalChannel(getSubId(), channel);
}
@@ -7082,6 +7155,7 @@
* {@link #iccTransmitApduLogicalChannelByPort(int, int, int, int, int, int, int, int, String)}
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@SystemApi
@Nullable
@Deprecated
@@ -7164,6 +7238,7 @@
* @return The APDU response from the ICC card with the status appended at
* the end.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String iccTransmitApduLogicalChannel(int channel, int cla,
int instruction, int p1, int p2, int p3, String data) {
return iccTransmitApduLogicalChannel(getSubId(), channel, cla,
@@ -7232,6 +7307,7 @@
* {@link #iccTransmitApduBasicChannelByPort(int, int, int, int, int, int, int, String)}
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@SystemApi
@NonNull
@Deprecated
@@ -7309,6 +7385,7 @@
* @return The APDU response from the ICC card with the status appended at
* the end.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String iccTransmitApduBasicChannel(int cla,
int instruction, int p1, int p2, int p3, String data) {
return iccTransmitApduBasicChannel(getSubId(), cla,
@@ -7364,6 +7441,7 @@
* @param filePath
* @return The APDU response.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
String filePath) {
return iccExchangeSimIO(getSubId(), fileID, command, p1, p2, p3, filePath);
@@ -7412,6 +7490,7 @@
* with the last 4 bytes being the status word. If the command fails,
* returns an empty string.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String sendEnvelopeWithStatus(String content) {
return sendEnvelopeWithStatus(getSubId(), content);
}
@@ -7575,6 +7654,7 @@
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean resetRadioConfig() {
try {
ITelephony telephony = getITelephony();
@@ -7602,6 +7682,7 @@
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean rebootRadio() {
try {
ITelephony telephony = getITelephony();
@@ -7623,6 +7704,7 @@
* subscription ID is returned. Otherwise, the default subscription ID will be returned.
*
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public int getSubscriptionId() {
return getSubId();
}
@@ -7733,6 +7815,7 @@
*/
@SystemApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void requestNumberVerification(@NonNull PhoneNumberRange range, long timeoutMillis,
@NonNull @CallbackExecutor Executor executor,
@NonNull NumberVerificationCallback callback) {
@@ -7946,6 +8029,7 @@
@Nullable
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String getIsimIst() {
try {
IPhoneSubInfo info = getSubscriberInfoService();
@@ -8030,6 +8114,7 @@
// TODO(b/73660190): This should probably require MODIFY_PHONE_STATE, not
// READ_PRIVILEGED_PHONE_STATE. It certainly shouldn't reference the permission in Javadoc since
// it's not public API.
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String getIccAuthentication(int appType, int authType, String data) {
return getIccAuthentication(getSubId(), appType, authType, data);
}
@@ -8083,6 +8168,7 @@
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String[] getForbiddenPlmns() {
return getForbiddenPlmns(getSubId(), APPTYPE_USIM);
}
@@ -8132,6 +8218,7 @@
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public int setForbiddenPlmns(@NonNull List<String> fplmns) {
try {
ITelephony telephony = getITelephony();
@@ -8158,6 +8245,7 @@
@SystemApi
@WorkerThread
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_IMS)
public void resetIms(int slotIndex) {
try {
ITelephony telephony = getITelephony();
@@ -8592,6 +8680,7 @@
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public @NetworkTypeBitMask long getAllowedNetworkTypesBitmask() {
try {
ITelephony telephony = getITelephony();
@@ -8643,6 +8732,7 @@
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public void setNetworkSelectionModeAutomatic() {
try {
ITelephony telephony = getITelephony();
@@ -8731,6 +8821,7 @@
android.Manifest.permission.MODIFY_PHONE_STATE,
Manifest.permission.ACCESS_FINE_LOCATION
})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public NetworkScan requestNetworkScan(
NetworkScanRequest request, Executor executor,
TelephonyScanManager.NetworkScanCallback callback) {
@@ -8823,6 +8914,7 @@
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean setNetworkSelectionModeManual(String operatorNumeric, boolean persistSelection) {
return setNetworkSelectionModeManual(
new OperatorInfo(
@@ -8852,6 +8944,7 @@
* @return {@code true} on success; {@code false} on any failure.
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean setNetworkSelectionModeManual(@NonNull String operatorNumeric,
boolean persistSelection, @AccessNetworkConstants.RadioAccessNetworkType int ran) {
return setNetworkSelectionModeManual(new OperatorInfo("" /* operatorAlphaLong */,
@@ -8907,6 +9000,7 @@
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
android.Manifest.permission.READ_PRECISE_PHONE_STATE
})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public @NetworkSelectionMode int getNetworkSelectionMode() {
int mode = NETWORK_SELECTION_MODE_UNKNOWN;
try {
@@ -8932,6 +9026,7 @@
*/
@SuppressAutoDoc // No support carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public @NonNull String getManualNetworkSelectionPlmn() {
try {
ITelephony telephony = getITelephony();
@@ -8961,6 +9056,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)
public boolean isInEmergencySmsMode() {
try {
ITelephony telephony = getITelephony();
@@ -9271,6 +9367,7 @@
*
* @return true on success; false on any failure.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean setPreferredNetworkTypeToGlobal() {
return setPreferredNetworkTypeToGlobal(getSubId());
}
@@ -9298,6 +9395,7 @@
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean isTetheringApnRequired() {
return isTetheringApnRequired(getSubId(SubscriptionManager.getActiveDataSubscriptionId()));
}
@@ -9347,6 +9445,7 @@
*
* @return true if the app has carrier privileges.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public boolean hasCarrierPrivileges() {
return hasCarrierPrivileges(getSubId());
}
@@ -9393,6 +9492,7 @@
* @param brand The brand name to display/set.
* @return true if the operation was executed correctly.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public boolean setOperatorBrandOverride(String brand) {
return setOperatorBrandOverride(getSubId(), brand);
}
@@ -9495,6 +9595,7 @@
/** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
public String getCdmaMdn() {
return getCdmaMdn(getSubId());
}
@@ -9502,6 +9603,7 @@
/** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
public String getCdmaMdn(int subId) {
try {
ITelephony telephony = getITelephony();
@@ -9518,6 +9620,7 @@
/** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
public String getCdmaMin() {
return getCdmaMin(getSubId());
}
@@ -9525,6 +9628,7 @@
/** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
public String getCdmaMin(int subId) {
try {
ITelephony telephony = getITelephony();
@@ -9541,6 +9645,7 @@
/** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public int checkCarrierPrivilegesForPackage(String pkgName) {
try {
ITelephony telephony = getITelephony();
@@ -9557,6 +9662,7 @@
/** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) {
try {
ITelephony telephony = getITelephony();
@@ -9572,6 +9678,7 @@
/** @hide */
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public List<String> getCarrierPackageNamesForIntent(Intent intent) {
return getCarrierPackageNamesForIntentAndPhone(intent, getPhoneId());
}
@@ -9579,6 +9686,7 @@
/** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public List<String> getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId) {
try {
ITelephony telephony = getITelephony();
@@ -9660,6 +9768,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@NonNull
public List<String> getCarrierPrivilegedPackagesForAllActiveSubscriptions() {
try {
@@ -9706,6 +9815,7 @@
* @throws SecurityException if the caller does not have the permission.
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void setCallComposerStatus(@CallComposerStatus int status) {
if (status > CALL_COMPOSER_STATUS_ON
|| status < CALL_COMPOSER_STATUS_OFF) {
@@ -9734,6 +9844,7 @@
* {@link #CALL_COMPOSER_STATUS_ON} or {@link #CALL_COMPOSER_STATUS_OFF}.
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public @CallComposerStatus int getCallComposerStatus() {
try {
ITelephony telephony = getITelephony();
@@ -9750,6 +9861,7 @@
/** @hide */
@SystemApi
@SuppressLint("RequiresPermission")
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void dial(String number) {
try {
ITelephony telephony = getITelephony();
@@ -9882,6 +9994,7 @@
/** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public boolean supplyPin(String pin) {
try {
ITelephony telephony = getITelephony();
@@ -9896,6 +10009,7 @@
/** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public boolean supplyPuk(String puk, String pin) {
try {
ITelephony telephony = getITelephony();
@@ -9961,6 +10075,7 @@
@SystemApi
@NonNull
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public PinResult supplyIccLockPin(@NonNull String pin) {
try {
ITelephony telephony = getITelephony();
@@ -9996,6 +10111,7 @@
@SystemApi
@NonNull
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public PinResult supplyIccLockPuk(@NonNull String puk, @NonNull String pin) {
try {
ITelephony telephony = getITelephony();
@@ -10065,6 +10181,7 @@
* @param handler the {@link Handler} to run the request on.
*/
@RequiresPermission(android.Manifest.permission.CALL_PHONE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public void sendUssdRequest(String ussdRequest,
final UssdResponseCallback callback, Handler handler) {
checkNotNull(callback, "UssdResponseCallback cannot be null.");
@@ -10107,6 +10224,7 @@
*
* @return {@code true} if simultaneous voice and data supported, and {@code false} otherwise.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean isConcurrentVoiceAndDataSupported() {
try {
ITelephony telephony = getITelephony();
@@ -10149,6 +10267,7 @@
/** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public void toggleRadioOnOff() {
try {
ITelephony telephony = getITelephony();
@@ -10162,6 +10281,7 @@
/** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean setRadio(boolean turnOn) {
try {
ITelephony telephony = getITelephony();
@@ -10176,6 +10296,7 @@
/** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean setRadioPower(boolean turnOn) {
try {
ITelephony telephony = getITelephony();
@@ -10197,6 +10318,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public void shutdownAllRadios() {
try {
ITelephony telephony = getITelephony();
@@ -10217,6 +10339,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean isAnyRadioPoweredOn() {
try {
ITelephony telephony = getITelephony();
@@ -10263,6 +10386,7 @@
@SystemApi
@RequiresPermission(anyOf = {android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
android.Manifest.permission.READ_PHONE_STATE})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public @RadioPowerState int getRadioPowerState() {
try {
ITelephony telephony = getITelephony();
@@ -10289,6 +10413,7 @@
/** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean enableDataConnectivity() {
try {
ITelephony telephony = getITelephony();
@@ -10303,6 +10428,7 @@
/** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean disableDataConnectivity() {
try {
ITelephony telephony = getITelephony();
@@ -10316,6 +10442,7 @@
/** @hide */
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean isDataConnectivityPossible() {
try {
ITelephony telephony = getITelephony();
@@ -10330,6 +10457,7 @@
/** @hide */
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean needsOtaServiceProvisioning() {
try {
ITelephony telephony = getITelephony();
@@ -10437,6 +10565,7 @@
android.Manifest.permission.MODIFY_PHONE_STATE,
android.Manifest.permission.READ_PHONE_STATE,
android.Manifest.permission.READ_BASIC_PHONE_STATE})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean isDataEnabled() {
try {
return isDataEnabledForReason(DATA_ENABLED_REASON_USER);
@@ -10466,6 +10595,7 @@
@RequiresPermission(anyOf = {android.Manifest.permission.ACCESS_NETWORK_STATE,
android.Manifest.permission.READ_PHONE_STATE,
android.Manifest.permission.READ_BASIC_PHONE_STATE})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean isDataRoamingEnabled() {
boolean isDataRoamingEnabled = false;
try {
@@ -10503,6 +10633,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
public @CdmaRoamingMode int getCdmaRoamingMode() {
int mode = CDMA_ROAMING_MODE_RADIO_DEFAULT;
try {
@@ -10544,6 +10675,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
public void setCdmaRoamingMode(@CdmaRoamingMode int mode) {
if (getPhoneType() != PHONE_TYPE_CDMA) {
throw new IllegalStateException("Phone does not support CDMA.");
@@ -10611,6 +10743,7 @@
*/
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
public @CdmaSubscription int getCdmaSubscriptionMode() {
int mode = CDMA_SUBSCRIPTION_RUIM_SIM;
try {
@@ -10648,6 +10781,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
public void setCdmaSubscriptionMode(@CdmaSubscription int mode) {
if (getPhoneType() != PHONE_TYPE_CDMA) {
throw new IllegalStateException("Phone does not support CDMA.");
@@ -10682,6 +10816,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public void setDataRoamingEnabled(boolean isEnabled) {
try {
ITelephony telephony = getITelephony();
@@ -10779,6 +10914,7 @@
*
* @return {@code true} if the DTMF tone length can be changed, and {@code false} otherwise.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public boolean canChangeDtmfToneLength() {
try {
ITelephony telephony = getITelephony();
@@ -10842,6 +10978,7 @@
*
* @return {@code true} if the device and carrier both support RTT, {@code false} otherwise.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_IMS)
public boolean isRttSupported() {
try {
ITelephony telephony = getITelephony();
@@ -10861,6 +10998,7 @@
* @return {@code true} if the device supports hearing aid compatibility, and {@code false}
* otherwise.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public boolean isHearingAidCompatibilitySupported() {
try {
ITelephony telephony = getITelephony();
@@ -11208,6 +11346,7 @@
**/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public void setSimPowerState(@SimPowerState int state, @NonNull Executor executor,
@NonNull @SetSimPowerStateResult Consumer<Integer> callback) {
setSimPowerStateForSlot(getSlotIndex(), state, executor, callback);
@@ -11237,6 +11376,7 @@
**/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public void setSimPowerStateForSlot(int slotIndex, @SimPowerState int state,
@NonNull Executor executor,
@NonNull @SetSimPowerStateResult Consumer<Integer> callback) {
@@ -11451,6 +11591,7 @@
*/
@SystemApi
@RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)
public @Nullable ComponentName getAndUpdateDefaultRespondViaMessageApplication() {
return SmsApplication.getDefaultRespondViaMessageApplication(mContext, true);
}
@@ -11463,6 +11604,7 @@
*/
@SystemApi
@RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)
public @Nullable ComponentName getDefaultRespondViaMessageApplication() {
return SmsApplication.getDefaultRespondViaMessageApplication(mContext, false);
}
@@ -11658,6 +11800,7 @@
* permission.
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public int getSubscriptionId(@NonNull PhoneAccountHandle phoneAccountHandle) {
int retval = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
try {
@@ -11724,6 +11867,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@Nullable public Locale getSimLocale() {
try {
final ITelephony telephony = getITelephony();
@@ -11922,6 +12066,7 @@
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.ACCESS_COARSE_LOCATION
})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public @Nullable ServiceState getServiceState() {
return getServiceState(false, false);
}
@@ -12012,6 +12157,7 @@
* @return The URI for the ringtone to play when receiving a voicemail from a specific
* PhoneAccount. May be {@code null} if no ringtone is set.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public @Nullable Uri getVoicemailRingtoneUri(PhoneAccountHandle accountHandle) {
try {
ITelephony service = getITelephony();
@@ -12039,6 +12185,7 @@
* @deprecated Use {@link android.provider.Settings#ACTION_CHANNEL_NOTIFICATION_SETTINGS}
* instead.
*/
+ @Deprecated
public void setVoicemailRingtoneUri(PhoneAccountHandle phoneAccountHandle, Uri uri) {
try {
ITelephony service = getITelephony();
@@ -12057,6 +12204,7 @@
* voicemail vibration setting.
* @return {@code true} if the vibration is set for this PhoneAccount, {@code false} otherwise.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public boolean isVoicemailVibrationEnabled(PhoneAccountHandle accountHandle) {
try {
ITelephony service = getITelephony();
@@ -12084,6 +12232,7 @@
* @deprecated Use {@link android.provider.Settings#ACTION_CHANNEL_NOTIFICATION_SETTINGS}
* instead.
*/
+ @Deprecated
public void setVoicemailVibrationEnabled(PhoneAccountHandle phoneAccountHandle,
boolean enabled) {
try {
@@ -12110,6 +12259,7 @@
* @return Carrier id of the current subscription. Return {@link #UNKNOWN_CARRIER_ID} if the
* subscription is unavailable or the carrier cannot be identified.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public int getSimCarrierId() {
try {
ITelephony service = getITelephony();
@@ -12134,6 +12284,7 @@
* @return Carrier name of the current subscription. Return {@code null} if the subscription is
* unavailable or the carrier cannot be identified.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @Nullable CharSequence getSimCarrierIdName() {
try {
ITelephony service = getITelephony();
@@ -12171,6 +12322,7 @@
* Return {@link #UNKNOWN_CARRIER_ID} if the subscription is unavailable or the carrier cannot
* be identified.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public int getSimSpecificCarrierId() {
try {
ITelephony service = getITelephony();
@@ -12196,6 +12348,7 @@
* @return user-facing name of the subscription specific carrier id. Return {@code null} if the
* subscription is unavailable or the carrier cannot be identified.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @Nullable CharSequence getSimSpecificCarrierIdName() {
try {
ITelephony service = getITelephony();
@@ -12223,6 +12376,7 @@
* @return matching carrier id from sim MCCMNC. Return {@link #UNKNOWN_CARRIER_ID} if the
* subscription is unavailable or the carrier cannot be identified.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public int getCarrierIdFromSimMccMnc() {
try {
ITelephony service = getITelephony();
@@ -12301,6 +12455,7 @@
@Nullable
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String getAidForAppType(@UiccAppType int appType) {
return getAidForAppType(getSubId(), appType);
}
@@ -12363,6 +12518,7 @@
* @hide
*/
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
public String getCdmaPrlVersion() {
return getCdmaPrlVersion(getSubId());
}
@@ -12428,6 +12584,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CARRIERLOCK)
public int setAllowedCarriers(int slotIndex, List<CarrierIdentifier> carriers) {
if (carriers == null || !SubscriptionManager.isValidPhoneId(slotIndex)) {
return -1;
@@ -12554,6 +12711,7 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@SetCarrierRestrictionResult
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CARRIERLOCK)
public int setCarrierRestrictionRules(@NonNull CarrierRestrictionRules rules) {
try {
ITelephony service = getITelephony();
@@ -12611,6 +12769,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CARRIERLOCK)
@Nullable
public CarrierRestrictionRules getCarrierRestrictionRules() {
try {
@@ -12670,6 +12829,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public void setRadioEnabled(boolean enabled) {
try {
ITelephony service = getITelephony();
@@ -12791,6 +12951,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public void reportDefaultNetworkStatus(boolean report) {
try {
ITelephony service = getITelephony();
@@ -12816,6 +12977,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public void resetAllCarrierActions() {
try {
ITelephony service = getITelephony();
@@ -12935,6 +13097,7 @@
* @throws IllegalStateException if the Telephony process is not currently available.
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public void setDataEnabledForReason(@DataEnabledReason int reason, boolean enabled) {
setDataEnabledForReason(getSubId(), reason, enabled);
}
@@ -12981,6 +13144,7 @@
android.Manifest.permission.MODIFY_PHONE_STATE,
android.Manifest.permission.READ_BASIC_PHONE_STATE
})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean isDataEnabledForReason(@DataEnabledReason int reason) {
return isDataEnabledForReason(getSubId(), reason);
}
@@ -13034,6 +13198,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public boolean getEmergencyCallbackMode() {
return getEmergencyCallbackMode(getSubId());
}
@@ -13072,6 +13237,7 @@
@SuppressAutoDoc // No support carrier privileges (b/72967236).
@RequiresPermission(anyOf = {android.Manifest.permission.READ_PRECISE_PHONE_STATE,
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean isManualNetworkSelectionAllowed() {
try {
ITelephony telephony = getITelephony();
@@ -13092,6 +13258,7 @@
* @return the most recent cached signal strength info from the modem
*/
@Nullable
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public SignalStrength getSignalStrength() {
try {
ITelephony service = getITelephony();
@@ -13120,6 +13287,7 @@
android.Manifest.permission.READ_PHONE_STATE,
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
android.Manifest.permission.READ_BASIC_PHONE_STATE})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean isDataConnectionAllowed() {
boolean retVal = false;
try {
@@ -13140,6 +13308,7 @@
* data connections over the telephony network.
* <p>
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean isDataCapable() {
if (mContext == null) return true;
return mContext.getResources().getBoolean(
@@ -13287,6 +13456,7 @@
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean setOpportunisticNetworkState(boolean enable) {
String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
boolean ret = false;
@@ -13315,6 +13485,7 @@
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean isOpportunisticNetworkEnabled() {
String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
boolean isEnabled = false;
@@ -13506,6 +13677,7 @@
* @throws SecurityException if the caller does not have the required permission
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public @NetworkTypeBitMask long getSupportedRadioAccessFamily() {
try {
ITelephony telephony = getITelephony();
@@ -13541,6 +13713,7 @@
* @hide
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
@SystemApi
public void notifyOtaEmergencyNumberDbInstalled() {
try {
@@ -13567,6 +13740,7 @@
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
@SystemApi
public void updateOtaEmergencyNumberDbFilePath(
@NonNull ParcelFileDescriptor otaParcelFileDescriptor) {
@@ -13592,6 +13766,7 @@
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
@SystemApi
public void resetOtaEmergencyNumberDbFilePath() {
try {
@@ -13651,6 +13826,7 @@
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
@NonNull
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public Map<Integer, List<EmergencyNumber>> getEmergencyNumberList() {
Map<Integer, List<EmergencyNumber>> emergencyNumberList = new HashMap<>();
try {
@@ -13706,6 +13882,7 @@
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
@NonNull
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public Map<Integer, List<EmergencyNumber>> getEmergencyNumberList(
@EmergencyServiceCategories int categories) {
Map<Integer, List<EmergencyNumber>> emergencyNumberListForCategories = new HashMap<>();
@@ -13771,6 +13948,7 @@
* SIM card(s), Android database, modem, network or defaults; {@code false} otherwise.
* @throws IllegalStateException if the Telephony process is not currently available.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public boolean isEmergencyNumber(@NonNull String number) {
try {
ITelephony telephony = getITelephony();
@@ -13810,6 +13988,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public boolean isPotentialEmergencyNumber(@NonNull String number) {
try {
ITelephony telephony = getITelephony();
@@ -13835,6 +14014,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public int getEmergencyNumberDbVersion() {
try {
ITelephony telephony = getITelephony();
@@ -13975,6 +14155,7 @@
* See {@link TelephonyManager.SetOpportunisticSubscriptionResult}
* for more details. Pass null if don't care about the result.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public void setPreferredOpportunisticDataSubscription(int subId, boolean needValidation,
@Nullable @CallbackExecutor Executor executor, @Nullable Consumer<Integer> callback) {
String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
@@ -14038,6 +14219,7 @@
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
android.Manifest.permission.READ_PHONE_STATE
})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public int getPreferredOpportunisticDataSubscription() {
String packageName = mContext != null ? mContext.getOpPackageName() : "<unknown>";
String attributionTag = mContext != null ? mContext.getAttributionTag() : null;
@@ -14073,6 +14255,7 @@
*
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public void updateAvailableNetworks(@NonNull List<AvailableNetworkInfo> availableNetworks,
@Nullable @CallbackExecutor Executor executor,
@UpdateAvailableNetworksResult @Nullable Consumer<Integer> callback) {
@@ -14223,6 +14406,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CARRIERLOCK)
public void setMultiSimCarrierRestriction(boolean isMultiSimCarrierRestricted) {
try {
ITelephony service = getITelephony();
@@ -14276,6 +14460,7 @@
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@IsMultiSimSupportedResult
public int isMultiSimSupported() {
if (getSupportedModemCount() < 2) {
@@ -14306,6 +14491,7 @@
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public void switchMultiSimConfig(int numOfSims) {
try {
ITelephony telephony = getITelephony();
@@ -14331,6 +14517,7 @@
* configurations, otherwise return {@code false}.
*/
@RequiresPermission(Manifest.permission.READ_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public boolean doesSwitchMultiSimConfigTriggerReboot() {
try {
ITelephony service = getITelephony();
@@ -14383,6 +14570,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @CarrierPrivilegeStatus int getCarrierPrivilegeStatus(int uid) {
try {
ITelephony telephony = getITelephony();
@@ -14496,6 +14684,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean isDataEnabledForApn(@ApnType int apnType) {
String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
try {
@@ -14517,6 +14706,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean isApnMetered(@ApnType int apnType) {
try {
ITelephony service = getITelephony();
@@ -14545,6 +14735,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public void setSystemSelectionChannels(@NonNull List<RadioAccessSpecifier> specifiers,
@NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<Boolean> callback) {
@@ -14562,6 +14753,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public void setSystemSelectionChannels(@NonNull List<RadioAccessSpecifier> specifiers) {
Objects.requireNonNull(specifiers, "Specifiers must not be null.");
setSystemSelectionChannelsInternal(specifiers, null, null);
@@ -14608,6 +14800,7 @@
*/
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public @NonNull List<RadioAccessSpecifier> getSystemSelectionChannels() {
try {
ITelephony service = getITelephony();
@@ -14635,6 +14828,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public boolean matchesCurrentSimOperator(@NonNull String mccmnc, @MvnoType int mvnoType,
@Nullable String mvnoMatchData) {
try {
@@ -14725,6 +14919,7 @@
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void getCallForwarding(@CallForwardingReason int callForwardingReason,
@NonNull Executor executor, @NonNull CallForwardingInfoCallback callback) {
if (callForwardingReason < CallForwardingInfo.REASON_UNCONDITIONAL
@@ -14800,6 +14995,7 @@
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void setCallForwarding(@NonNull CallForwardingInfo callForwardingInfo,
@Nullable @CallbackExecutor Executor executor,
@Nullable @CallForwardingInfoCallback.CallForwardingError
@@ -14912,6 +15108,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void getCallWaitingStatus(@NonNull Executor executor,
@NonNull @CallWaitingStatus Consumer<Integer> resultListener) {
Objects.requireNonNull(executor);
@@ -14960,6 +15157,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void setCallWaitingEnabled(boolean enabled, @Nullable Executor executor,
@Nullable Consumer<Integer> resultListener) {
if (resultListener != null) {
@@ -15041,6 +15239,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public void setMobileDataPolicyEnabled(@MobileDataPolicy int policy, boolean enabled) {
try {
ITelephony service = getITelephony();
@@ -15061,6 +15260,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean isMobileDataPolicyEnabled(@MobileDataPolicy int policy) {
try {
ITelephony service = getITelephony();
@@ -15095,6 +15295,7 @@
*/
@WorkerThread
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@SystemApi
public boolean isIccLockEnabled() {
try {
@@ -15129,6 +15330,7 @@
@SystemApi
@NonNull
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public PinResult setIccLockEnabled(boolean enabled, @NonNull String pin) {
checkNotNull(pin, "setIccLockEnabled pin can't be null.");
try {
@@ -15170,6 +15372,7 @@
@SystemApi
@NonNull
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public PinResult changeIccLockPin(@NonNull String oldPin, @NonNull String newPin) {
checkNotNull(oldPin, "changeIccLockPin oldPin can't be null.");
checkNotNull(newPin, "changeIccLockPin newPin can't be null.");
@@ -15562,6 +15765,7 @@
*
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @NonNull List<String> getEquivalentHomePlmns() {
try {
ITelephony telephony = getITelephony();
@@ -15675,6 +15879,7 @@
* @param capability the name of the capability to check for
* @return the availability of the capability
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean isRadioInterfaceCapabilitySupported(
@NonNull @RadioInterfaceCapability String capability) {
try {
@@ -15796,6 +16001,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
@ThermalMitigationResult
public int sendThermalMitigationRequest(
@NonNull ThermalMitigationRequest thermalMitigationRequest) {
@@ -16067,6 +16273,7 @@
@WorkerThread
@RequiresPermission(anyOf = {android.Manifest.permission.MODIFY_PHONE_STATE,
Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public void bootstrapAuthenticationRequest(
@UiccAppTypeExt int appType, @NonNull Uri nafId,
@NonNull UaSecurityProtocolIdentifier securityProtocol,
@@ -16161,6 +16368,7 @@
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public void setSignalStrengthUpdateRequest(@NonNull SignalStrengthUpdateRequest request) {
Objects.requireNonNull(request, "request must not be null");
@@ -16190,6 +16398,7 @@
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public void clearSignalStrengthUpdateRequest(@NonNull SignalStrengthUpdateRequest request) {
Objects.requireNonNull(request, "request must not be null");
diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
index 122662d..e0c5298 100644
--- a/telephony/java/android/telephony/TelephonyScanManager.java
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -19,6 +19,8 @@
import static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
+import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -42,6 +44,7 @@
/**
* Manages the radio access network scan requests and callbacks.
*/
+@RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public final class TelephonyScanManager {
private static final String TAG = "TelephonyScanManager";
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index b0ddf2c..a710e38 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1290,8 +1290,8 @@
&& 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 @@
// 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/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java
index ab35d77..4452d1c 100644
--- a/telephony/java/android/telephony/euicc/EuiccCardManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccCardManager.java
@@ -19,8 +19,10 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
import android.annotation.SystemApi;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.RemoteException;
import android.service.euicc.EuiccProfileInfo;
@@ -61,6 +63,7 @@
* @hide
*/
@SystemApi
+@RequiresFeature(PackageManager.FEATURE_TELEPHONY_EUICC)
public class EuiccCardManager {
private static final String TAG = "EuiccCardManager";
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index a1e4f29..a49a61b5 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
@@ -54,6 +55,7 @@
*
* <p>See {@link #isEnabled} before attempting to use these APIs.
*/
+@RequiresFeature(PackageManager.FEATURE_TELEPHONY_EUICC)
public class EuiccManager {
/**
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 82d64ab..5bae1ad 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -21,11 +21,13 @@
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SuppressAutoDoc;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
@@ -61,6 +63,7 @@
* Use {@link android.telephony.ims.ImsManager#getImsMmTelManager(int)} to get an instance of this
* manager.
*/
+@RequiresFeature(PackageManager.FEATURE_TELEPHONY_IMS)
public class ImsMmTelManager implements RegistrationManager {
private static final String TAG = "ImsMmTelManager";
diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java
index 1b047c7..3415868 100644
--- a/telephony/java/android/telephony/ims/ImsRcsManager.java
+++ b/telephony/java/android/telephony/ims/ImsRcsManager.java
@@ -19,11 +19,13 @@
import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
+import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -53,6 +55,7 @@
*
* Use {@link ImsManager#getImsRcsManager(int)} to create an instance of this manager.
*/
+@RequiresFeature(PackageManager.FEATURE_TELEPHONY_IMS)
public class ImsRcsManager {
private static final String TAG = "ImsRcsManager";
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 5aef8a6..677c1a9 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -20,6 +20,7 @@
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.StringDef;
@@ -55,6 +56,7 @@
* applications and may vary. It is up to the carrier and OEM applications to ensure that the
* correct provisioning keys are being used when integrating with a vendor's ImsService.
*/
+@RequiresFeature(PackageManager.FEATURE_TELEPHONY_IMS)
public class ProvisioningManager {
private static final String TAG = "ProvisioningManager";
diff --git a/telephony/java/android/telephony/ims/RegistrationManager.java b/telephony/java/android/telephony/ims/RegistrationManager.java
index a2015cd..090d413 100644
--- a/telephony/java/android/telephony/ims/RegistrationManager.java
+++ b/telephony/java/android/telephony/ims/RegistrationManager.java
@@ -21,7 +21,9 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
+import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -42,6 +44,7 @@
/**
* Manages IMS Service registration state for associated {@link ImsFeature}s.
*/
+@RequiresFeature(PackageManager.FEATURE_TELEPHONY_IMS)
public interface RegistrationManager {
/**
diff --git a/telephony/java/android/telephony/ims/SipDelegateManager.java b/telephony/java/android/telephony/ims/SipDelegateManager.java
index f913df5..94e9afb 100644
--- a/telephony/java/android/telephony/ims/SipDelegateManager.java
+++ b/telephony/java/android/telephony/ims/SipDelegateManager.java
@@ -21,6 +21,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.Context;
@@ -57,6 +58,7 @@
* @hide
*/
@SystemApi
+@RequiresFeature(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION)
public class SipDelegateManager {
/**
diff --git a/tests/ApkVerityTest/AndroidTest.xml b/tests/ApkVerityTest/AndroidTest.xml
index 55704ed..3c8e1ed 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>
diff --git a/tools/processors/intdef_mappings/Android.bp b/tools/processors/intdef_mappings/Android.bp
index 82a5dac..7059c52 100644
--- a/tools/processors/intdef_mappings/Android.bp
+++ b/tools/processors/intdef_mappings/Android.bp
@@ -7,18 +7,24 @@
default_applicable_licenses: ["frameworks_base_license"],
}
+java_library_host {
+ name: "libintdef-annotation-processor",
+
+ srcs: [
+ ":framework-annotations",
+ "src/**/*.java",
+ "src/**/*.kt",
+ ],
+
+ use_tools_jar: true,
+}
+
java_plugin {
name: "intdef-annotation-processor",
processor_class: "android.processor.IntDefProcessor",
- srcs: [
- ":framework-annotations",
- "src/**/*.java",
- "src/**/*.kt"
- ],
-
- use_tools_jar: true,
+ static_libs: ["libintdef-annotation-processor"],
}
java_test_host {
@@ -26,8 +32,8 @@
srcs: [
"test/**/*.java",
- "test/**/*.kt"
- ],
+ "test/**/*.kt",
+ ],
java_resource_dirs: ["test/resources"],
static_libs: [
@@ -35,7 +41,7 @@
"truth-prebuilt",
"junit",
"guava",
- "intdef-annotation-processor"
+ "libintdef-annotation-processor",
],
test_suites: ["general-tests"],
diff --git a/tools/processors/view_inspector/Android.bp b/tools/processors/view_inspector/Android.bp
index ea9974f..877a1d2 100644
--- a/tools/processors/view_inspector/Android.bp
+++ b/tools/processors/view_inspector/Android.bp
@@ -7,10 +7,8 @@
default_applicable_licenses: ["frameworks_base_license"],
}
-java_plugin {
- name: "view-inspector-annotation-processor",
-
- processor_class: "android.processor.view.inspector.PlatformInspectableProcessor",
+java_library_host {
+ name: "libview-inspector-annotation-processor",
srcs: ["src/java/**/*.java"],
java_resource_dirs: ["src/resources"],
@@ -23,6 +21,16 @@
use_tools_jar: true,
}
+java_plugin {
+ name: "view-inspector-annotation-processor",
+
+ processor_class: "android.processor.view.inspector.PlatformInspectableProcessor",
+
+ static_libs: [
+ "libview-inspector-annotation-processor",
+ ],
+}
+
java_test_host {
name: "view-inspector-annotation-processor-test",
@@ -32,7 +40,7 @@
static_libs: [
"junit",
"guava",
- "view-inspector-annotation-processor"
+ "libview-inspector-annotation-processor",
],
test_suites: ["general-tests"],