Merge "expose APIs for mainline telephony-sdk"
diff --git a/Android.bp b/Android.bp
index 7d91b1e..c979cc9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -366,7 +366,9 @@
sdk_version: "core_platform",
libs: [
+ "app-compat-annotations",
"ext",
+ "unsupportedappusage",
"updatable_media_stubs",
],
@@ -426,7 +428,6 @@
name: "framework-minus-apex",
defaults: ["framework-defaults"],
srcs: [":framework-non-updatable-sources"],
- libs: ["app-compat-annotations"],
installable: true,
javac_shard_size: 150,
required: [
@@ -458,7 +459,8 @@
installable: false, // this lib is a build-only library
static_libs: [
"framework-minus-apex",
- // TODO(jiyong): add stubs for APEXes here
+ "framework-sdkext-stubs-systemapi",
+ // TODO(jiyong): add more stubs for APEXes here
],
sdk_version: "core_platform",
}
@@ -468,14 +470,16 @@
defaults: ["framework-defaults"],
srcs: [":framework-all-sources"],
installable: false,
- libs: ["app-compat-annotations"],
}
java_library {
name: "framework-annotation-proc",
defaults: ["framework-defaults"],
srcs: [":framework-all-sources"],
- libs: ["app-compat-annotations"],
+ libs: [
+ "app-compat-annotations",
+ "unsupportedappusage",
+ ],
installable: false,
plugins: [
"unsupportedappusage-annotation-processor",
@@ -563,6 +567,7 @@
"core/java/android/annotation/Nullable.java",
"core/java/android/annotation/IntDef.java",
"core/java/android/annotation/IntRange.java",
+ "core/java/android/annotation/SystemApi.java",
"core/java/android/annotation/UnsupportedAppUsage.java",
"core/java/com/android/internal/annotations/GuardedBy.java",
"core/java/com/android/internal/annotations/VisibleForTesting.java",
@@ -1604,10 +1609,13 @@
filegroup {
name: "framework-cellbroadcast-shared-srcs",
srcs: [
- "core/java/android/util/LocalLog.java",
+ "core/java/android/os/HandlerExecutor.java",
+ "core/java/android/util/LocalLog.java",
"core/java/android/util/Slog.java",
- "core/java/com/android/internal/util/State.java",
- "core/java/com/android/internal/util/StateMachine.java",
+ "core/java/com/android/internal/util/IState.java",
+ "core/java/com/android/internal/util/Preconditions.java",
+ "core/java/com/android/internal/util/State.java",
+ "core/java/com/android/internal/util/StateMachine.java",
],
}
@@ -1619,15 +1627,14 @@
"core/java/android/os/RegistrantList.java",
"core/java/android/os/Registrant.java",
"core/java/android/util/LocalLog.java",
- "core/java/android/util/Slog.java",
"core/java/android/util/TimeUtils.java",
"core/java/com/android/internal/os/SomeArgs.java",
+ "core/java/com/android/internal/util/FastXmlSerializer.java",
+ "core/java/com/android/internal/util/HexDump.java",
+ "core/java/com/android/internal/util/IndentingPrintWriter.java",
"core/java/com/android/internal/util/Preconditions.java",
"core/java/com/android/internal/util/State.java",
"core/java/com/android/internal/util/StateMachine.java",
- "core/java/com/android/internal/util/XmlUtils.java",
- "core/java/com/android/internal/util/HexDump.java",
- "core/java/com/android/internal/util/IndentingPrintWriter.java",
- "core/java/com/android/internal/util/DumpUtils.java"
+ "core/java/com/android/internal/util/UserIcons.java",
],
}
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 1e0b58e..1a6f104 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -7,6 +7,50 @@
"exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
+ },
+ {
+ "name": "ExtServicesUnitTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "TestablesTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ }
+ ]
+ },
+ {
+ "name": "FrameworksServicesTests",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ }
+ ]
}
]
}
diff --git a/apex/Android.bp b/apex/Android.bp
new file mode 100644
index 0000000..9ea3953
--- /dev/null
+++ b/apex/Android.bp
@@ -0,0 +1,39 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+mainline_stubs_args =
+ "--error UnhiddenSystemApi " +
+ "--hide BroadcastBehavior " +
+ "--hide DeprecationMismatch " +
+ "--hide HiddenSuperclass " +
+ "--hide HiddenTypedefConstant " +
+ "--hide HiddenTypeParameter " +
+ "--hide MissingPermission " +
+ "--hide RequiresPermission " +
+ "--hide SdkConstant " +
+ "--hide Todo " +
+ "--hide Typo " +
+ "--hide UnavailableSymbol "
+
+stubs_defaults {
+ name: "framework-module-stubs-defaults-publicapi",
+ args: mainline_stubs_args,
+ installable: false,
+}
+
+stubs_defaults {
+ name: "framework-module-stubs-defaults-systemapi",
+ args: mainline_stubs_args + " --show-annotation android.annotation.SystemApi ",
+ installable: false,
+}
diff --git a/apex/sdkext/Android.bp b/apex/sdkext/Android.bp
index 40f3c45..b9071f8 100644
--- a/apex/sdkext/Android.bp
+++ b/apex/sdkext/Android.bp
@@ -12,6 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_visibility: [":__subpackages__"],
+}
+
apex {
name: "com.android.sdkext",
manifest: "manifest.json",
@@ -19,13 +23,17 @@
java_libs: [ "framework-sdkext" ],
prebuilts: [
"com.android.sdkext.ldconfig",
- "cur_sdkinfo",
"derive_sdk.rc",
],
key: "com.android.sdkext.key",
certificate: ":com.android.sdkext.certificate",
}
+sdk {
+ name: "sdkext-sdk",
+ java_libs: [ "framework-sdkext-stubs-systemapi" ],
+}
+
apex_key {
name: "com.android.sdkext.key",
public_key: "com.android.sdkext.avbpubkey",
@@ -43,28 +51,3 @@
filename: "ld.config.txt",
installable: false,
}
-
-python_binary_host {
- name: "gen_sdkinfo",
- srcs: [
- "derive_sdk/sdk.proto",
- "gen_sdkinfo.py",
- ],
- proto: {
- canonical_path_from_root: false,
- },
-}
-
-gensrcs {
- name: "cur_sdkinfo_src",
- srcs: [""],
- tools: [ "gen_sdkinfo" ],
- cmd: "$(location) -v 0 -o $(out)",
-}
-
-prebuilt_etc {
- name: "cur_sdkinfo",
- src: ":cur_sdkinfo_src",
- filename: "sdkinfo.binarypb",
- installable: false,
-}
diff --git a/apex/sdkext/TEST_MAPPING b/apex/sdkext/TEST_MAPPING
new file mode 100644
index 0000000..91947f3
--- /dev/null
+++ b/apex/sdkext/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsSdkExtTestCases"
+ }
+ ]
+}
diff --git a/apex/sdkext/derive_sdk/derive_sdk.cpp b/apex/sdkext/derive_sdk/derive_sdk.cpp
index 0aacebe..7536def 100644
--- a/apex/sdkext/derive_sdk/derive_sdk.cpp
+++ b/apex/sdkext/derive_sdk/derive_sdk.cpp
@@ -68,7 +68,7 @@
auto itr = std::min_element(versions.begin(), versions.end());
std::string prop_value = itr == versions.end() ? "0" : std::to_string(*itr);
- if (!android::base::SetProperty("persist.com.android.sdkext.sdk_info", prop_value)) {
+ if (!android::base::SetProperty("ro.build.version.extensions.r", prop_value)) {
LOG(ERROR) << "failed to set sdk_info prop";
return EXIT_FAILURE;
}
diff --git a/apex/sdkext/framework/Android.bp b/apex/sdkext/framework/Android.bp
index b17f0f8..a50dc3d 100644
--- a/apex/sdkext/framework/Android.bp
+++ b/apex/sdkext/framework/Android.bp
@@ -12,12 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_visibility: [ ":__pkg__" ]
+}
+
filegroup {
name: "framework-sdkext-sources",
srcs: [
"java/**/*.java",
],
path: "java",
+ visibility: [ "//frameworks/base:__pkg__" ] // For the "global" stubs.
}
java_library {
@@ -27,4 +32,40 @@
libs: [ "framework-annotations-lib" ],
permitted_packages: [ "android.os.ext" ],
installable: true,
+ visibility: [ "//frameworks/base/apex/sdkext:__pkg__" ],
+}
+
+droidstubs {
+ name: "framework-sdkext-droidstubs-publicapi",
+ defaults: [
+ "framework-sdkext-stubs-defaults",
+ "framework-module-stubs-defaults-publicapi",
+ ]
+}
+
+droidstubs {
+ name: "framework-sdkext-droidstubs-systemapi",
+ defaults: [
+ "framework-sdkext-stubs-defaults",
+ "framework-module-stubs-defaults-systemapi",
+ ]
+}
+
+stubs_defaults {
+ name: "framework-sdkext-stubs-defaults",
+ srcs: [
+ ":framework-sdkext-sources",
+ ":framework-annotations",
+ ],
+ sdk_version: "system_current",
+}
+
+java_library {
+ name: "framework-sdkext-stubs-systemapi",
+ srcs: [":framework-sdkext-droidstubs-systemapi"],
+ sdk_version: "system_current",
+ visibility: [
+ "//frameworks/base:__pkg__", // Framework
+ "//frameworks/base/apex/sdkext:__pkg__", // sdkext SDK
+ ]
}
diff --git a/apex/sdkext/framework/java/android/os/ext/SdkExtensions.java b/apex/sdkext/framework/java/android/os/ext/SdkExtensions.java
index c039a82..d3b9397 100644
--- a/apex/sdkext/framework/java/android/os/ext/SdkExtensions.java
+++ b/apex/sdkext/framework/java/android/os/ext/SdkExtensions.java
@@ -17,25 +17,40 @@
package android.os.ext;
import android.annotation.IntDef;
+import android.annotation.SystemApi;
import android.os.Build.VERSION_CODES;
import android.os.SystemProperties;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-/** @hide */
+/**
+ * Methods for interacting with the extension SDK.
+ *
+ * This class provides information about the extension SDK version present
+ * on this device. Use the {@link #getExtensionVersion(int) getExtension} to
+ * query for the extension version for the given SDK version.
+
+ * @hide
+ */
+@SystemApi
public class SdkExtensions {
private static final int R_EXTENSION_INT;
static {
- R_EXTENSION_INT = SystemProperties.getInt("persist.com.android.sdkext.sdk_info", 0);
+ R_EXTENSION_INT = SystemProperties.getInt("ro.build.version.extensions.r", 0);
}
- /** Values suitable as parameters for {@link #getExtensionVersion(int)}. */
+ /**
+ * Values suitable as parameters for {@link #getExtensionVersion(int)}.
+ * @hide
+ */
@IntDef(value = { VERSION_CODES.R })
@Retention(RetentionPolicy.SOURCE)
public @interface SdkVersion {}
+ private SdkExtensions() { }
+
/**
* Return the version of the extension to the given SDK.
*
diff --git a/apex/sdkext/framework/tests/Android.bp b/apex/sdkext/framework/tests/Android.bp
deleted file mode 100644
index 3d5dbb3..0000000
--- a/apex/sdkext/framework/tests/Android.bp
+++ /dev/null
@@ -1,10 +0,0 @@
-android_test {
- name: "framework-sdkext-tests",
- srcs: ["src/**/*.java"],
- libs: [
- "android.test.base",
- "android.test.runner",
- ],
- static_libs: [ "framework-sdkext" ],
- platform_apis: true,
-}
diff --git a/apex/sdkext/framework/tests/AndroidManifest.xml b/apex/sdkext/framework/tests/AndroidManifest.xml
deleted file mode 100644
index 831f132..0000000
--- a/apex/sdkext/framework/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.sdkext.tests">
-
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
-
- <instrumentation android:name="android.test.InstrumentationTestRunner"
- android:targetPackage="com.android.sdkext.tests" />
-
-</manifest>
diff --git a/apex/sdkext/framework/tests/src/android/os/ext/SdkExtensionsTest.java b/apex/sdkext/framework/tests/src/android/os/ext/SdkExtensionsTest.java
deleted file mode 100644
index 6885110..0000000
--- a/apex/sdkext/framework/tests/src/android/os/ext/SdkExtensionsTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os.ext;
-
-import android.os.Build;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-public class SdkExtensionsTest extends TestCase {
-
- @SmallTest
- public void testBadArgument() throws Exception {
- try {
- SdkExtensions.getExtensionVersion(Build.VERSION_CODES.Q);
- fail("expected IllegalArgumentException");
- } catch (IllegalArgumentException expected) { }
-
- try {
- SdkExtensions.getExtensionVersion(999999);
- fail("expected IllegalArgumentException");
- } catch (IllegalArgumentException expected) { }
- }
-
- @SmallTest
- public void testDefault() throws Exception {
- int r = SdkExtensions.getExtensionVersion(Build.VERSION_CODES.R);
- assertTrue(r >= 0);
- }
-
-}
diff --git a/apex/sdkext/gen_sdkinfo.py b/apex/sdkext/gen_sdkinfo.py
deleted file mode 100644
index 5af478b..0000000
--- a/apex/sdkext/gen_sdkinfo.py
+++ /dev/null
@@ -1,19 +0,0 @@
-import sdk_pb2
-import sys
-
-if __name__ == '__main__':
- argv = sys.argv[1:]
- if not len(argv) == 4 or sorted([argv[0], argv[2]]) != ['-o', '-v']:
- print('usage: gen_sdkinfo -v <version> -o <output-file>')
- sys.exit(1)
-
- for i in range(len(argv)):
- if sys.argv[i] == '-o':
- filename = sys.argv[i+1]
- if sys.argv[i] == '-v':
- version = int(sys.argv[i+1])
-
- proto = sdk_pb2.SdkVersion()
- proto.version = version
- with open(filename, 'wb') as f:
- f.write(proto.SerializeToString())
diff --git a/api/current.txt b/api/current.txt
index ee89cc1..5fbd967 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -28903,6 +28903,7 @@
public class NetworkRequest implements android.os.Parcelable {
method public int describeContents();
+ method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
method public boolean hasCapability(int);
method public boolean hasTransport(int);
method public void writeToParcel(android.os.Parcel, int);
@@ -42386,6 +42387,7 @@
method public static String[] listxattr(String) throws android.system.ErrnoException;
method public static long lseek(java.io.FileDescriptor, long, int) throws android.system.ErrnoException;
method public static android.system.StructStat lstat(String) throws android.system.ErrnoException;
+ method @NonNull public static java.io.FileDescriptor memfd_create(@NonNull String, int) throws android.system.ErrnoException;
method public static void mincore(long, long, byte[]) throws android.system.ErrnoException;
method public static void mkdir(String, int) throws android.system.ErrnoException;
method public static void mkfifo(String, int) throws android.system.ErrnoException;
@@ -42694,6 +42696,7 @@
field public static final int MCAST_UNBLOCK_SOURCE;
field public static final int MCL_CURRENT;
field public static final int MCL_FUTURE;
+ field public static final int MFD_CLOEXEC;
field public static final int MSG_CTRUNC;
field public static final int MSG_DONTROUTE;
field public static final int MSG_EOR;
@@ -44196,6 +44199,7 @@
field public static final String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
field public static final String KEY_DIAL_STRING_REPLACE_STRING_ARRAY = "dial_string_replace_string_array";
field public static final String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
+ field public static final String KEY_DISABLE_SUPPLEMENTARY_SERVICES_IN_AIRPLANE_MODE_BOOL = "disable_supplementary_services_in_airplane_mode_bool";
field public static final String KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY = "disconnect_cause_play_busytone_int_array";
field public static final String KEY_DISPLAY_HD_AUDIO_PROPERTY_BOOL = "display_hd_audio_property_bool";
field public static final String KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL = "drop_video_call_when_answering_audio_call_bool";
@@ -44264,7 +44268,6 @@
field public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSSNR_INT = "opportunistic_network_entry_threshold_rssnr_int";
field public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSRP_INT = "opportunistic_network_exit_threshold_rsrp_int";
field public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT = "opportunistic_network_exit_threshold_rssnr_int";
- field public static final String KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT = "parameters_use_for_5g_nr_signal_bar_int";
field public static final String KEY_PREFER_2G_BOOL = "prefer_2g_bool";
field public static final String KEY_PREVENT_CLIR_ACTIVATION_AND_DEACTIVATION_CODE_BOOL = "prevent_clir_activation_and_deactivation_code_bool";
field public static final String KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY = "radio_restart_failure_causes_int_array";
@@ -45165,7 +45168,7 @@
method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getMeid(int);
method public String getMmsUAProfUrl();
method public String getMmsUserAgent();
- method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getNai();
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getNai();
method public String getNetworkCountryIso();
method public String getNetworkOperator();
method public String getNetworkOperatorName();
@@ -45504,6 +45507,7 @@
field public static final int TYPE_MCX = 1024; // 0x400
field public static final int TYPE_MMS = 2; // 0x2
field public static final int TYPE_SUPL = 4; // 0x4
+ field public static final int TYPE_XCAP = 2048; // 0x800
}
public static class ApnSetting.Builder {
@@ -46073,12 +46077,12 @@
package android.text {
- public class AlteredCharSequence implements java.lang.CharSequence android.text.GetChars {
- method public char charAt(int);
- method public void getChars(int, int, char[], int);
- method public int length();
- method public static android.text.AlteredCharSequence make(CharSequence, char[], int, int);
- method public CharSequence subSequence(int, int);
+ @Deprecated public class AlteredCharSequence implements java.lang.CharSequence android.text.GetChars {
+ method @Deprecated public char charAt(int);
+ method @Deprecated public void getChars(int, int, char[], int);
+ method @Deprecated public int length();
+ method @Deprecated public static android.text.AlteredCharSequence make(CharSequence, char[], int, int);
+ method @Deprecated public CharSequence subSequence(int, int);
}
@Deprecated public class AndroidCharacter {
@@ -46813,7 +46817,7 @@
field public static final long WEEK_IN_MILLIS = 604800000L; // 0x240c8400L
field public static final String YEAR_FORMAT = "%Y";
field public static final String YEAR_FORMAT_TWO_DIGITS = "%g";
- field public static final long YEAR_IN_MILLIS = 31449600000L; // 0x7528ad000L
+ field @Deprecated public static final long YEAR_IN_MILLIS = 31449600000L; // 0x7528ad000L
field @Deprecated public static final int[] sameMonthTable;
field @Deprecated public static final int[] sameYearTable;
}
@@ -48250,6 +48254,13 @@
ctor public Base64OutputStream(java.io.OutputStream, int);
}
+ public final class CloseGuard {
+ ctor public CloseGuard();
+ method public void close();
+ method public void open(@NonNull String);
+ method public void warnIfOpen();
+ }
+
@Deprecated public final class Config {
field @Deprecated public static final boolean DEBUG = false;
field @Deprecated public static final boolean LOGD = true;
diff --git a/api/system-current.txt b/api/system-current.txt
old mode 100644
new mode 100755
index 299048e..a41564e
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -75,6 +75,7 @@
field public static final String GET_TOP_ACTIVITY_INFO = "android.permission.GET_TOP_ACTIVITY_INFO";
field public static final String GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS = "android.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS";
field public static final String GRANT_RUNTIME_PERMISSIONS = "android.permission.GRANT_RUNTIME_PERMISSIONS";
+ field public static final String GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS = "android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS";
field public static final String HANDLE_CAR_MODE_CHANGES = "android.permission.HANDLE_CAR_MODE_CHANGES";
field public static final String HARDWARE_TEST = "android.permission.HARDWARE_TEST";
field public static final String HDMI_CEC = "android.permission.HDMI_CEC";
@@ -1225,6 +1226,7 @@
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getAppStandbyBucket(String);
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public java.util.Map<java.lang.String,java.lang.Integer> getAppStandbyBuckets();
method public int getUsageSource();
+ method @RequiresPermission(android.Manifest.permission.BIND_CARRIER_SERVICES) public void onCarrierPrivilegedAppsChanged();
method @RequiresPermission(allOf={android.Manifest.permission.SUSPEND_APPS, android.Manifest.permission.OBSERVE_APP_USAGE}) public void registerAppUsageLimitObserver(int, @NonNull String[], @NonNull java.time.Duration, @NonNull java.time.Duration, @Nullable android.app.PendingIntent);
method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerAppUsageObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, @NonNull android.app.PendingIntent);
method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerUsageSessionObserver(int, @NonNull String[], @NonNull java.time.Duration, @NonNull java.time.Duration, @NonNull android.app.PendingIntent, @Nullable android.app.PendingIntent);
@@ -1251,8 +1253,22 @@
package android.bluetooth {
public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void disableOptionalCodecs(@Nullable android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void enableOptionalCodecs(@Nullable android.bluetooth.BluetoothDevice);
+ method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothDevice getActiveDevice();
+ method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothCodecStatus getCodecStatus(@Nullable android.bluetooth.BluetoothDevice);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public int getOptionalCodecsEnabled(@Nullable android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void setCodecConfigPreference(@Nullable android.bluetooth.BluetoothDevice, @Nullable android.bluetooth.BluetoothCodecConfig);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void setOptionalCodecsEnabled(@Nullable android.bluetooth.BluetoothDevice, int);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public int supportsOptionalCodecs(@Nullable android.bluetooth.BluetoothDevice);
+ field public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0; // 0x0
+ field public static final int OPTIONAL_CODECS_PREF_DISABLED = 0; // 0x0
+ field public static final int OPTIONAL_CODECS_PREF_ENABLED = 1; // 0x1
+ field public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1; // 0xffffffff
+ field public static final int OPTIONAL_CODECS_SUPPORTED = 1; // 0x1
+ field public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1; // 0xffffffff
}
public final class BluetoothAdapter {
@@ -1281,17 +1297,72 @@
method public void onMetadataChanged(@NonNull android.bluetooth.BluetoothDevice, int, @Nullable byte[]);
}
+ public final class BluetoothCodecConfig implements android.os.Parcelable {
+ ctor public BluetoothCodecConfig(int, int, int, int, int, long, long, long, long);
+ ctor public BluetoothCodecConfig(int);
+ method public int getBitsPerSample();
+ method @NonNull public String getCodecName();
+ method public int getCodecPriority();
+ method public long getCodecSpecific1();
+ method public int getCodecType();
+ method public int getSampleRate();
+ method public boolean isMandatoryCodec();
+ field public static final int BITS_PER_SAMPLE_16 = 1; // 0x1
+ field public static final int BITS_PER_SAMPLE_24 = 2; // 0x2
+ field public static final int BITS_PER_SAMPLE_32 = 4; // 0x4
+ field public static final int BITS_PER_SAMPLE_NONE = 0; // 0x0
+ field public static final int CHANNEL_MODE_MONO = 1; // 0x1
+ field public static final int CHANNEL_MODE_NONE = 0; // 0x0
+ field public static final int CHANNEL_MODE_STEREO = 2; // 0x2
+ field public static final int CODEC_PRIORITY_DEFAULT = 0; // 0x0
+ field public static final int CODEC_PRIORITY_DISABLED = -1; // 0xffffffff
+ field public static final int CODEC_PRIORITY_HIGHEST = 1000000; // 0xf4240
+ field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothCodecConfig> CREATOR;
+ field public static final int SAMPLE_RATE_176400 = 16; // 0x10
+ field public static final int SAMPLE_RATE_192000 = 32; // 0x20
+ field public static final int SAMPLE_RATE_44100 = 1; // 0x1
+ field public static final int SAMPLE_RATE_48000 = 2; // 0x2
+ field public static final int SAMPLE_RATE_88200 = 4; // 0x4
+ field public static final int SAMPLE_RATE_96000 = 8; // 0x8
+ field public static final int SAMPLE_RATE_NONE = 0; // 0x0
+ field public static final int SOURCE_CODEC_TYPE_AAC = 1; // 0x1
+ field public static final int SOURCE_CODEC_TYPE_APTX = 2; // 0x2
+ field public static final int SOURCE_CODEC_TYPE_APTX_HD = 3; // 0x3
+ field public static final int SOURCE_CODEC_TYPE_INVALID = 1000000; // 0xf4240
+ field public static final int SOURCE_CODEC_TYPE_LDAC = 4; // 0x4
+ field public static final int SOURCE_CODEC_TYPE_MAX = 5; // 0x5
+ field public static final int SOURCE_CODEC_TYPE_SBC = 0; // 0x0
+ }
+
+ public final class BluetoothCodecStatus implements android.os.Parcelable {
+ ctor public BluetoothCodecStatus(@Nullable android.bluetooth.BluetoothCodecConfig, @Nullable android.bluetooth.BluetoothCodecConfig[], @Nullable android.bluetooth.BluetoothCodecConfig[]);
+ method @Nullable public android.bluetooth.BluetoothCodecConfig getCodecConfig();
+ method @Nullable public android.bluetooth.BluetoothCodecConfig[] getCodecsLocalCapabilities();
+ method @Nullable public android.bluetooth.BluetoothCodecConfig[] getCodecsSelectableCapabilities();
+ field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothCodecStatus> CREATOR;
+ field public static final String EXTRA_CODEC_STATUS = "android.bluetooth.extra.CODEC_STATUS";
+ }
+
public final class BluetoothDevice implements android.os.Parcelable {
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean cancelBondProcess();
+ method public boolean cancelPairing();
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getBatteryLevel();
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getMessageAccessPermission();
method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public byte[] getMetadata(int);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getPhonebookAccessPermission();
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getSimAccessPermission();
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean isBondingInitiatedLocally();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean isConnected();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean isEncrypted();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean isInSilenceMode();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean removeBond();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean setAlias(@NonNull String);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setMessageAccessPermission(int);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setMetadata(int, @NonNull byte[]);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setPhonebookAccessPermission(int);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setPin(@Nullable String);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setSilenceMode(boolean);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setSimAccessPermission(int);
field public static final int ACCESS_ALLOWED = 1; // 0x1
field public static final int ACCESS_REJECTED = 2; // 0x2
field public static final int ACCESS_UNKNOWN = 0; // 0x0
@@ -1326,7 +1397,9 @@
}
public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile {
+ method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH) public java.util.List<android.bluetooth.BluetoothDevice> getActiveDevices();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public long getHiSyncId(@Nullable android.bluetooth.BluetoothDevice);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
}
@@ -1534,9 +1607,25 @@
field public static final String EXTRA_REMOTE_CALLBACK = "android.intent.extra.REMOTE_CALLBACK";
field public static final String EXTRA_RESULT_NEEDED = "android.intent.extra.RESULT_NEEDED";
field public static final String EXTRA_ROLE_NAME = "android.intent.extra.ROLE_NAME";
+ field @Deprecated public static final String EXTRA_SIM_LOCKED_REASON = "reason";
+ field @Deprecated public static final String EXTRA_SIM_STATE = "ss";
field public static final String EXTRA_UNKNOWN_INSTANT_APP = "android.intent.extra.UNKNOWN_INSTANT_APP";
field public static final String EXTRA_VERIFICATION_BUNDLE = "android.intent.extra.VERIFICATION_BUNDLE";
field public static final String METADATA_SETUP_VERSION = "android.SETUP_VERSION";
+ field @Deprecated public static final String SIM_ABSENT_ON_PERM_DISABLED = "PERM_DISABLED";
+ field @Deprecated public static final String SIM_LOCKED_NETWORK = "NETWORK";
+ field @Deprecated public static final String SIM_LOCKED_ON_PIN = "PIN";
+ field @Deprecated public static final String SIM_LOCKED_ON_PUK = "PUK";
+ field @Deprecated public static final String SIM_STATE_ABSENT = "ABSENT";
+ field @Deprecated public static final String SIM_STATE_CARD_IO_ERROR = "CARD_IO_ERROR";
+ field @Deprecated public static final String SIM_STATE_CARD_RESTRICTED = "CARD_RESTRICTED";
+ field @Deprecated public static final String SIM_STATE_IMSI = "IMSI";
+ field @Deprecated public static final String SIM_STATE_LOADED = "LOADED";
+ field @Deprecated public static final String SIM_STATE_LOCKED = "LOCKED";
+ field @Deprecated public static final String SIM_STATE_NOT_READY = "NOT_READY";
+ field @Deprecated public static final String SIM_STATE_PRESENT = "PRESENT";
+ field @Deprecated public static final String SIM_STATE_READY = "READY";
+ field @Deprecated public static final String SIM_STATE_UNKNOWN = "UNKNOWN";
}
public class IntentFilter implements android.os.Parcelable {
@@ -3996,6 +4085,7 @@
method @Nullable public String onHardwareRemoved(android.media.tv.TvInputHardwareInfo);
method @Nullable public android.media.tv.TvInputInfo onHdmiDeviceAdded(android.hardware.hdmi.HdmiDeviceInfo);
method @Nullable public String onHdmiDeviceRemoved(android.hardware.hdmi.HdmiDeviceInfo);
+ method public void onHdmiDeviceUpdated(@NonNull android.hardware.hdmi.HdmiDeviceInfo);
}
public abstract static class TvInputService.RecordingSession {
@@ -4472,6 +4562,9 @@
}
public abstract class ChildSessionParams {
+ method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getLocalTrafficSelectors();
+ method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getRemoteTrafficSelectors();
+ method @NonNull public java.util.List<android.net.ipsec.ike.ChildSaProposal> getSaProposals();
}
public class IkeFqdnIdentification extends android.net.ipsec.ike.IkeIdentification {
@@ -4539,6 +4632,13 @@
}
public final class IkeSessionParams {
+ method @NonNull public android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig getLocalAuthConfig();
+ method @NonNull public android.net.ipsec.ike.IkeIdentification getLocalIdentification();
+ method @NonNull public android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig getRemoteAuthConfig();
+ method @NonNull public android.net.ipsec.ike.IkeIdentification getRemoteIdentification();
+ method @NonNull public java.util.List<android.net.ipsec.ike.IkeSaProposal> getSaProposals();
+ method @NonNull public java.net.InetAddress getServerAddress();
+ method @NonNull public android.net.IpSecManager.UdpEncapsulationSocket getUdpEncapsulationSocket();
}
public static final class IkeSessionParams.Builder {
@@ -4555,6 +4655,27 @@
method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setUdpEncapsulationSocket(@NonNull android.net.IpSecManager.UdpEncapsulationSocket);
}
+ public abstract static class IkeSessionParams.IkeAuthConfig {
+ }
+
+ public static class IkeSessionParams.IkeAuthDigitalSignLocalConfig extends android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig {
+ method @NonNull public java.security.cert.X509Certificate getClientEndCertificate();
+ method @NonNull public java.util.List<java.security.cert.X509Certificate> getIntermediateCertificates();
+ method @NonNull public java.security.PrivateKey getPrivateKey();
+ }
+
+ public static class IkeSessionParams.IkeAuthDigitalSignRemoteConfig extends android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig {
+ method @NonNull public java.security.cert.X509Certificate getRemoteCaCert();
+ }
+
+ public static class IkeSessionParams.IkeAuthEapConfig extends android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig {
+ method @NonNull public android.net.eap.EapSessionConfig getEapConfig();
+ }
+
+ public static class IkeSessionParams.IkeAuthPskConfig extends android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig {
+ method @NonNull public byte[] getPsk();
+ }
+
public final class IkeTrafficSelector {
ctor public IkeTrafficSelector(int, int, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress);
field public final int endPort;
@@ -4601,6 +4722,7 @@
}
public final class TunnelModeChildSessionParams extends android.net.ipsec.ike.ChildSessionParams {
+ method @NonNull public java.util.List<android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest> getConfigurationRequests();
}
public static final class TunnelModeChildSessionParams.Builder {
@@ -4618,6 +4740,39 @@
method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams build();
}
+ public static interface TunnelModeChildSessionParams.ConfigRequest {
+ }
+
+ public static interface TunnelModeChildSessionParams.ConfigRequestIpv4Address extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+ method @Nullable public java.net.Inet4Address getAddress();
+ }
+
+ public static interface TunnelModeChildSessionParams.ConfigRequestIpv4DhcpServer extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+ method @Nullable public java.net.Inet4Address getAddress();
+ }
+
+ public static interface TunnelModeChildSessionParams.ConfigRequestIpv4DnsServer extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+ method @Nullable public java.net.Inet4Address getAddress();
+ }
+
+ public static interface TunnelModeChildSessionParams.ConfigRequestIpv4Netmask extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+ }
+
+ public static interface TunnelModeChildSessionParams.ConfigRequestIpv4Subnet extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+ }
+
+ public static interface TunnelModeChildSessionParams.ConfigRequestIpv6Address extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+ method @Nullable public java.net.Inet6Address getAddress();
+ method public int getPrefixLength();
+ }
+
+ public static interface TunnelModeChildSessionParams.ConfigRequestIpv6DnsServer extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+ method @Nullable public java.net.Inet6Address getAddress();
+ }
+
+ public static interface TunnelModeChildSessionParams.ConfigRequestIpv6Subnet extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+ }
+
}
package android.net.ipsec.ike.exceptions {
@@ -6019,6 +6174,14 @@
}
+package android.os.ext {
+
+ public class SdkExtensions {
+ method public static int getExtensionVersion(int);
+ }
+
+}
+
package android.os.image {
public class DynamicSystemClient {
@@ -7763,6 +7926,10 @@
field public final double lng;
}
+ public class CellBroadcastIntents {
+ method public static void sendOrderedBroadcastForBackgroundReceivers(@NonNull android.content.Context, @Nullable android.os.UserHandle, @NonNull android.content.Intent, @Nullable String, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle);
+ }
+
public abstract class CellBroadcastService extends android.app.Service {
ctor public CellBroadcastService();
method @CallSuper @NonNull public android.os.IBinder onBind(@Nullable android.content.Intent);
@@ -8089,6 +8256,7 @@
field public static final int UE_SECURITY_CAPABILITIES_MISMATCH = 2185; // 0x889
field public static final int UMTS_HANDOVER_TO_IWLAN = 2199; // 0x897
field public static final int UMTS_REACTIVATION_REQ = 39; // 0x27
+ field public static final int UNACCEPTABLE_NETWORK_PARAMETER = 65538; // 0x10002
field public static final int UNACCEPTABLE_NON_EPS_AUTHENTICATION = 2187; // 0x88b
field public static final int UNKNOWN = 65536; // 0x10000
field public static final int UNKNOWN_INFO_ELEMENT = 99; // 0x63
@@ -8583,6 +8751,7 @@
method @NonNull public android.content.ContentValues getContentValues();
method @Nullable public android.telephony.SmsCbEtwsInfo getEtwsWarningInfo();
method public int getGeographicalScope();
+ method @NonNull public java.util.List<android.telephony.CbGeoUtils.Geometry> getGeometries();
method @Nullable public String getLanguageCode();
method @NonNull public android.telephony.SmsCbLocation getLocation();
method public int getMaximumWaitingDuration();
@@ -8695,6 +8864,7 @@
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPrivilegedPackagesForAllActiveSubscriptions();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn(int);
@@ -8715,7 +8885,7 @@
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
method public int getMaxNumberOfSimultaneouslyActiveSims();
method public static long getMaxNumberVerificationTimeoutMillis();
- method @NonNull public String getNetworkCountryIso(int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getNetworkCountryIso(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask();
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
method public int getSimApplicationState();
@@ -8781,6 +8951,7 @@
method public void updateServiceLocation();
method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateTestOtaEmergencyNumberDbFilePath(@NonNull String);
field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED";
+ field public static final String ACTION_EMERGENCY_ASSISTANCE = "android.telephony.action.EMERGENCY_ASSISTANCE";
field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
diff --git a/api/system-lint-baseline.txt b/api/system-lint-baseline.txt
index c64e3d8..432a5fd 100644
--- a/api/system-lint-baseline.txt
+++ b/api/system-lint-baseline.txt
@@ -144,6 +144,16 @@
ProtectedMember: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context):
+PublicTypedef: android.content.integrity.AtomicFormula.Key: Don't expose @IntDef: @Key must be hidden.
+
+PublicTypedef: android.content.integrity.AtomicFormula.Operator: Don't expose @IntDef: @Operator must be hidden.
+
+PublicTypedef: android.content.integrity.CompoundFormula.Connector: Don't expose @IntDef: @Connector must be hidden.
+
+PublicTypedef: android.content.integrity.Formula.Tag: Don't expose @IntDef: @Tag must be hidden.
+
+PublicTypedef: android.content.integrity.Rule.Effect: Don't expose @IntDef: @Effect must be hidden.
+
SamShouldBeLast: android.accounts.AccountManager#addAccount(String, String, String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
diff --git a/api/test-current.txt b/api/test-current.txt
index c29ef99..b5cd479b 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3041,7 +3041,7 @@
method @Nullable public static android.content.ComponentName getDefaultRespondViaMessageApplication(@NonNull android.content.Context, boolean);
method public int getEmergencyNumberDbVersion();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag();
- method @NonNull public String getNetworkCountryIso(int);
+ method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getNetworkCountryIso(int);
method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile();
method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String);
diff --git a/api/test-lint-baseline.txt b/api/test-lint-baseline.txt
index bf21ce7..3af392c 100644
--- a/api/test-lint-baseline.txt
+++ b/api/test-lint-baseline.txt
@@ -2444,6 +2444,12 @@
ProtectedMember: android.view.ViewGroup#resetResolvedDrawables():
+PublicTypedef: android.os.HwParcel.Status: Don't expose @IntDef: @Status must be hidden.
+
+PublicTypedef: android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability: Don't expose @IntDef: @MmTelCapability must be hidden.
+
+PublicTypedef: android.telephony.ims.feature.MmTelFeature.ProcessCallResult: Don't expose @IntDef: @ProcessCallResult must be hidden.
+
RawAidl: android.telephony.mbms.vendor.MbmsDownloadServiceBase:
diff --git a/cmds/uiautomator/library/Android.bp b/cmds/uiautomator/library/Android.bp
index 1173d57..3a26063 100644
--- a/cmds/uiautomator/library/Android.bp
+++ b/cmds/uiautomator/library/Android.bp
@@ -22,6 +22,7 @@
"android.test.runner",
"junit",
"android.test.base",
+ "unsupportedappusage",
],
custom_template: "droiddoc-templates-sdk",
installable: false,
diff --git a/core/java/android/annotation/Hide.java b/core/java/android/annotation/Hide.java
new file mode 100644
index 0000000..c8e5a4a
--- /dev/null
+++ b/core/java/android/annotation/Hide.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.annotation;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PACKAGE;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that an API is hidden by default, in a similar fashion to the
+ * <pre>@hide</pre> javadoc tag.
+ *
+ * <p>Note that, in order for this to work, metalava has to be invoked with
+ * the flag {@code --hide-annotation android.annotation.Hide}.
+ * @hide
+ */
+@Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE, PACKAGE})
+@Retention(RetentionPolicy.CLASS)
+public @interface Hide {
+}
diff --git a/core/java/android/annotation/OWNERS b/core/java/android/annotation/OWNERS
index e07028b..8aceb56 100644
--- a/core/java/android/annotation/OWNERS
+++ b/core/java/android/annotation/OWNERS
@@ -1,2 +1,3 @@
tnorbye@google.com
+aurimas@google.com
per-file UnsupportedAppUsage.java = mathewi@google.com, dbrazdil@google.com, atrost@google.com, andreionea@google.com
diff --git a/core/java/android/app/role/IRoleManager.aidl b/core/java/android/app/role/IRoleManager.aidl
index d8cea28..6d790b3 100644
--- a/core/java/android/app/role/IRoleManager.aidl
+++ b/core/java/android/app/role/IRoleManager.aidl
@@ -19,7 +19,6 @@
import android.app.role.IOnRoleHoldersChangedListener;
import android.os.Bundle;
import android.os.RemoteCallback;
-import android.telephony.IFinancialSmsCallback;
/**
* @hide
@@ -55,9 +54,4 @@
List<String> getHeldRolesFromController(in String packageName);
String getDefaultSmsPackage(int userId);
-
- /**
- * Get filtered SMS messages for financial app.
- */
- void getSmsMessagesForFinancialApp(in String callingPkg, in Bundle params, in IFinancialSmsCallback callback);
}
diff --git a/core/java/android/app/timedetector/ManualTimeSuggestion.java b/core/java/android/app/timedetector/ManualTimeSuggestion.java
index 471606da..55f92be 100644
--- a/core/java/android/app/timedetector/ManualTimeSuggestion.java
+++ b/core/java/android/app/timedetector/ManualTimeSuggestion.java
@@ -56,6 +56,7 @@
public ManualTimeSuggestion(@NonNull TimestampedValue<Long> utcTime) {
mUtcTime = Objects.requireNonNull(utcTime);
+ Objects.requireNonNull(utcTime.getValue());
}
private static ManualTimeSuggestion createFromParcel(Parcel in) {
diff --git a/core/java/android/app/timedetector/PhoneTimeSuggestion.java b/core/java/android/app/timedetector/PhoneTimeSuggestion.java
index dd02af7..4a89a12 100644
--- a/core/java/android/app/timedetector/PhoneTimeSuggestion.java
+++ b/core/java/android/app/timedetector/PhoneTimeSuggestion.java
@@ -166,7 +166,12 @@
}
/** Returns the builder for call chaining. */
- public Builder setUtcTime(TimestampedValue<Long> utcTime) {
+ public Builder setUtcTime(@Nullable TimestampedValue<Long> utcTime) {
+ if (utcTime != null) {
+ // utcTime can be null, but the value it holds cannot.
+ Objects.requireNonNull(utcTime.getValue());
+ }
+
mUtcTime = utcTime;
return this;
}
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 749a011..92e1b30 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -1041,8 +1041,11 @@
/**
* Inform usage stats that the carrier privileged apps access rules have changed.
+ * <p> The caller must have {@link android.Manifest.permission#BIND_CARRIER_SERVICES} </p>
* @hide
*/
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.BIND_CARRIER_SERVICES)
public void onCarrierPrivilegedAppsChanged() {
try {
mService.onCarrierPrivilegedAppsChanged();
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 8ed61b6..64df0e8 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -17,6 +17,7 @@
package android.bluetooth;
import android.Manifest;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -32,6 +33,8 @@
import android.os.RemoteException;
import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
@@ -154,13 +157,22 @@
*/
public static final int STATE_NOT_PLAYING = 11;
+ /** @hide */
+ @IntDef(prefix = "OPTIONAL_CODECS_", value = {
+ OPTIONAL_CODECS_SUPPORT_UNKNOWN,
+ OPTIONAL_CODECS_NOT_SUPPORTED,
+ OPTIONAL_CODECS_SUPPORTED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface OptionalCodecsSupportStatus {}
+
/**
* We don't have a stored preference for whether or not the given A2DP sink device supports
* optional codecs.
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1;
/**
@@ -168,7 +180,7 @@
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0;
/**
@@ -176,16 +188,25 @@
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int OPTIONAL_CODECS_SUPPORTED = 1;
+ /** @hide */
+ @IntDef(prefix = "OPTIONAL_CODECS_PREF_", value = {
+ OPTIONAL_CODECS_PREF_UNKNOWN,
+ OPTIONAL_CODECS_PREF_DISABLED,
+ OPTIONAL_CODECS_PREF_ENABLED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface OptionalCodecsPreferenceStatus {}
+
/**
- * We don't have a stored preference for whether optional codecs should be enabled or disabled
- * for the given A2DP device.
+ * We don't have a stored preference for whether optional codecs should be enabled or
+ * disabled for the given A2DP device.
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1;
/**
@@ -193,7 +214,7 @@
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int OPTIONAL_CODECS_PREF_DISABLED = 0;
/**
@@ -201,7 +222,7 @@
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int OPTIONAL_CODECS_PREF_ENABLED = 1;
private BluetoothAdapter mAdapter;
@@ -248,13 +269,12 @@
* the state. Users can get the connection state of the profile
* from this intent.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- * permission.
*
* @param device Remote Bluetooth Device
* @return false on immediate error, true otherwise
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
@UnsupportedAppUsage
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
@@ -289,13 +309,12 @@
* {@link #STATE_DISCONNECTING} can be used to distinguish between the
* two scenarios.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- * permission.
*
* @param device Remote Bluetooth Device
* @return false on immediate error, true otherwise
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
@@ -384,14 +403,12 @@
* {@link #ACTION_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
* with the active device.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- * permission.
- *
* @param device the remote Bluetooth device. Could be null to clear
* the active device and stop streaming audio to a Bluetooth device.
* @return false on immediate error, true otherwise
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
@UnsupportedAppUsage
public boolean setActiveDevice(@Nullable BluetoothDevice device) {
if (DBG) log("setActiveDevice(" + device + ")");
@@ -412,16 +429,13 @@
/**
* Get the connected device that is active.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
- * permission.
- *
* @return the connected device that is active or null if no device
* is active
* @hide
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @SystemApi
@Nullable
- @UnsupportedAppUsage
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public BluetoothDevice getActiveDevice() {
if (VDBG) log("getActiveDevice()");
try {
@@ -441,7 +455,7 @@
* Set priority of the profile
*
* <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
+ * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF}
*
* @param device Paired bluetooth device
* @param priority
@@ -626,8 +640,10 @@
* @return the current codec status
* @hide
*/
- @UnsupportedAppUsage
- public @Nullable BluetoothCodecStatus getCodecStatus(BluetoothDevice device) {
+ @SystemApi
+ @Nullable
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public BluetoothCodecStatus getCodecStatus(@Nullable BluetoothDevice device) {
if (DBG) Log.d(TAG, "getCodecStatus(" + device + ")");
try {
final IBluetoothA2dp service = getService();
@@ -652,9 +668,10 @@
* @param codecConfig the codec configuration preference
* @hide
*/
- @UnsupportedAppUsage
- public void setCodecConfigPreference(BluetoothDevice device,
- BluetoothCodecConfig codecConfig) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void setCodecConfigPreference(@Nullable BluetoothDevice device,
+ @Nullable BluetoothCodecConfig codecConfig) {
if (DBG) Log.d(TAG, "setCodecConfigPreference(" + device + ")");
try {
final IBluetoothA2dp service = getService();
@@ -676,8 +693,9 @@
* active A2DP Bluetooth device.
* @hide
*/
- @UnsupportedAppUsage
- public void enableOptionalCodecs(BluetoothDevice device) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void enableOptionalCodecs(@Nullable BluetoothDevice device) {
if (DBG) Log.d(TAG, "enableOptionalCodecs(" + device + ")");
enableDisableOptionalCodecs(device, true);
}
@@ -689,8 +707,9 @@
* active A2DP Bluetooth device.
* @hide
*/
- @UnsupportedAppUsage
- public void disableOptionalCodecs(BluetoothDevice device) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void disableOptionalCodecs(@Nullable BluetoothDevice device) {
if (DBG) Log.d(TAG, "disableOptionalCodecs(" + device + ")");
enableDisableOptionalCodecs(device, false);
}
@@ -728,8 +747,10 @@
* OPTIONAL_CODECS_SUPPORTED.
* @hide
*/
- @UnsupportedAppUsage
- public int supportsOptionalCodecs(BluetoothDevice device) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ @OptionalCodecsSupportStatus
+ public int supportsOptionalCodecs(@Nullable BluetoothDevice device) {
try {
final IBluetoothA2dp service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
@@ -738,7 +759,7 @@
if (service == null) Log.w(TAG, "Proxy not attached to service");
return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
} catch (RemoteException e) {
- Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
+ Log.e(TAG, "Error talking to BT service in supportsOptionalCodecs()", e);
return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
}
}
@@ -751,8 +772,10 @@
* OPTIONAL_CODECS_PREF_DISABLED.
* @hide
*/
- @UnsupportedAppUsage
- public int getOptionalCodecsEnabled(BluetoothDevice device) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ @OptionalCodecsPreferenceStatus
+ public int getOptionalCodecsEnabled(@Nullable BluetoothDevice device) {
try {
final IBluetoothA2dp service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
@@ -761,7 +784,7 @@
if (service == null) Log.w(TAG, "Proxy not attached to service");
return OPTIONAL_CODECS_PREF_UNKNOWN;
} catch (RemoteException e) {
- Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
+ Log.e(TAG, "Error talking to BT service in getOptionalCodecsEnabled()", e);
return OPTIONAL_CODECS_PREF_UNKNOWN;
}
}
@@ -775,8 +798,10 @@
* OPTIONAL_CODECS_PREF_DISABLED.
* @hide
*/
- @UnsupportedAppUsage
- public void setOptionalCodecsEnabled(BluetoothDevice device, int value) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void setOptionalCodecsEnabled(@Nullable BluetoothDevice device,
+ @OptionalCodecsPreferenceStatus int value) {
try {
if (value != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN
&& value != BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index c17834a..cf33676 100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -320,7 +320,7 @@
* Set priority of the profile
*
* <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
+ * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF}
*
* @param device Paired bluetooth device
* @param priority
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 9b5280d..291d1d9 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -847,7 +847,8 @@
}
synchronized (mLock) {
if (sBluetoothLeScanner == null) {
- sBluetoothLeScanner = new BluetoothLeScanner(mManagerService);
+ sBluetoothLeScanner = new BluetoothLeScanner(mManagerService, getOpPackageName(),
+ getFeatureId());
}
}
return sBluetoothLeScanner;
@@ -862,18 +863,7 @@
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
public boolean isEnabled() {
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.isEnabled();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
-
- return false;
+ return getState() == BluetoothAdapter.STATE_ON;
}
/**
@@ -1648,6 +1638,15 @@
return ActivityThread.currentOpPackageName();
}
+ private String getFeatureId() {
+ // Workaround for legacy API for getting a BluetoothAdapter not
+ // passing a context
+ if (mContext != null) {
+ return null;
+ }
+ return null;
+ }
+
/**
* Start the remote device discovery process.
* <p>The discovery process usually involves an inquiry scan of about 12
@@ -1685,7 +1684,7 @@
try {
mServiceLock.readLock().lock();
if (mService != null) {
- return mService.startDiscovery(getOpPackageName());
+ return mService.startDiscovery(getOpPackageName(), getFeatureId());
}
} catch (RemoteException e) {
Log.e(TAG, "", e);
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
index 36f3a1e..08d0797 100644
--- a/core/java/android/bluetooth/BluetoothCodecConfig.java
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.java
@@ -16,10 +16,15 @@
package android.bluetooth;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
@@ -29,78 +34,131 @@
*
* {@hide}
*/
+@SystemApi
public final class BluetoothCodecConfig implements Parcelable {
// Add an entry for each source codec here.
// NOTE: The values should be same as those listed in the following file:
// hardware/libhardware/include/hardware/bt_av.h
- @UnsupportedAppUsage
+
+ /** @hide */
+ @IntDef(prefix = "SOURCE_CODEC_TYPE_", value = {
+ SOURCE_CODEC_TYPE_SBC,
+ SOURCE_CODEC_TYPE_AAC,
+ SOURCE_CODEC_TYPE_APTX,
+ SOURCE_CODEC_TYPE_APTX_HD,
+ SOURCE_CODEC_TYPE_LDAC,
+ SOURCE_CODEC_TYPE_MAX,
+ SOURCE_CODEC_TYPE_INVALID
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SourceCodecType {}
+
public static final int SOURCE_CODEC_TYPE_SBC = 0;
- @UnsupportedAppUsage
+
public static final int SOURCE_CODEC_TYPE_AAC = 1;
- @UnsupportedAppUsage
+
public static final int SOURCE_CODEC_TYPE_APTX = 2;
- @UnsupportedAppUsage
+
public static final int SOURCE_CODEC_TYPE_APTX_HD = 3;
- @UnsupportedAppUsage
+
public static final int SOURCE_CODEC_TYPE_LDAC = 4;
- @UnsupportedAppUsage
+
public static final int SOURCE_CODEC_TYPE_MAX = 5;
- @UnsupportedAppUsage
+
public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
- @UnsupportedAppUsage
+ /** @hide */
+ @IntDef(prefix = "CODEC_PRIORITY_", value = {
+ CODEC_PRIORITY_DISABLED,
+ CODEC_PRIORITY_DEFAULT,
+ CODEC_PRIORITY_HIGHEST
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CodecPriority {}
+
public static final int CODEC_PRIORITY_DISABLED = -1;
- @UnsupportedAppUsage
+
public static final int CODEC_PRIORITY_DEFAULT = 0;
- @UnsupportedAppUsage
+
public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000;
- @UnsupportedAppUsage
+
+ /** @hide */
+ @IntDef(prefix = "SAMPLE_RATE_", value = {
+ SAMPLE_RATE_NONE,
+ SAMPLE_RATE_44100,
+ SAMPLE_RATE_48000,
+ SAMPLE_RATE_88200,
+ SAMPLE_RATE_96000,
+ SAMPLE_RATE_176400,
+ SAMPLE_RATE_192000
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SampleRate {}
+
public static final int SAMPLE_RATE_NONE = 0;
- @UnsupportedAppUsage
+
public static final int SAMPLE_RATE_44100 = 0x1 << 0;
- @UnsupportedAppUsage
+
public static final int SAMPLE_RATE_48000 = 0x1 << 1;
- @UnsupportedAppUsage
+
public static final int SAMPLE_RATE_88200 = 0x1 << 2;
- @UnsupportedAppUsage
+
public static final int SAMPLE_RATE_96000 = 0x1 << 3;
- @UnsupportedAppUsage
+
public static final int SAMPLE_RATE_176400 = 0x1 << 4;
- @UnsupportedAppUsage
+
public static final int SAMPLE_RATE_192000 = 0x1 << 5;
- @UnsupportedAppUsage
+
+ /** @hide */
+ @IntDef(prefix = "BITS_PER_SAMPLE_", value = {
+ BITS_PER_SAMPLE_NONE,
+ BITS_PER_SAMPLE_16,
+ BITS_PER_SAMPLE_24,
+ BITS_PER_SAMPLE_32
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface BitsPerSample {}
+
public static final int BITS_PER_SAMPLE_NONE = 0;
- @UnsupportedAppUsage
+
public static final int BITS_PER_SAMPLE_16 = 0x1 << 0;
- @UnsupportedAppUsage
+
public static final int BITS_PER_SAMPLE_24 = 0x1 << 1;
- @UnsupportedAppUsage
+
public static final int BITS_PER_SAMPLE_32 = 0x1 << 2;
- @UnsupportedAppUsage
+
+ /** @hide */
+ @IntDef(prefix = "CHANNEL_MODE_", value = {
+ CHANNEL_MODE_NONE,
+ CHANNEL_MODE_MONO,
+ CHANNEL_MODE_STEREO
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ChannelMode {}
+
public static final int CHANNEL_MODE_NONE = 0;
- @UnsupportedAppUsage
+
public static final int CHANNEL_MODE_MONO = 0x1 << 0;
- @UnsupportedAppUsage
+
public static final int CHANNEL_MODE_STEREO = 0x1 << 1;
- private final int mCodecType;
- private int mCodecPriority;
- private final int mSampleRate;
- private final int mBitsPerSample;
- private final int mChannelMode;
+ private final @SourceCodecType int mCodecType;
+ private @CodecPriority int mCodecPriority;
+ private final @SampleRate int mSampleRate;
+ private final @BitsPerSample int mBitsPerSample;
+ private final @ChannelMode int mChannelMode;
private final long mCodecSpecific1;
private final long mCodecSpecific2;
private final long mCodecSpecific3;
private final long mCodecSpecific4;
- @UnsupportedAppUsage
- public BluetoothCodecConfig(int codecType, int codecPriority,
- int sampleRate, int bitsPerSample,
- int channelMode, long codecSpecific1,
+ public BluetoothCodecConfig(@SourceCodecType int codecType, @CodecPriority int codecPriority,
+ @SampleRate int sampleRate, @BitsPerSample int bitsPerSample,
+ @ChannelMode int channelMode, long codecSpecific1,
long codecSpecific2, long codecSpecific3,
long codecSpecific4) {
mCodecType = codecType;
@@ -114,8 +172,7 @@
mCodecSpecific4 = codecSpecific4;
}
- @UnsupportedAppUsage
- public BluetoothCodecConfig(int codecType) {
+ public BluetoothCodecConfig(@SourceCodecType int codecType) {
mCodecType = codecType;
mCodecPriority = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT;
mSampleRate = BluetoothCodecConfig.SAMPLE_RATE_NONE;
@@ -144,6 +201,12 @@
return false;
}
+ /**
+ * Returns a hash based on the config values
+ *
+ * @return a hash based on the config values
+ * @hide
+ */
@Override
public int hashCode() {
return Objects.hash(mCodecType, mCodecPriority, mSampleRate,
@@ -155,6 +218,7 @@
* Checks whether the object contains valid codec configuration.
*
* @return true if the object contains valid codec configuration, otherwise false.
+ * @hide
*/
public boolean isValid() {
return (mSampleRate != SAMPLE_RATE_NONE)
@@ -242,6 +306,12 @@
+ ",mCodecSpecific4:" + mCodecSpecific4 + "}";
}
+ /**
+ * Always returns 0
+ *
+ * @return 0
+ * @hide
+ */
@Override
public int describeContents() {
return 0;
@@ -271,6 +341,14 @@
}
};
+ /**
+ * Flattens the object to a parcel
+ *
+ * @param out The Parcel in which the object should be written.
+ * @param flags Additional flags about how the object should be written.
+ *
+ * @hide
+ */
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mCodecType);
@@ -289,7 +367,7 @@
*
* @return the codec name
*/
- public String getCodecName() {
+ public @NonNull String getCodecName() {
switch (mCodecType) {
case SOURCE_CODEC_TYPE_SBC:
return "SBC";
@@ -315,8 +393,7 @@
*
* @return the codec type
*/
- @UnsupportedAppUsage
- public int getCodecType() {
+ public @SourceCodecType int getCodecType() {
return mCodecType;
}
@@ -336,8 +413,7 @@
*
* @return the codec priority
*/
- @UnsupportedAppUsage
- public int getCodecPriority() {
+ public @CodecPriority int getCodecPriority() {
return mCodecPriority;
}
@@ -347,9 +423,10 @@
* means higher priority. If 0, reset to default.
*
* @param codecPriority the codec priority
+ * @hide
*/
@UnsupportedAppUsage
- public void setCodecPriority(int codecPriority) {
+ public void setCodecPriority(@CodecPriority int codecPriority) {
mCodecPriority = codecPriority;
}
@@ -366,8 +443,7 @@
*
* @return the codec sample rate
*/
- @UnsupportedAppUsage
- public int getSampleRate() {
+ public @SampleRate int getSampleRate() {
return mSampleRate;
}
@@ -381,8 +457,7 @@
*
* @return the codec bits per sample
*/
- @UnsupportedAppUsage
- public int getBitsPerSample() {
+ public @BitsPerSample int getBitsPerSample() {
return mBitsPerSample;
}
@@ -394,9 +469,10 @@
* {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_STEREO}
*
* @return the codec channel mode
+ * @hide
*/
@UnsupportedAppUsage
- public int getChannelMode() {
+ public @ChannelMode int getChannelMode() {
return mChannelMode;
}
@@ -405,7 +481,6 @@
*
* @return a codec specific value1.
*/
- @UnsupportedAppUsage
public long getCodecSpecific1() {
return mCodecSpecific1;
}
@@ -414,6 +489,7 @@
* Gets a codec specific value2.
*
* @return a codec specific value2
+ * @hide
*/
@UnsupportedAppUsage
public long getCodecSpecific2() {
@@ -424,6 +500,7 @@
* Gets a codec specific value3.
*
* @return a codec specific value3
+ * @hide
*/
@UnsupportedAppUsage
public long getCodecSpecific3() {
@@ -434,6 +511,7 @@
* Gets a codec specific value4.
*
* @return a codec specific value4
+ * @hide
*/
@UnsupportedAppUsage
public long getCodecSpecific4() {
@@ -445,6 +523,7 @@
*
* @param valueSet the value set presented by a bitmask
* @return true if the valueSet contains zero or single bit, otherwise false.
+ * @hide
*/
private static boolean hasSingleBit(int valueSet) {
return (valueSet == 0 || (valueSet & (valueSet - 1)) == 0);
@@ -454,6 +533,7 @@
* Checks whether the object contains none or single sample rate.
*
* @return true if the object contains none or single sample rate, otherwise false.
+ * @hide
*/
public boolean hasSingleSampleRate() {
return hasSingleBit(mSampleRate);
@@ -463,6 +543,7 @@
* Checks whether the object contains none or single bits per sample.
*
* @return true if the object contains none or single bits per sample, otherwise false.
+ * @hide
*/
public boolean hasSingleBitsPerSample() {
return hasSingleBit(mBitsPerSample);
@@ -472,6 +553,7 @@
* Checks whether the object contains none or single channel mode.
*
* @return true if the object contains none or single channel mode, otherwise false.
+ * @hide
*/
public boolean hasSingleChannelMode() {
return hasSingleBit(mChannelMode);
@@ -482,6 +564,7 @@
*
* @param other the codec config to compare against
* @return true if the audio feeding parameters are same, otherwise false
+ * @hide
*/
public boolean sameAudioFeedingParameters(BluetoothCodecConfig other) {
return (other != null && other.mSampleRate == mSampleRate
@@ -495,6 +578,7 @@
*
* @param other the codec config to compare against
* @return true if the audio feeding parameters are similar, otherwise false.
+ * @hide
*/
public boolean similarCodecFeedingParameters(BluetoothCodecConfig other) {
if (other == null || mCodecType != other.mCodecType) {
@@ -526,6 +610,7 @@
*
* @param other the codec config to compare against
* @return true if the codec specific parameters are the same, otherwise false.
+ * @hide
*/
public boolean sameCodecSpecificParameters(BluetoothCodecConfig other) {
if (other == null && mCodecType != other.mCodecType) {
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java
index 58a764a..b6e7739 100644
--- a/core/java/android/bluetooth/BluetoothCodecStatus.java
+++ b/core/java/android/bluetooth/BluetoothCodecStatus.java
@@ -17,7 +17,7 @@
package android.bluetooth;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,6 +32,7 @@
*
* {@hide}
*/
+@SystemApi
public final class BluetoothCodecStatus implements Parcelable {
/**
* Extra for the codec configuration intents of the individual profiles.
@@ -39,17 +40,16 @@
* This extra represents the current codec status of the A2DP
* profile.
*/
- @UnsupportedAppUsage
public static final String EXTRA_CODEC_STATUS =
- "android.bluetooth.codec.extra.CODEC_STATUS";
+ "android.bluetooth.extra.CODEC_STATUS";
private final @Nullable BluetoothCodecConfig mCodecConfig;
private final BluetoothCodecConfig[] mCodecsLocalCapabilities;
private final BluetoothCodecConfig[] mCodecsSelectableCapabilities;
- public BluetoothCodecStatus(BluetoothCodecConfig codecConfig,
- BluetoothCodecConfig[] codecsLocalCapabilities,
- BluetoothCodecConfig[] codecsSelectableCapabilities) {
+ public BluetoothCodecStatus(@Nullable BluetoothCodecConfig codecConfig,
+ @Nullable BluetoothCodecConfig[] codecsLocalCapabilities,
+ @Nullable BluetoothCodecConfig[] codecsSelectableCapabilities) {
mCodecConfig = codecConfig;
mCodecsLocalCapabilities = codecsLocalCapabilities;
mCodecsSelectableCapabilities = codecsSelectableCapabilities;
@@ -74,6 +74,7 @@
* @param c1 the first array of capabilities to compare
* @param c2 the second array of capabilities to compare
* @return true if both arrays contain same capabilities
+ * @hide
*/
public static boolean sameCapabilities(BluetoothCodecConfig[] c1,
BluetoothCodecConfig[] c2) {
@@ -95,6 +96,7 @@
*
* @param codecConfig the codec config to compare against
* @return true if the codec config matches, otherwise false
+ * @hide
*/
public boolean isCodecConfigSelectable(BluetoothCodecConfig codecConfig) {
if (codecConfig == null || !codecConfig.hasSingleSampleRate()
@@ -125,7 +127,12 @@
return false;
}
-
+ /**
+ * Returns a hash based on the codec config and local capabilities
+ *
+ * @return a hash based on the config values
+ * @hide
+ */
@Override
public int hashCode() {
return Objects.hash(mCodecConfig, mCodecsLocalCapabilities,
@@ -140,6 +147,12 @@
+ "}";
}
+ /**
+ * Always returns 0
+ *
+ * @return 0
+ * @hide
+ */
@Override
public int describeContents() {
return 0;
@@ -165,6 +178,14 @@
}
};
+ /**
+ * Flattens the object to a parcel
+ *
+ * @param out The Parcel in which the object should be written.
+ * @param flags Additional flags about how the object should be written.
+ *
+ * @hide
+ */
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeTypedObject(mCodecConfig, 0);
@@ -177,7 +198,6 @@
*
* @return the current codec configuration
*/
- @UnsupportedAppUsage
public @Nullable BluetoothCodecConfig getCodecConfig() {
return mCodecConfig;
}
@@ -187,8 +207,7 @@
*
* @return an array with the codecs local capabilities
*/
- @UnsupportedAppUsage
- public BluetoothCodecConfig[] getCodecsLocalCapabilities() {
+ public @Nullable BluetoothCodecConfig[] getCodecsLocalCapabilities() {
return mCodecsLocalCapabilities;
}
@@ -197,8 +216,7 @@
*
* @return an array with the codecs selectable capabilities
*/
- @UnsupportedAppUsage
- public BluetoothCodecConfig[] getCodecsSelectableCapabilities() {
+ public @Nullable BluetoothCodecConfig[] getCodecsSelectableCapabilities() {
return mCodecsSelectableCapabilities;
}
}
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 0be3eca..323c7d1 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -17,6 +17,7 @@
package android.bluetooth;
import android.Manifest;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -33,8 +34,12 @@
import android.os.RemoteException;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.io.IOException;
import java.io.UnsupportedEncodingException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.UUID;
/**
@@ -771,6 +776,13 @@
@UnsupportedAppUsage
public static final String EXTRA_SDP_SEARCH_STATUS =
"android.bluetooth.device.extra.SDP_SEARCH_STATUS";
+
+ /** @hide */
+ @IntDef(prefix = "ACCESS_", value = {ACCESS_UNKNOWN,
+ ACCESS_ALLOWED, ACCESS_REJECTED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AccessPermission{}
+
/**
* For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission},
* {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}.
@@ -1096,15 +1108,14 @@
/**
* Get the most recent identified battery level of this Bluetooth device
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
*
* @return Battery level in percents from 0 to 100, or {@link #BATTERY_LEVEL_UNKNOWN} if
* Bluetooth is disabled, or device is disconnected, or does not have any battery reporting
* service, or return value is invalid
* @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.BLUETOOTH)
- @UnsupportedAppUsage
public int getBatteryLevel() {
final IBluetooth service = sService;
if (service == null) {
@@ -1131,20 +1142,7 @@
*/
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean createBond() {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
- return false;
- }
- try {
- Log.i(TAG, "createBond() for device " + getAddress()
- + " called by pid: " + Process.myPid()
- + " tid: " + Process.myTid());
- return service.createBond(this, TRANSPORT_AUTO);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
+ return createBond(TRANSPORT_AUTO);
}
/**
@@ -1165,23 +1163,7 @@
*/
@UnsupportedAppUsage
public boolean createBond(int transport) {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
- return false;
- }
- if (TRANSPORT_AUTO > transport || transport > TRANSPORT_LE) {
- throw new IllegalArgumentException(transport + " is not a valid Bluetooth transport");
- }
- try {
- Log.i(TAG, "createBond() for device " + getAddress()
- + " called by pid: " + Process.myPid()
- + " tid: " + Process.myTid());
- return service.createBond(this, transport);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
+ return createBondOutOfBand(transport, null);
}
/**
@@ -1209,15 +1191,22 @@
return false;
}
try {
- return service.createBondOutOfBand(this, transport, oobData);
+ return service.createBond(this, transport, oobData);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
return false;
}
- /** @hide */
- @UnsupportedAppUsage
+ /**
+ * Gets whether bonding was initiated locally
+ *
+ * @return true if bonding is initiated locally, false otherwise
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public boolean isBondingInitiatedLocally() {
final IBluetooth service = sService;
if (service == null) {
@@ -1509,15 +1498,20 @@
return false;
}
- /** @hide */
- @UnsupportedAppUsage
- public boolean setPasskey(int passkey) {
- //TODO(BT)
- /*
- try {
- return sService.setPasskey(this, true, 4, passkey);
- } catch (RemoteException e) {Log.e(TAG, "", e);}*/
- return false;
+ /**
+ * Set the pin during pairing when the pairing method is {@link #PAIRING_VARIANT_PIN}
+ *
+ * @return true pin has been set false for error
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ public boolean setPin(@Nullable String pin) {
+ byte[] pinBytes = convertPinToBytes(pin);
+ if (pinBytes == null) {
+ return false;
+ }
+ return setPin(pinBytes);
}
/**
@@ -1540,22 +1534,18 @@
return false;
}
- /** @hide */
- public boolean setRemoteOutOfBandData() {
- // TODO(BT)
- /*
- try {
- return sService.setRemoteOutOfBandData(this);
- } catch (RemoteException e) {Log.e(TAG, "", e);}*/
- return false;
- }
-
- /** @hide */
- @UnsupportedAppUsage
- public boolean cancelPairingUserInput() {
+ /**
+ * Cancels pairing to this device
+ *
+ * @return true if pairing cancelled successfully, false otherwise
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean cancelPairing() {
final IBluetooth service = sService;
if (service == null) {
- Log.e(TAG, "BT not enabled. Cannot create pairing user input");
+ Log.e(TAG, "BT not enabled. Cannot cancel pairing");
return false;
}
try {
@@ -1566,17 +1556,6 @@
return false;
}
- /** @hide */
- @UnsupportedAppUsage
- public boolean isBluetoothDock() {
- // TODO(BT)
- /*
- try {
- return sService.isBluetoothDock(this);
- } catch (RemoteException e) {Log.e(TAG, "", e);}*/
- return false;
- }
-
boolean isBluetoothEnabled() {
boolean ret = false;
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -1587,13 +1566,14 @@
}
/**
- * Requires {@link android.Manifest.permission#BLUETOOTH}.
+ * Gets whether the phonebook access is allowed for this bluetooth device
*
* @return Whether the phonebook access is allowed to this device. Can be {@link
* #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public int getPhonebookAccessPermission() {
final IBluetooth service = sService;
if (service == null) {
@@ -1696,14 +1676,14 @@
}
/**
- * Requires {@link android.Manifest.permission#BLUETOOTH}.
+ * Gets whether message access is allowed to this bluetooth device
*
- * @return Whether the message access is allowed to this device. Can be {@link #ACCESS_UNKNOWN},
- * {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}.
+ * @return Whether the message access is allowed to this device.
* @hide
*/
- @UnsupportedAppUsage
- public int getMessageAccessPermission() {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public @AccessPermission int getMessageAccessPermission() {
final IBluetooth service = sService;
if (service == null) {
return ACCESS_UNKNOWN;
@@ -1718,15 +1698,18 @@
/**
* Sets whether the message access is allowed to this device.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
*
- * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link
- * #ACCESS_REJECTED}.
+ * @param value is the value we are setting the message access permission to
* @return Whether the value has been successfully set.
* @hide
*/
- @UnsupportedAppUsage
- public boolean setMessageAccessPermission(int value) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public boolean setMessageAccessPermission(@AccessPermission int value) {
+ // Validates param value is one of the accepted constants
+ if (value != ACCESS_ALLOWED && value != ACCESS_REJECTED && value != ACCESS_UNKNOWN) {
+ throw new IllegalArgumentException(value + "is not a valid AccessPermission value");
+ }
final IBluetooth service = sService;
if (service == null) {
return false;
@@ -1740,13 +1723,14 @@
}
/**
- * Requires {@link android.Manifest.permission#BLUETOOTH}.
+ * Gets whether sim access is allowed for this bluetooth device
*
- * @return Whether the Sim access is allowed to this device. Can be {@link #ACCESS_UNKNOWN},
- * {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}.
+ * @return Whether the Sim access is allowed to this device.
* @hide
*/
- public int getSimAccessPermission() {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public @AccessPermission int getSimAccessPermission() {
final IBluetooth service = sService;
if (service == null) {
return ACCESS_UNKNOWN;
@@ -1761,14 +1745,14 @@
/**
* Sets whether the Sim access is allowed to this device.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
*
* @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link
* #ACCESS_REJECTED}.
* @return Whether the value has been successfully set.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
public boolean setSimAccessPermission(int value) {
final IBluetooth service = sService;
if (service == null) {
@@ -1999,7 +1983,7 @@
* @return the pin code as a UTF-8 byte array, or null if it is an invalid Bluetooth pin.
* @hide
*/
- @UnsupportedAppUsage
+ @VisibleForTesting
public static byte[] convertPinToBytes(String pin) {
if (pin == null) {
return null;
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index ead8429..b4521c6 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -335,9 +335,9 @@
* is not active, it will be null on that position. Returns empty list on error.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
@RequiresPermission(Manifest.permission.BLUETOOTH)
- public List<BluetoothDevice> getActiveDevices() {
+ public @NonNull List<BluetoothDevice> getActiveDevices() {
if (VDBG) log("getActiveDevices()");
final IBluetoothHearingAid service = getService();
try {
@@ -559,8 +559,9 @@
* @return the CustomerId of the device
* @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.BLUETOOTH)
- public long getHiSyncId(BluetoothDevice device) {
+ public long getHiSyncId(@Nullable BluetoothDevice device) {
if (VDBG) {
log("getCustomerId(" + device + ")");
}
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index adedff3..cff4c2d 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -22,7 +22,9 @@
import android.annotation.SystemService;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.os.IBinder;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.util.Log;
import java.util.ArrayList;
@@ -60,22 +62,34 @@
* @hide
*/
public BluetoothManager(Context context) {
- context = context.getApplicationContext();
- if (context == null) {
- throw new IllegalArgumentException(
- "context not associated with any application (using a mock context?)");
+ if (null == null) {
+ context = context.getApplicationContext();
+ if (context == null) {
+ throw new IllegalArgumentException(
+ "context not associated with any application (using a mock context?)");
+ }
+
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
+ } else {
+ IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE);
+ if (b != null) {
+ mAdapter = new BluetoothAdapter(IBluetoothManager.Stub.asInterface(b));
+ } else {
+ Log.e(TAG, "Bluetooth binder is null");
+ mAdapter = null;
+ }
}
- // Legacy api - getDefaultAdapter does not take in the context
- mAdapter = BluetoothAdapter.getDefaultAdapter();
+
+ // Context is not initialized in constructor
if (mAdapter != null) {
mAdapter.setContext(context);
}
}
/**
- * Get the default BLUETOOTH Adapter for this device.
+ * Get the BLUETOOTH Adapter for this device.
*
- * @return the default BLUETOOTH Adapter
+ * @return the BLUETOOTH Adapter
*/
public BluetoothAdapter getAdapter() {
return mAdapter;
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index ac126ae..9a17346 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -21,7 +21,6 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.app.ActivityThread;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothGatt;
@@ -84,17 +83,25 @@
private BluetoothAdapter mBluetoothAdapter;
private final Map<ScanCallback, BleScanCallbackWrapper> mLeScanClients;
+ private final String mOpPackageName;
+ private final String mFeatureId;
+
/**
* Use {@link BluetoothAdapter#getBluetoothLeScanner()} instead.
*
* @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management.
+ * @param opPackageName The opPackageName of the context this object was created from
+ * @param featureId The featureId of the context this object was created from
* @hide
*/
- public BluetoothLeScanner(IBluetoothManager bluetoothManager) {
+ public BluetoothLeScanner(IBluetoothManager bluetoothManager,
+ @NonNull String opPackageName, @Nullable String featureId) {
mBluetoothManager = bluetoothManager;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mHandler = new Handler(Looper.getMainLooper());
mLeScanClients = new HashMap<ScanCallback, BleScanCallbackWrapper>();
+ mOpPackageName = opPackageName;
+ mFeatureId = featureId;
}
/**
@@ -246,8 +253,8 @@
wrapper.startRegistration();
} else {
try {
- gatt.startScanForIntent(callbackIntent, settings, filters,
- ActivityThread.currentOpPackageName());
+ gatt.startScanForIntent(callbackIntent, settings, filters, mOpPackageName,
+ mFeatureId);
} catch (RemoteException e) {
return ScanCallback.SCAN_FAILED_INTERNAL_ERROR;
}
@@ -288,7 +295,7 @@
IBluetoothGatt gatt;
try {
gatt = mBluetoothManager.getBluetoothGatt();
- gatt.stopScanForIntent(callbackIntent, ActivityThread.currentOpPackageName());
+ gatt.stopScanForIntent(callbackIntent, mOpPackageName);
} catch (RemoteException e) {
}
}
@@ -448,8 +455,7 @@
} else {
mScannerId = scannerId;
mBluetoothGatt.startScan(mScannerId, mSettings, mFilters,
- mResultStorages,
- ActivityThread.currentOpPackageName());
+ mResultStorages, mOpPackageName, mFeatureId);
}
} catch (RemoteException e) {
Log.e(TAG, "fail to start le scan: " + e);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 2a17800..e9a4762 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3995,9 +3995,15 @@
* Broadcast Action: The sim card state has changed.
* For more details see TelephonyIntents.ACTION_SIM_STATE_CHANGED. This is here
* because TelephonyIntents is an internal class.
- * @hide
+ * The intent will have following extras.</p>
+ * <p>
+ * @see #EXTRA_SIM_STATE
+ * @see #EXTRA_SIM_LOCKED_REASON
+ *
* @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED} or
* {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+ *
+ * @hide
*/
@Deprecated
@SystemApi
@@ -4005,6 +4011,170 @@
public static final String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
/**
+ * The extra used with {@link #ACTION_SIM_STATE_CHANGED} for broadcasting SIM STATE.
+ * This will have one of the following intent values.
+ * @see #SIM_STATE_UNKNOWN
+ * @see #SIM_STATE_NOT_READY
+ * @see #SIM_STATE_ABSENT
+ * @see #SIM_STATE_PRESENT
+ * @see #SIM_STATE_CARD_IO_ERROR
+ * @see #SIM_STATE_CARD_RESTRICTED
+ * @see #SIM_STATE_LOCKED
+ * @see #SIM_STATE_READY
+ * @see #SIM_STATE_IMSI
+ * @see #SIM_STATE_LOADED
+ * @hide
+ * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_SIM_STATE = "ss";
+
+ /**
+ * The intent value UNKNOWN represents the SIM state unknown
+ * @hide
+ * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+ */
+ @Deprecated
+ @SystemApi
+ public static final String SIM_STATE_UNKNOWN = "UNKNOWN";
+
+ /**
+ * The intent value NOT_READY means that the SIM is not ready eg. radio is off or powering on
+ * @hide
+ * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+ */
+ @Deprecated
+ @SystemApi
+ public static final String SIM_STATE_NOT_READY = "NOT_READY";
+
+ /**
+ * The intent value ABSENT means the SIM card is missing
+ * @hide
+ * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+ */
+ @Deprecated
+ @SystemApi
+ public static final String SIM_STATE_ABSENT = "ABSENT";
+
+ /**
+ * The intent value PRESENT means the device has a SIM card inserted
+ * @hide
+ * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+ */
+ @Deprecated
+ @SystemApi
+ public static final String SIM_STATE_PRESENT = "PRESENT";
+
+ /**
+ * The intent value CARD_IO_ERROR means for three consecutive times there was SIM IO error
+ * @hide
+ * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+ */
+ @Deprecated
+ @SystemApi
+ static public final String SIM_STATE_CARD_IO_ERROR = "CARD_IO_ERROR";
+
+ /**
+ * The intent value CARD_RESTRICTED means card is present but not usable due to carrier
+ * restrictions
+ * @hide
+ * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+ */
+ @Deprecated
+ @SystemApi
+ static public final String SIM_STATE_CARD_RESTRICTED = "CARD_RESTRICTED";
+
+ /**
+ * The intent value LOCKED means the SIM is locked by PIN or by network
+ * @hide
+ * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+ */
+ @Deprecated
+ @SystemApi
+ public static final String SIM_STATE_LOCKED = "LOCKED";
+
+ /**
+ * The intent value READY means the SIM is ready to be accessed
+ * @hide
+ * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+ */
+ @Deprecated
+ @SystemApi
+ public static final String SIM_STATE_READY = "READY";
+
+ /**
+ * The intent value IMSI means the SIM IMSI is ready in property
+ * @hide
+ * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+ */
+ @Deprecated
+ @SystemApi
+ public static final String SIM_STATE_IMSI = "IMSI";
+
+ /**
+ * The intent value LOADED means all SIM records, including IMSI, are loaded
+ * @hide
+ * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+ */
+ @Deprecated
+ @SystemApi
+ public static final String SIM_STATE_LOADED = "LOADED";
+
+ /**
+ * The extra used with {@link #ACTION_SIM_STATE_CHANGED} for broadcasting SIM STATE.
+ * This extra will have one of the following intent values.
+ * <p>
+ * @see #SIM_LOCKED_ON_PIN
+ * @see #SIM_LOCKED_ON_PUK
+ * @see #SIM_LOCKED_NETWORK
+ * @see #SIM_ABSENT_ON_PERM_DISABLED
+ *
+ * @hide
+ * @deprecated Use {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_SIM_LOCKED_REASON = "reason";
+
+ /**
+ * The intent value PIN means the SIM is locked on PIN1
+ * @hide
+ * @deprecated Use {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+ */
+ @Deprecated
+ @SystemApi
+ public static final String SIM_LOCKED_ON_PIN = "PIN";
+
+ /**
+ * The intent value PUK means the SIM is locked on PUK1
+ * @hide
+ * @deprecated Use {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+ */
+ /* PUK means ICC is locked on PUK1 */
+ @Deprecated
+ @SystemApi
+ public static final String SIM_LOCKED_ON_PUK = "PUK";
+
+ /**
+ * The intent value NETWORK means the SIM is locked on NETWORK PERSONALIZATION
+ * @hide
+ * @deprecated Use {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+ */
+ @Deprecated
+ @SystemApi
+ public static final String SIM_LOCKED_NETWORK = "NETWORK";
+
+ /**
+ * The intent value PERM_DISABLED means SIM is permanently disabled due to puk fails
+ * @hide
+ * @deprecated Use {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+ */
+ @Deprecated
+ @SystemApi
+ public static final String SIM_ABSENT_ON_PERM_DISABLED = "PERM_DISABLED";
+
+ /**
* Broadcast Action: indicate that the phone service state has changed.
* The intent will have the following extra values:</p>
* <p>
diff --git a/core/java/android/content/pm/ParceledListSlice.aidl b/core/java/android/content/pm/ParceledListSlice.aidl
index c02cc6a..5031fba 100644
--- a/core/java/android/content/pm/ParceledListSlice.aidl
+++ b/core/java/android/content/pm/ParceledListSlice.aidl
@@ -16,4 +16,4 @@
package android.content.pm;
-parcelable ParceledListSlice;
+parcelable ParceledListSlice<T>;
diff --git a/core/java/android/net/InterfaceConfiguration.java b/core/java/android/net/InterfaceConfiguration.java
index c9a999c..1ae44e1 100644
--- a/core/java/android/net/InterfaceConfiguration.java
+++ b/core/java/android/net/InterfaceConfiguration.java
@@ -20,8 +20,6 @@
import android.os.Parcel;
import android.os.Parcelable;
-import com.google.android.collect.Sets;
-
import java.util.HashSet;
/**
@@ -32,7 +30,7 @@
public class InterfaceConfiguration implements Parcelable {
private String mHwAddr;
private LinkAddress mAddr;
- private HashSet<String> mFlags = Sets.newHashSet();
+ private HashSet<String> mFlags = new HashSet<>();
// Must be kept in sync with constant in INetd.aidl
private static final String FLAG_UP = "up";
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 4270740..471b23e 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -17,6 +17,7 @@
package android.net;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
@@ -461,6 +462,14 @@
return networkCapabilities.hasTransport(transportType);
}
+ /**
+ * @see Builder#setNetworkSpecifier(NetworkSpecifier)
+ */
+ @Nullable
+ public NetworkSpecifier getNetworkSpecifier() {
+ return networkCapabilities.getNetworkSpecifier();
+ }
+
public String toString() {
return "NetworkRequest [ " + type + " id=" + requestId +
(legacyType != ConnectivityManager.TYPE_NONE ? ", legacyType=" + legacyType : "") +
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 450bfae..1130f1d 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -519,11 +519,12 @@
* @param appDataDir null-ok the data directory of the app.
* @param invokeWith null-ok the command to invoke with.
* @param packageName null-ok the name of the package this process belongs to.
- *
+ * @param disabledCompatChanges null-ok list of disabled compat changes for the process being
+ * started.
* @param zygoteArgs Additional arguments to supply to the zygote process.
* @return An object that describes the result of the attempt to start the process.
* @throws RuntimeException on fatal start failure
- *
+ *
* {@hide}
*/
public static ProcessStartResult start(@NonNull final String processClass,
@@ -538,11 +539,12 @@
@Nullable String appDataDir,
@Nullable String invokeWith,
@Nullable String packageName,
+ @Nullable long[] disabledCompatChanges,
@Nullable String[] zygoteArgs) {
return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
- /*useUsapPool=*/ true, zygoteArgs);
+ /*useUsapPool=*/ true, disabledCompatChanges, zygoteArgs);
}
/** @hide */
@@ -558,11 +560,12 @@
@Nullable String appDataDir,
@Nullable String invokeWith,
@Nullable String packageName,
+ @Nullable long[] disabledCompatChanges,
@Nullable String[] zygoteArgs) {
return WebViewZygote.getProcess().start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
- /*useUsapPool=*/ false, zygoteArgs);
+ /*useUsapPool=*/ false, disabledCompatChanges, zygoteArgs);
}
/**
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index 1456a73..e132c11 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -21,6 +21,7 @@
import com.android.internal.os.Zygote;
+import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
/**
@@ -107,12 +108,15 @@
private static final int MAX_SECTION_NAME_LEN = 127;
// Must be volatile to avoid word tearing.
+ // This is only kept in case any apps get this by reflection but do not
+ // check the return value for null.
@UnsupportedAppUsage
private static volatile long sEnabledTags = TRACE_TAG_NOT_READY;
private static int sZygoteDebugFlags = 0;
@UnsupportedAppUsage
+ @CriticalNative
private static native long nativeGetEnabledTags();
private static native void nativeSetAppTracingAllowed(boolean allowed);
private static native void nativeSetTracingEnabled(boolean allowed);
@@ -128,47 +132,10 @@
@FastNative
private static native void nativeAsyncTraceEnd(long tag, String name, int cookie);
- static {
- // We configure two separate change callbacks, one in Trace.cpp and one here. The
- // native callback reads the tags from the system property, and this callback
- // reads the value that the native code retrieved. It's essential that the native
- // callback executes first.
- //
- // The system provides ordering through a priority level. Callbacks made through
- // SystemProperties.addChangeCallback currently have a negative priority, while
- // our native code is using a priority of zero.
- SystemProperties.addChangeCallback(() -> {
- cacheEnabledTags();
- if ((sZygoteDebugFlags & Zygote.DEBUG_JAVA_DEBUGGABLE) != 0) {
- traceCounter(TRACE_TAG_ALWAYS, "java_debuggable", 1);
- }
- });
- }
-
private Trace() {
}
/**
- * Caches a copy of the enabled-tag bits. The "master" copy is held by the native code,
- * and comes from the PROPERTY_TRACE_TAG_ENABLEFLAGS property.
- * <p>
- * If the native code hasn't yet read the property, we will cause it to do one-time
- * initialization. We don't want to do this during class init, because this class is
- * preloaded, so all apps would be stuck with whatever the zygote saw. (The zygote
- * doesn't see the system-property update broadcasts.)
- * <p>
- * We want to defer initialization until the first use by an app, post-zygote.
- * <p>
- * We're okay if multiple threads call here simultaneously -- the native state is
- * synchronized, and sEnabledTags is volatile (prevents word tearing).
- */
- private static long cacheEnabledTags() {
- long tags = nativeGetEnabledTags();
- sEnabledTags = tags;
- return tags;
- }
-
- /**
* Returns true if a trace tag is enabled.
*
* @param traceTag The trace tag to check.
@@ -178,10 +145,7 @@
*/
@UnsupportedAppUsage
public static boolean isTagEnabled(long traceTag) {
- long tags = sEnabledTags;
- if (tags == TRACE_TAG_NOT_READY) {
- tags = cacheEnabledTags();
- }
+ long tags = nativeGetEnabledTags();
return (tags & traceTag) != 0;
}
@@ -210,10 +174,6 @@
@UnsupportedAppUsage
public static void setAppTracingAllowed(boolean allowed) {
nativeSetAppTracingAllowed(allowed);
-
- // Setting whether app tracing is allowed may change the tags, so we update the cached
- // tags here.
- cacheEnabledTags();
}
/**
@@ -227,10 +187,6 @@
public static void setTracingEnabled(boolean enabled, int debugFlags) {
nativeSetTracingEnabled(enabled);
sZygoteDebugFlags = debugFlags;
-
- // Setting whether tracing is enabled may change the tags, so we update the cached tags
- // here.
- cacheEnabledTags();
}
/**
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 3a55aff..c2d3ecc 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -306,6 +306,8 @@
* @param appDataDir null-ok the data directory of the app.
* @param invokeWith null-ok the command to invoke with.
* @param packageName null-ok the name of the package this process belongs to.
+ * @param disabledCompatChanges null-ok list of disabled compat changes for the process being
+ * started.
* @param zygoteArgs Additional arguments to supply to the zygote process.
*
* @return An object that describes the result of the attempt to start the process.
@@ -323,6 +325,7 @@
@Nullable String invokeWith,
@Nullable String packageName,
boolean useUsapPool,
+ @Nullable long[] disabledCompatChanges,
@Nullable String[] zygoteArgs) {
// TODO (chriswailes): Is there a better place to check this value?
if (fetchUsapPoolEnabledPropWithMinInterval()) {
@@ -333,7 +336,7 @@
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
- packageName, useUsapPool, zygoteArgs);
+ packageName, useUsapPool, disabledCompatChanges, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
@@ -534,6 +537,7 @@
* @param startChildZygote Start a sub-zygote. This creates a new zygote process
* that has its state cloned from this zygote process.
* @param packageName null-ok the name of the package this process belongs to.
+ * @param disabledCompatChanges a list of disabled compat changes for the process being started.
* @param extraArgs Additional arguments to supply to the zygote process.
* @return An object that describes the result of the attempt to start the process.
* @throws ZygoteStartFailedEx if process start failed for any reason
@@ -552,6 +556,7 @@
boolean startChildZygote,
@Nullable String packageName,
boolean useUsapPool,
+ @Nullable long[] disabledCompatChanges,
@Nullable String[] extraArgs)
throws ZygoteStartFailedEx {
ArrayList<String> argsForZygote = new ArrayList<>();
@@ -623,6 +628,21 @@
argsForZygote.add("--package-name=" + packageName);
}
+ if (disabledCompatChanges != null && disabledCompatChanges.length > 0) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("--disabled-compat-changes=");
+
+ final int sz = disabledCompatChanges.length;
+ for (int i = 0; i < sz; i++) {
+ if (i != 0) {
+ sb.append(',');
+ }
+ sb.append(disabledCompatChanges[i]);
+ }
+
+ argsForZygote.add(sb.toString());
+ }
+
argsForZygote.add(processClass);
if (extraArgs != null) {
@@ -1170,7 +1190,8 @@
gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo,
abi, instructionSet, null /* appDataDir */, null /* invokeWith */,
true /* startChildZygote */, null /* packageName */,
- false /* useUsapPool */, extraArgs);
+ false /* useUsapPool */,
+ null /* disabledCompatChanges */, extraArgs);
} catch (ZygoteStartFailedEx ex) {
throw new RuntimeException("Starting child-zygote through Zygote failed", ex);
}
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index ebdde0a..c9123e3 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -25,7 +25,6 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
-import android.app.job.JobService;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -1272,8 +1271,7 @@
* Broadcast action: When SMS-MMS db is being created. If file-based encryption is
* supported, this broadcast indicates creation of the db in credential-encrypted
* storage. A boolean is specified in {@link #EXTRA_IS_INITIAL_CREATE} to indicate if
- * this is the initial create of the db. Requires
- * {@link android.Manifest.permission#READ_SMS} to receive.
+ * this is the initial create of the db.
*
* @see #EXTRA_IS_INITIAL_CREATE
*
@@ -4119,20 +4117,6 @@
public static final String CID = "cid";
/**
- * Message code. <em>OBSOLETE: merged into SERIAL_NUMBER.</em>
- * <P>Type: INTEGER</P>
- * @hide
- */
- public static final String V1_MESSAGE_CODE = "message_code";
-
- /**
- * Message identifier. <em>OBSOLETE: renamed to SERVICE_CATEGORY.</em>
- * <P>Type: INTEGER</P>
- * @hide
- */
- public static final String V1_MESSAGE_IDENTIFIER = "message_id";
-
- /**
* Service category which represents the general topic of the message.
* <p>
* For GSM/UMTS: message identifier (see 3GPP TS 23.041 section 9.4.1.2.2)
@@ -4380,9 +4364,11 @@
* ServiceState provider.
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
- * {@link ServiceState} while your app is running. You can also use a {@link JobService} to
+ * {@link ServiceState} while your app is running.
+ * You can also use a {@link android.app.job.JobService} to
* ensure your app is notified of changes to the {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+ * Note, however, that using a {@link android.app.job.JobService}
+ * does not guarantee timely delivery of
* updates to the {@link Uri}.
*
* @param subscriptionId the subscriptionId to receive updates on
@@ -4399,9 +4385,11 @@
* ServiceState provider.
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
- * {@link ServiceState} while your app is running. You can also use a {@link JobService} to
+ * {@link ServiceState} while your app is running. You can also use a
+ * {@link android.app.job.JobService} to
* ensure your app is notified of changes to the {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+ * Note, however, that using a {@link android.app.job.JobService}
+ * does not guarantee timely delivery of
* updates to the {@link Uri}.
*
* @param subscriptionId the subscriptionId to receive updates on
@@ -4479,7 +4467,7 @@
/**
* The current registered voice network operator name in long alphanumeric format.
* <p>
- * This is the same as {@link ServiceState#getVoiceOperatorAlphaLong()}.
+ * This is the same as {@link ServiceState#getOperatorAlphaLong()}.
* @hide
*/
public static final String VOICE_OPERATOR_ALPHA_LONG = "voice_operator_alpha_long";
@@ -4490,12 +4478,11 @@
* In GSM/UMTS, short format can be up to 8 characters long. The current registered voice
* network operator name in long alphanumeric format.
* <p>
- * This is the same as {@link ServiceState#getVoiceOperatorAlphaShort()}.
+ * This is the same as {@link ServiceState#getOperatorAlphaShort()}.
* @hide
*/
public static final String VOICE_OPERATOR_ALPHA_SHORT = "voice_operator_alpha_short";
-
/**
* The current registered operator numeric id.
* <p>
@@ -4509,7 +4496,7 @@
/**
* The current registered data network operator name in long alphanumeric format.
* <p>
- * This is the same as {@link ServiceState#getDataOperatorAlphaLong()}.
+ * This is the same as {@link ServiceState#getOperatorAlphaLong()}.
* @hide
*/
public static final String DATA_OPERATOR_ALPHA_LONG = "data_operator_alpha_long";
@@ -4517,7 +4504,7 @@
/**
* The current registered data network operator name in short alphanumeric format.
* <p>
- * This is the same as {@link ServiceState#getDataOperatorAlphaShort()}.
+ * This is the same as {@link ServiceState#getOperatorAlphaShort()}.
* @hide
*/
public static final String DATA_OPERATOR_ALPHA_SHORT = "data_operator_alpha_short";
@@ -4525,7 +4512,7 @@
/**
* The current registered data network operator numeric id.
* <p>
- * This is the same as {@link ServiceState#getDataOperatorNumeric()}.
+ * This is the same as {@link ServiceState#getOperatorNumeric()}.
* @hide
*/
public static final String DATA_OPERATOR_NUMERIC = "data_operator_numeric";
@@ -4656,10 +4643,11 @@
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
* carrier identity {@link TelephonyManager#getSimCarrierId()}
- * while your app is running. You can also use a {@link JobService} to ensure your app
+ * while your app is running. You can also use a {@link android.app.job.JobService}
+ * to ensure your app
* is notified of changes to the {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
- * updates to the {@link Uri}.
+ * Note, however, that using a {@link android.app.job.JobService} does not guarantee
+ * timely delivery of updates to the {@link Uri}.
*
* @param subscriptionId the subscriptionId to receive updates on
* @return the Uri used to observe carrier identity changes
@@ -4677,10 +4665,11 @@
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
* specific carrier identity {@link TelephonyManager#getSimSpecificCarrierId()}
- * while your app is running. You can also use a {@link JobService} to ensure your app
+ * while your app is running. You can also use a {@link android.app.job.JobService}
+ * to ensure your app
* is notified of changes to the {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
- * updates to the {@link Uri}.
+ * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+ * delivery of updates to the {@link Uri}.
*
* @param subscriptionId the subscriptionId to receive updates on
* @return the Uri used to observe specific carrier identity changes
diff --git a/core/java/android/service/carrier/ApnService.java b/core/java/android/service/carrier/ApnService.java
index 57e4b1b..0c12fd4 100644
--- a/core/java/android/service/carrier/ApnService.java
+++ b/core/java/android/service/carrier/ApnService.java
@@ -26,7 +26,7 @@
import android.os.IBinder;
import android.util.Log;
-import com.android.internal.telephony.IApnSourceService;
+import android.service.carrier.IApnSourceService;
import java.util.List;
diff --git a/telephony/java/com/android/internal/telephony/IApnSourceService.aidl b/core/java/android/service/carrier/IApnSourceService.aidl
similarity index 93%
rename from telephony/java/com/android/internal/telephony/IApnSourceService.aidl
rename to core/java/android/service/carrier/IApnSourceService.aidl
index 34c9067..fadd2ff 100644
--- a/telephony/java/com/android/internal/telephony/IApnSourceService.aidl
+++ b/core/java/android/service/carrier/IApnSourceService.aidl
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-package com.android.internal.telephony;
+package android.service.carrier;
import android.content.ContentValues;
+/** @hide */
interface IApnSourceService {
/** Retreive APNs. */
ContentValues[] getApns(int subId);
diff --git a/core/java/android/telephony/CellBroadcastIntents.java b/core/java/android/telephony/CellBroadcastIntents.java
new file mode 100644
index 0000000..8446253
--- /dev/null
+++ b/core/java/android/telephony/CellBroadcastIntents.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.UserHandle;
+
+/**
+ * A static helper class used to send Intents with prepopulated flags.
+ * <p>
+ * This is intended to be used by the CellBroadcastService and will throw a security exception if
+ * used from a UID besides the network stack UID.
+ *
+ * @hide
+ */
+@SystemApi
+public class CellBroadcastIntents {
+ private static final String LOG_TAG = "CellBroadcastIntents";
+
+ /**
+ * @hide
+ */
+ private CellBroadcastIntents() {
+ }
+
+ /**
+ * Returns an intent which can be received by background BroadcastReceivers. This is only
+ * intended to be used by the CellBroadcastService and will throw a security exception if called
+ * from another UID.
+ *
+ * @param context The context from which to send the broadcast
+ * @param user The user from which to send the broadcast
+ * @param intent The Intent to broadcast; all receivers matching this Intent will
+ * receive the broadcast.
+ * @param receiverPermission String naming a permissions that a receiver must hold in order to
+ * receive your broadcast. If null, no permission is required.
+ * @param receiverAppOp The app op associated with the broadcast. If null, no appOp is
+ * required. If both receiverAppOp and receiverPermission are
+ * non-null, a receiver must have both of them to receive the
+ * broadcast
+ * @param resultReceiver Your own BroadcastReceiver to treat as the final receiver of the
+ * broadcast.
+ * @param scheduler A custom Handler with which to schedule the resultReceiver
+ * callback; if null it will be scheduled in the Context's main
+ * thread.
+ * @param initialCode An initial value for the result code. Often Activity.RESULT_OK.
+ * @param initialData An initial value for the result data. Often null.
+ * @param initialExtras An initial value for the result extras. Often null.
+ */
+ public static void sendOrderedBroadcastForBackgroundReceivers(@NonNull Context context,
+ @Nullable UserHandle user, @NonNull Intent intent, @Nullable String receiverPermission,
+ @Nullable String receiverAppOp, @Nullable BroadcastReceiver resultReceiver,
+ @Nullable Handler scheduler, int initialCode, @Nullable String initialData,
+ @Nullable Bundle initialExtras) {
+ int status = context.checkCallingOrSelfPermission(
+ "android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS");
+ if (status == PackageManager.PERMISSION_DENIED) {
+ throw new SecurityException(
+ "Caller does not have permission to send broadcast for background receivers");
+ }
+ Intent backgroundIntent = new Intent(intent);
+ backgroundIntent.setFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+ if (user != null) {
+ context.createContextAsUser(user, 0).sendOrderedBroadcast(backgroundIntent,
+ receiverPermission, receiverAppOp, resultReceiver, scheduler, initialCode,
+ initialData, initialExtras);
+ } else {
+ context.sendOrderedBroadcast(backgroundIntent, receiverPermission,
+ receiverAppOp, resultReceiver, scheduler, initialCode, initialData,
+ initialExtras);
+ }
+ }
+}
diff --git a/telephony/java/android/telephony/SubscriptionPlan.aidl b/core/java/android/telephony/SubscriptionPlan.aidl
similarity index 100%
rename from telephony/java/android/telephony/SubscriptionPlan.aidl
rename to core/java/android/telephony/SubscriptionPlan.aidl
diff --git a/telephony/java/android/telephony/SubscriptionPlan.java b/core/java/android/telephony/SubscriptionPlan.java
similarity index 100%
rename from telephony/java/android/telephony/SubscriptionPlan.java
rename to core/java/android/telephony/SubscriptionPlan.java
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 308c8b3..f87a7c5 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -25,8 +25,6 @@
import android.net.NetworkCapabilities;
import android.os.Binder;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerExecutor;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.Annotation.ApnType;
diff --git a/core/java/android/text/AlteredCharSequence.java b/core/java/android/text/AlteredCharSequence.java
index 4cc71fd..971a47d 100644
--- a/core/java/android/text/AlteredCharSequence.java
+++ b/core/java/android/text/AlteredCharSequence.java
@@ -16,12 +16,14 @@
package android.text;
-// XXX should this really be in the public API at all?
/**
* An AlteredCharSequence is a CharSequence that is largely mirrored from
* another CharSequence, except that a specified range of characters are
* mirrored from a different char array instead.
+ *
+ * @deprecated The functionality this class offers is easily implemented outside the framework.
*/
+@Deprecated
public class AlteredCharSequence
implements CharSequence, GetChars
{
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index e94b800..90625183 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -56,8 +56,12 @@
public static final long DAY_IN_MILLIS = HOUR_IN_MILLIS * 24;
public static final long WEEK_IN_MILLIS = DAY_IN_MILLIS * 7;
/**
- * This constant is actually the length of 364 days, not of a year!
+ * @deprecated Not all years have the same number of days, and this constant is actually the
+ * length of 364 days. Please use other date/time constructs such as
+ * {@link java.util.concurrent.TimeUnit}, {@link java.util.Calendar} or
+ * {@link java.time.Duration} instead.
*/
+ @Deprecated
public static final long YEAR_IN_MILLIS = WEEK_IN_MILLIS * 52;
// The following FORMAT_* symbols are used for specifying the format of
diff --git a/core/java/android/util/CloseGuard.java b/core/java/android/util/CloseGuard.java
new file mode 100644
index 0000000..c39a6c9
--- /dev/null
+++ b/core/java/android/util/CloseGuard.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.util;
+
+import android.annotation.NonNull;
+
+/**
+ * CloseGuard is a mechanism for flagging implicit finalizer cleanup of
+ * resources that should have been cleaned up by explicit close
+ * methods (aka "explicit termination methods" in Effective Java).
+ * <p>
+ * A simple example: <pre> {@code
+ * class Foo {
+ *
+ * private final CloseGuard guard = CloseGuard.get();
+ *
+ * ...
+ *
+ * public Foo() {
+ * ...;
+ * guard.open("cleanup");
+ * }
+ *
+ * public void cleanup() {
+ * guard.close();
+ * ...;
+ * }
+ *
+ * protected void finalize() throws Throwable {
+ * try {
+ * // Note that guard could be null if the constructor threw.
+ * if (guard != null) {
+ * guard.warnIfOpen();
+ * }
+ * cleanup();
+ * } finally {
+ * super.finalize();
+ * }
+ * }
+ * }
+ * }</pre>
+ *
+ * In usage where the resource to be explicitly cleaned up is
+ * allocated after object construction, CloseGuard protection can
+ * be deferred. For example: <pre> {@code
+ * class Bar {
+ *
+ * private final CloseGuard guard = CloseGuard.get();
+ *
+ * ...
+ *
+ * public Bar() {
+ * ...;
+ * }
+ *
+ * public void connect() {
+ * ...;
+ * guard.open("cleanup");
+ * }
+ *
+ * public void cleanup() {
+ * guard.close();
+ * ...;
+ * Reference.reachabilityFence(this);
+ * // For full correctness in the absence of a close() call, other methods may also need
+ * // reachabilityFence() calls.
+ * }
+ *
+ * protected void finalize() throws Throwable {
+ * try {
+ * // Note that guard could be null if the constructor threw.
+ * if (guard != null) {
+ * guard.warnIfOpen();
+ * }
+ * cleanup();
+ * } finally {
+ * super.finalize();
+ * }
+ * }
+ * }
+ * }</pre>
+ *
+ * When used in a constructor, calls to {@code open} should occur at
+ * the end of the constructor since an exception that would cause
+ * abrupt termination of the constructor will mean that the user will
+ * not have a reference to the object to cleanup explicitly. When used
+ * in a method, the call to {@code open} should occur just after
+ * resource acquisition.
+ */
+public final class CloseGuard {
+ private final dalvik.system.CloseGuard mImpl;
+
+ /**
+ * Constructs a new CloseGuard instance.
+ * {@link #open(String)} can be used to set up the instance to warn on failure to close.
+ */
+ public CloseGuard() {
+ mImpl = dalvik.system.CloseGuard.get();
+ }
+
+ /**
+ * Initializes the instance with a warning that the caller should have explicitly called the
+ * {@code closeMethodName} method instead of relying on finalization.
+ *
+ * @param closeMethodName non-null name of explicit termination method. Printed by warnIfOpen.
+ * @throws NullPointerException if closeMethodName is null.
+ */
+ public void open(@NonNull String closeMethodName) {
+ mImpl.open(closeMethodName);
+ }
+
+ /** Marks this CloseGuard instance as closed to avoid warnings on finalization. */
+ public void close() {
+ mImpl.close();
+ }
+
+ /**
+ * Logs a warning if the caller did not properly cleanup by calling an explicit close method
+ * before finalization.
+ */
+ public void warnIfOpen() {
+ mImpl.warnIfOpen();
+ }
+}
diff --git a/core/java/android/util/LocalLog.java b/core/java/android/util/LocalLog.java
index 8b5659b..0203430 100644
--- a/core/java/android/util/LocalLog.java
+++ b/core/java/android/util/LocalLog.java
@@ -17,9 +17,11 @@
package android.util;
import android.annotation.UnsupportedAppUsage;
+import android.os.SystemClock;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.time.Instant;
import java.time.LocalDateTime;
import java.util.ArrayDeque;
import java.util.Deque;
@@ -33,10 +35,22 @@
private final Deque<String> mLog;
private final int mMaxLines;
+ /**
+ * {@code true} to use log timestamps expressed in local date/time, {@code false} to use log
+ * timestamped expressed with the elapsed realtime clock and UTC system clock. {@code false} is
+ * useful when logging behavior that modifies device time zone or system clock.
+ */
+ private final boolean mUseLocalTimestamps;
+
@UnsupportedAppUsage
public LocalLog(int maxLines) {
+ this(maxLines, true /* useLocalTimestamps */);
+ }
+
+ public LocalLog(int maxLines, boolean useLocalTimestamps) {
mMaxLines = Math.max(0, maxLines);
mLog = new ArrayDeque<>(mMaxLines);
+ mUseLocalTimestamps = useLocalTimestamps;
}
@UnsupportedAppUsage
@@ -44,7 +58,14 @@
if (mMaxLines <= 0) {
return;
}
- append(String.format("%s - %s", LocalDateTime.now(), msg));
+ final String logLine;
+ if (mUseLocalTimestamps) {
+ logLine = String.format("%s - %s", LocalDateTime.now(), msg);
+ } else {
+ logLine = String.format(
+ "%s / %s - %s", SystemClock.elapsedRealtime(), Instant.now(), msg);
+ }
+ append(logLine);
}
private synchronized void append(String logLine) {
diff --git a/telephony/java/com/android/ims/internal/uce/common/CapInfo.aidl b/core/java/com/android/ims/internal/uce/common/CapInfo.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/common/CapInfo.aidl
rename to core/java/com/android/ims/internal/uce/common/CapInfo.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/common/CapInfo.java b/core/java/com/android/ims/internal/uce/common/CapInfo.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/common/CapInfo.java
rename to core/java/com/android/ims/internal/uce/common/CapInfo.java
diff --git a/telephony/java/com/android/ims/internal/uce/common/StatusCode.aidl b/core/java/com/android/ims/internal/uce/common/StatusCode.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/common/StatusCode.aidl
rename to core/java/com/android/ims/internal/uce/common/StatusCode.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/common/StatusCode.java b/core/java/com/android/ims/internal/uce/common/StatusCode.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/common/StatusCode.java
rename to core/java/com/android/ims/internal/uce/common/StatusCode.java
diff --git a/telephony/java/com/android/ims/internal/uce/common/UceLong.aidl b/core/java/com/android/ims/internal/uce/common/UceLong.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/common/UceLong.aidl
rename to core/java/com/android/ims/internal/uce/common/UceLong.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/common/UceLong.java b/core/java/com/android/ims/internal/uce/common/UceLong.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/common/UceLong.java
rename to core/java/com/android/ims/internal/uce/common/UceLong.java
diff --git a/telephony/java/com/android/ims/internal/uce/options/IOptionsListener.aidl b/core/java/com/android/ims/internal/uce/options/IOptionsListener.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/IOptionsListener.aidl
rename to core/java/com/android/ims/internal/uce/options/IOptionsListener.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/options/IOptionsService.aidl b/core/java/com/android/ims/internal/uce/options/IOptionsService.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/IOptionsService.aidl
rename to core/java/com/android/ims/internal/uce/options/IOptionsService.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsCapInfo.aidl b/core/java/com/android/ims/internal/uce/options/OptionsCapInfo.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/OptionsCapInfo.aidl
rename to core/java/com/android/ims/internal/uce/options/OptionsCapInfo.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsCapInfo.java b/core/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
rename to core/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsCmdId.aidl b/core/java/com/android/ims/internal/uce/options/OptionsCmdId.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/OptionsCmdId.aidl
rename to core/java/com/android/ims/internal/uce/options/OptionsCmdId.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsCmdId.java b/core/java/com/android/ims/internal/uce/options/OptionsCmdId.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/OptionsCmdId.java
rename to core/java/com/android/ims/internal/uce/options/OptionsCmdId.java
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsCmdStatus.aidl b/core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/OptionsCmdStatus.aidl
rename to core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java b/core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
rename to core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsSipResponse.aidl b/core/java/com/android/ims/internal/uce/options/OptionsSipResponse.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/OptionsSipResponse.aidl
rename to core/java/com/android/ims/internal/uce/options/OptionsSipResponse.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsSipResponse.java b/core/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
rename to core/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/IPresenceListener.aidl b/core/java/com/android/ims/internal/uce/presence/IPresenceListener.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/IPresenceListener.aidl
rename to core/java/com/android/ims/internal/uce/presence/IPresenceListener.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/IPresenceService.aidl b/core/java/com/android/ims/internal/uce/presence/IPresenceService.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/IPresenceService.aidl
rename to core/java/com/android/ims/internal/uce/presence/IPresenceService.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresCapInfo.aidl b/core/java/com/android/ims/internal/uce/presence/PresCapInfo.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresCapInfo.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresCapInfo.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresCapInfo.java b/core/java/com/android/ims/internal/uce/presence/PresCapInfo.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresCapInfo.java
rename to core/java/com/android/ims/internal/uce/presence/PresCapInfo.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresCmdId.aidl b/core/java/com/android/ims/internal/uce/presence/PresCmdId.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresCmdId.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresCmdId.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresCmdId.java b/core/java/com/android/ims/internal/uce/presence/PresCmdId.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresCmdId.java
rename to core/java/com/android/ims/internal/uce/presence/PresCmdId.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresCmdStatus.aidl b/core/java/com/android/ims/internal/uce/presence/PresCmdStatus.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresCmdStatus.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresCmdStatus.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresCmdStatus.java b/core/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
rename to core/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.aidl b/core/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java b/core/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java
rename to core/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresResInfo.aidl b/core/java/com/android/ims/internal/uce/presence/PresResInfo.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresResInfo.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresResInfo.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresResInfo.java b/core/java/com/android/ims/internal/uce/presence/PresResInfo.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresResInfo.java
rename to core/java/com/android/ims/internal/uce/presence/PresResInfo.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.aidl b/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java b/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
rename to core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresRlmiInfo.aidl b/core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresRlmiInfo.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java b/core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
rename to core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresServiceInfo.aidl b/core/java/com/android/ims/internal/uce/presence/PresServiceInfo.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresServiceInfo.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresServiceInfo.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresServiceInfo.java b/core/java/com/android/ims/internal/uce/presence/PresServiceInfo.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresServiceInfo.java
rename to core/java/com/android/ims/internal/uce/presence/PresServiceInfo.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresSipResponse.aidl b/core/java/com/android/ims/internal/uce/presence/PresSipResponse.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresSipResponse.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresSipResponse.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresSipResponse.java b/core/java/com/android/ims/internal/uce/presence/PresSipResponse.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresSipResponse.java
rename to core/java/com/android/ims/internal/uce/presence/PresSipResponse.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresSubscriptionState.aidl b/core/java/com/android/ims/internal/uce/presence/PresSubscriptionState.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresSubscriptionState.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresSubscriptionState.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java b/core/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java
rename to core/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresTupleInfo.aidl b/core/java/com/android/ims/internal/uce/presence/PresTupleInfo.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresTupleInfo.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresTupleInfo.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresTupleInfo.java b/core/java/com/android/ims/internal/uce/presence/PresTupleInfo.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresTupleInfo.java
rename to core/java/com/android/ims/internal/uce/presence/PresTupleInfo.java
diff --git a/telephony/java/com/android/ims/internal/uce/uceservice/IUceListener.aidl b/core/java/com/android/ims/internal/uce/uceservice/IUceListener.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/uceservice/IUceListener.aidl
rename to core/java/com/android/ims/internal/uce/uceservice/IUceListener.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/uceservice/IUceService.aidl b/core/java/com/android/ims/internal/uce/uceservice/IUceService.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/uceservice/IUceService.aidl
rename to core/java/com/android/ims/internal/uce/uceservice/IUceService.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/uceservice/ImsUceManager.java b/core/java/com/android/ims/internal/uce/uceservice/ImsUceManager.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/uceservice/ImsUceManager.java
rename to core/java/com/android/ims/internal/uce/uceservice/ImsUceManager.java
diff --git a/telephony/java/com/android/ims/internal/uce/uceservice/UceServiceBase.java b/core/java/com/android/ims/internal/uce/uceservice/UceServiceBase.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/uceservice/UceServiceBase.java
rename to core/java/com/android/ims/internal/uce/uceservice/UceServiceBase.java
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index fd3cd42..fa823c4 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -30,8 +30,10 @@
import android.os.Trace;
import android.util.Log;
import android.util.Slog;
+
import com.android.internal.logging.AndroidConfig;
import com.android.server.NetworkManagementSocketTagger;
+
import dalvik.system.RuntimeHooks;
import dalvik.system.VMRuntime;
@@ -365,8 +367,8 @@
if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!");
}
- protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
- ClassLoader classLoader) {
+ protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
+ String[] argv, ClassLoader classLoader) {
// If the application calls System.exit(), terminate the process
// immediately without running any shutdown hooks. It is not possible to
// shutdown an Android application gracefully. Among other things, the
@@ -374,10 +376,8 @@
// leftover running threads to crash before the process actually exits.
nativeSetExitWithoutCleanup(true);
- // We want to be fairly aggressive about heap utilization, to avoid
- // holding on to a lot of memory that isn't needed.
- VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
+ VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);
final Arguments args = new Arguments(argv);
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index f0e7796..790d7f7 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -23,16 +23,18 @@
import android.system.OsConstants;
import android.system.StructCapUserData;
import android.system.StructCapUserHeader;
-import android.util.TimingsTraceLog;
import android.util.Slog;
+import android.util.TimingsTraceLog;
+
import dalvik.system.VMRuntime;
+
+import libcore.io.IoUtils;
+
import java.io.DataOutputStream;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
-import libcore.io.IoUtils;
-
/**
* Startup class for the wrapper process.
* @hide
@@ -166,10 +168,10 @@
System.arraycopy(argv, 2, removedArgs, 0, argv.length - 2);
argv = removedArgs;
}
-
// Perform the same initialization that would happen after the Zygote forks.
Zygote.nativePreApplicationInit();
- return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
+ return RuntimeInit.applicationInit(targetSdkVersion, /*disabledCompatChanges*/ null,
+ argv, classLoader);
}
/**
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 00ab45e..33adec1 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -642,6 +642,7 @@
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
return ZygoteInit.zygoteInit(args.mTargetSdkVersion,
+ args.mDisabledCompatChanges,
args.mRemainingArgs,
null /* classLoader */);
} finally {
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index fc55ccf..3915ba2 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -210,6 +210,12 @@
int mHiddenApiAccessStatslogSampleRate = -1;
/**
+ * A set of disabled app compatibility changes for the running app. From
+ * --disabled-compat-changes.
+ */
+ long[] mDisabledCompatChanges = null;
+
+ /**
* Constructs instance and parses args
*
* @param args zygote command-line args
@@ -416,6 +422,16 @@
mUsapPoolStatusSpecified = true;
mUsapPoolEnabled = Boolean.parseBoolean(arg.substring(arg.indexOf('=') + 1));
expectRuntimeArgs = false;
+ } else if (arg.startsWith("--disabled-compat-changes=")) {
+ if (mDisabledCompatChanges != null) {
+ throw new IllegalArgumentException("Duplicate arg specified");
+ }
+ final String[] params = arg.substring(arg.indexOf('=') + 1).split(",");
+ final int length = params.length;
+ mDisabledCompatChanges = new long[length];
+ for (int i = 0; i < length; i++) {
+ mDisabledCompatChanges[i] = Long.parseLong(params[i]);
+ }
} else {
break;
}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index b15e1ef..4c37591 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -502,6 +502,7 @@
} else {
if (!isZygote) {
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
+ parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, null /* classLoader */);
} else {
return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 93e6102..7b77a92 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -547,6 +547,7 @@
* Pass the remaining arguments to SystemServer.
*/
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
+ parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, cl);
}
@@ -972,14 +973,16 @@
*
* Current recognized args:
* <ul>
- * <li> <code> [--] <start class name> <args>
+ * <li> <code> [--] <start class name> <args>
* </ul>
*
* @param targetSdkVersion target SDK version
- * @param argv arg strings
+ * @param disabledCompatChanges set of disabled compat changes for the process (all others
+ * are enabled)
+ * @param argv arg strings
*/
- public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
- ClassLoader classLoader) {
+ public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
+ String[] argv, ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
@@ -989,7 +992,8 @@
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit();
- return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
+ return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
+ classLoader);
}
/**
diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java
index 731b93c..3fff5c2 100644
--- a/core/java/com/android/internal/util/Preconditions.java
+++ b/core/java/com/android/internal/util/Preconditions.java
@@ -102,6 +102,24 @@
}
/**
+ * Ensures that an string reference passed as a parameter to the calling method is not empty.
+ *
+ * @param string an string reference
+ * @param messageTemplate a printf-style message template to use if the check fails; will be
+ * converted to a string using {@link String#format(String, Object...)}
+ * @param messageArgs arguments for {@code messageTemplate}
+ * @return the string reference that was validated
+ * @throws IllegalArgumentException if {@code string} is empty
+ */
+ public static @NonNull <T extends CharSequence> T checkStringNotEmpty(
+ final T string, final String messageTemplate, final Object... messageArgs) {
+ if (TextUtils.isEmpty(string)) {
+ throw new IllegalArgumentException(String.format(messageTemplate, messageArgs));
+ }
+ return string;
+ }
+
+ /**
* Ensures that an object reference passed as a parameter to the calling
* method is not null.
*
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 2383731..8e0e1c6 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -693,6 +693,7 @@
char methodTraceFileSizeBuf[sizeof("-Xmethod-trace-file-size:") + PROPERTY_VALUE_MAX];
std::string fingerprintBuf;
char jdwpProviderBuf[sizeof("-XjdwpProvider:") - 1 + PROPERTY_VALUE_MAX];
+ char opaqueJniIds[sizeof("-Xopaque-jni-ids:") - 1 + PROPERTY_VALUE_MAX];
char bootImageBuf[sizeof("-Ximage:") - 1 + PROPERTY_VALUE_MAX];
// Read if we are using the profile configuration, do this at the start since the last ART args
@@ -884,6 +885,14 @@
"default");
}
+ // Only pass an explicit opaque-jni-ids to apps forked from zygote
+ if (zygote) {
+ parseRuntimeOption("dalvik.vm.opaque-jni-ids",
+ opaqueJniIds,
+ "-Xopaque-jni-ids:",
+ "swapable");
+ }
+
parseRuntimeOption("dalvik.vm.lockprof.threshold",
lockProfThresholdBuf,
"-Xlockprofthreshold:");
diff --git a/core/jni/android_os_Trace.cpp b/core/jni/android_os_Trace.cpp
index bd82bd9..0f7611a 100644
--- a/core/jni/android_os_Trace.cpp
+++ b/core/jni/android_os_Trace.cpp
@@ -50,10 +50,6 @@
callback(buffer.data());
}
-static jlong android_os_Trace_nativeGetEnabledTags(JNIEnv*, jclass) {
- return atrace_get_enabled_tags();
-}
-
static void android_os_Trace_nativeTraceCounter(JNIEnv* env, jclass,
jlong tag, jstring nameStr, jlong value) {
withString(env, nameStr, [tag, value](char* str) {
@@ -96,9 +92,6 @@
static const JNINativeMethod gTraceMethods[] = {
/* name, signature, funcPtr */
- { "nativeGetEnabledTags",
- "()J",
- (void*)android_os_Trace_nativeGetEnabledTags },
{ "nativeSetAppTracingAllowed",
"(Z)V",
(void*)android_os_Trace_nativeSetAppTracingAllowed },
@@ -123,6 +116,11 @@
{ "nativeAsyncTraceEnd",
"(JLjava/lang/String;I)V",
(void*)android_os_Trace_nativeAsyncTraceEnd },
+
+ // ----------- @CriticalNative ----------------
+ { "nativeGetEnabledTags",
+ "()J",
+ (void*)atrace_get_enabled_tags },
};
int register_android_os_Trace(JNIEnv* env) {
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index a3f5311..58fd9c0 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -74,6 +74,7 @@
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <bionic/malloc.h>
+#include <bionic/page.h>
#include <cutils/fs.h>
#include <cutils/multiuser.h>
#include <private/android_filesystem_config.h>
@@ -1673,9 +1674,14 @@
static int disable_execute_only(struct dl_phdr_info *info, size_t size, void *data) {
// Search for any execute-only segments and mark them read+execute.
for (int i = 0; i < info->dlpi_phnum; i++) {
- if ((info->dlpi_phdr[i].p_type == PT_LOAD) && (info->dlpi_phdr[i].p_flags == PF_X)) {
- mprotect(reinterpret_cast<void*>(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr),
- info->dlpi_phdr[i].p_memsz, PROT_READ | PROT_EXEC);
+ const auto& phdr = info->dlpi_phdr[i];
+ if ((phdr.p_type == PT_LOAD) && (phdr.p_flags == PF_X)) {
+ auto addr = reinterpret_cast<void*>(info->dlpi_addr + PAGE_START(phdr.p_vaddr));
+ size_t len = PAGE_OFFSET(phdr.p_vaddr) + phdr.p_memsz;
+ if (mprotect(addr, len, PROT_READ | PROT_EXEC) == -1) {
+ ALOGE("mprotect(%p, %zu, PROT_READ | PROT_EXEC) failed: %m", addr, len);
+ return -1;
+ }
}
}
// Return non-zero to exit dl_iterate_phdr.
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index fd6984b..0c21076 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -37,6 +37,8 @@
"/apex/com.android.ipsec/javalib/ike.jar",
"/apex/com.android.media/javalib/updatable-media.jar",
"/apex/com.android.sdkext/javalib/framework-sdkext.jar",
+ "/apex/com.android.telephony/javalib/telephony-common.jar",
+ "/apex/com.android.telephony/javalib/ims-common.jar",
"/dev/null",
"/dev/socket/zygote",
"/dev/socket/zygote_secondary",
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 68f3c2e..8dc84c8 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -633,10 +633,9 @@
<protected-broadcast android:name="android.intent.action.DEVICE_CUSTOMIZATION_READY" />
- <!-- NETWORK_SET_TIME / NETWORK_SET_TIMEZONE moved from com.android.phone to system server.
- They should ultimately be removed. -->
+ <!-- NETWORK_SET_TIME moved from com.android.phone to system server. It should ultimately be
+ removed. -->
<protected-broadcast android:name="android.intent.action.NETWORK_SET_TIME" />
- <protected-broadcast android:name="android.intent.action.NETWORK_SET_TIMEZONE" />
<!-- For tether entitlement recheck-->
<protected-broadcast
@@ -2031,6 +2030,11 @@
<!-- =========================================== -->
<eat-comment />
+ <!-- @SystemApi Allows granting runtime permissions to telephony related components.
+ @hide Used internally. -->
+ <permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS"
+ android:protectionLevel="signature|telephony" />
+
<!-- Allows modification of the telephony state - power on, mmi, etc.
Does not include placing calls.
<p>Not for use by third-party applications. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d5e263f..4c25a7a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3015,9 +3015,6 @@
<!-- String array containing numbers that shouldn't be logged. Country-specific. -->
<string-array name="unloggable_phone_numbers" />
- <!-- Flag specifying whether or not IMS will use the dynamic ImsResolver -->
- <bool name="config_dynamic_bind_ims">false</bool>
-
<!-- Cellular data service package name to bind to by default. If none is specified in an overlay, an
empty string is passed in -->
<string name="config_wwan_data_service_package" translatable="false">com.android.phone</string>
@@ -3677,14 +3674,13 @@
-->
<string name="config_defaultWellbeingPackage" translatable="false"></string>
-
<!-- The package name for the system telephony apps.
This package must be trusted, as it will be granted with permissions with special telephony
protection level. Note, framework by default support multiple telephony apps, each package
name is separated by comma.
Example: "com.android.phone,com.android.stk,com.android.providers.telephony"
-->
- <string name="config_telephonyPackages" translatable="false">"com.android.phone,com.android.stk,com.android.providers.telephony,com.android.ons"</string>
+ <string name="config_telephonyPackages" translatable="false">"com.android.phone,com.android.stk,com.android.providers.telephony,com.android.ons,com.android.cellbroadcastservice"</string>
<!-- The component name for the default system attention service.
This service must be trusted, as it can be activated without explicit consent of the user.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 18c68c3..a1f66d3 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -296,7 +296,6 @@
<java-symbol type="bool" name="config_hotswapCapable" />
<java-symbol type="bool" name="config_mms_content_disposition_support" />
<java-symbol type="string" name="config_ims_package" />
- <java-symbol type="bool" name="config_dynamic_bind_ims" />
<java-symbol type="string" name="config_wwan_network_service_package" />
<java-symbol type="string" name="config_wlan_network_service_package" />
<java-symbol type="string" name="config_wwan_network_service_class" />
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
index b906d84..ed613c3 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
@@ -176,14 +176,12 @@
mDevice.setPin(mPin);
break;
case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
- mDevice.setPasskey(mPasskey);
break;
case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:
case BluetoothDevice.PAIRING_VARIANT_CONSENT:
mDevice.setPairingConfirmation(true);
break;
case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:
- mDevice.setRemoteOutOfBandData();
break;
}
} else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())) {
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 1670d49..4d4f447 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -24,6 +24,7 @@
],
static_libs: [
"frameworks-base-testutils",
+ "core-test-rules", // for libcore.dalvik.system.CloseGuardSupport
"core-tests-support",
"android-common",
"frameworks-core-util-lib",
diff --git a/core/tests/coretests/src/android/util/CloseGuardTest.java b/core/tests/coretests/src/android/util/CloseGuardTest.java
new file mode 100644
index 0000000..d86c7b7
--- /dev/null
+++ b/core/tests/coretests/src/android/util/CloseGuardTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import libcore.dalvik.system.CloseGuardSupport;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+
+/** Unit tests for {@link android.util.CloseGuard} */
+public class CloseGuardTest {
+
+ @Rule
+ public final TestRule rule = CloseGuardSupport.getRule();
+
+ @Test
+ public void testEnabled_NotOpen() throws Throwable {
+ ResourceOwner owner = new ResourceOwner();
+ assertUnreleasedResources(owner, 0);
+ }
+
+ @Test
+ public void testEnabled_OpenNotClosed() throws Throwable {
+ ResourceOwner owner = new ResourceOwner();
+ owner.open();
+ assertUnreleasedResources(owner, 1);
+ }
+
+ @Test
+ public void testEnabled_OpenThenClosed() throws Throwable {
+ ResourceOwner owner = new ResourceOwner();
+ owner.open();
+ owner.close();
+ assertUnreleasedResources(owner, 0);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testOpen_withNullMethodName_throwsNPE() throws Throwable {
+ CloseGuard closeGuard = new CloseGuard();
+ closeGuard.open(null);
+ }
+
+ private void assertUnreleasedResources(ResourceOwner owner, int expectedCount)
+ throws Throwable {
+ try {
+ CloseGuardSupport.getFinalizerChecker().accept(owner, expectedCount);
+ } finally {
+ // Close the resource so that CloseGuard does not generate a warning for real when it
+ // is actually finalized.
+ owner.close();
+ }
+ }
+
+ /**
+ * A test user of {@link CloseGuard}.
+ */
+ private static class ResourceOwner {
+
+ private final CloseGuard mCloseGuard;
+
+ ResourceOwner() {
+ mCloseGuard = new CloseGuard();
+ }
+
+ public void open() {
+ mCloseGuard.open("close");
+ }
+
+ public void close() {
+ mCloseGuard.close();
+ }
+
+ /**
+ * Make finalize public so that it can be tested directly without relying on garbage
+ * collection to trigger it.
+ */
+ @Override
+ public void finalize() throws Throwable {
+ mCloseGuard.warnIfOpen();
+ super.finalize();
+ }
+ }
+}
diff --git a/core/tests/coretests/src/android/util/LocalLogTest.java b/core/tests/coretests/src/android/util/LocalLogTest.java
index 6cdcb5e..d4861cd 100644
--- a/core/tests/coretests/src/android/util/LocalLogTest.java
+++ b/core/tests/coretests/src/android/util/LocalLogTest.java
@@ -29,14 +29,24 @@
@LargeTest
public class LocalLogTest extends TestCase {
- public void testA() {
+ public void testA_localTimestamps() {
+ boolean localTimestamps = true;
+ doTestA(localTimestamps);
+ }
+
+ public void testA_nonLocalTimestamps() {
+ boolean localTimestamps = false;
+ doTestA(localTimestamps);
+ }
+
+ private void doTestA(boolean localTimestamps) {
String[] lines = {
- "foo",
- "bar",
- "baz"
+ "foo",
+ "bar",
+ "baz"
};
String[] want = lines;
- testcase(new LocalLog(10), lines, want);
+ testcase(new LocalLog(10, localTimestamps), lines, want);
}
public void testB() {
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 3455c4f..1033e56 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -25,6 +25,7 @@
import android.content.pm.PackageManager;
import android.media.audiofx.AudioEffect;
import android.media.audiopolicy.AudioMix;
+import android.telephony.TelephonyManager;
import android.util.Log;
import java.lang.annotation.Retention;
@@ -1239,7 +1240,8 @@
* </ul>
*/
public static int getPlatformType(Context context) {
- if (context.getResources().getBoolean(com.android.internal.R.bool.config_voice_capable)) {
+ if (((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE))
+ .isVoiceCapable()) {
return PLATFORM_VOICE;
} else if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
return PLATFORM_TELEVISION;
diff --git a/media/java/android/media/MediaScannerConnection.java b/media/java/android/media/MediaScannerConnection.java
index 471fa2c..aafbd44 100644
--- a/media/java/android/media/MediaScannerConnection.java
+++ b/media/java/android/media/MediaScannerConnection.java
@@ -220,7 +220,7 @@
/**
* Convenience for constructing a {@link MediaScannerConnection}, calling
- * {@link #connect} on it, and calling {@link #scanFile} with the given
+ * {@link #connect} on it, and calling {@link #scanFile(String, String)} with the given
* <var>path</var> and <var>mimeType</var> when the connection is
* established.
* @param context The caller's Context, required for establishing a connection to
diff --git a/media/java/android/media/tv/ITvInputService.aidl b/media/java/android/media/tv/ITvInputService.aidl
old mode 100644
new mode 100755
index bd05184..f90c504
--- a/media/java/android/media/tv/ITvInputService.aidl
+++ b/media/java/android/media/tv/ITvInputService.aidl
@@ -38,4 +38,5 @@
void notifyHardwareRemoved(in TvInputHardwareInfo hardwareInfo);
void notifyHdmiDeviceAdded(in HdmiDeviceInfo deviceInfo);
void notifyHdmiDeviceRemoved(in HdmiDeviceInfo deviceInfo);
+ void notifyHdmiDeviceUpdated(in HdmiDeviceInfo deviceInfo);
}
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
old mode 100644
new mode 100755
index ff69779..5c11ed9b
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -173,6 +173,12 @@
mServiceHandler.obtainMessage(ServiceHandler.DO_REMOVE_HDMI_INPUT,
deviceInfo).sendToTarget();
}
+
+ @Override
+ public void notifyHdmiDeviceUpdated(HdmiDeviceInfo deviceInfo) {
+ mServiceHandler.obtainMessage(ServiceHandler.DO_UPDATE_HDMI_INPUT,
+ deviceInfo).sendToTarget();
+ }
};
}
@@ -257,6 +263,24 @@
return null;
}
+ /**
+ * Called when {@code deviceInfo} is updated.
+ *
+ * <p>The changes are usually cuased by the corresponding HDMI-CEC logical device.
+ *
+ * <p>The default behavior ignores all changes.
+ *
+ * <p>The TV input service responsible for {@code deviceInfo} can update the {@link TvInputInfo}
+ * object based on the updated {@code deviceInfo} (e.g. update the label based on the preferred
+ * device OSD name).
+ *
+ * @param deviceInfo the updated {@link HdmiDeviceInfo} object.
+ * @hide
+ */
+ @SystemApi
+ public void onHdmiDeviceUpdated(@NonNull HdmiDeviceInfo deviceInfo) {
+ }
+
private boolean isPassthroughInput(String inputId) {
if (mTvInputManager == null) {
mTvInputManager = (TvInputManager) getSystemService(Context.TV_INPUT_SERVICE);
@@ -1962,6 +1986,7 @@
private static final int DO_REMOVE_HARDWARE_INPUT = 5;
private static final int DO_ADD_HDMI_INPUT = 6;
private static final int DO_REMOVE_HDMI_INPUT = 7;
+ private static final int DO_UPDATE_HDMI_INPUT = 8;
private void broadcastAddHardwareInput(int deviceId, TvInputInfo inputInfo) {
int n = mCallbacks.beginBroadcast();
@@ -2131,6 +2156,11 @@
}
return;
}
+ case DO_UPDATE_HDMI_INPUT: {
+ HdmiDeviceInfo deviceInfo = (HdmiDeviceInfo) msg.obj;
+ onHdmiDeviceUpdated(deviceInfo);
+ return;
+ }
default: {
Log.w(TAG, "Unhandled message code: " + msg.what);
return;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index 96aee51..a2bd210 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -155,8 +155,8 @@
public boolean disconnect(BluetoothDevice device) {
if (mService == null) return false;
// Downgrade priority as user is disconnecting the headset.
- if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ if (mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
}
return mService.disconnect(device);
}
@@ -179,23 +179,29 @@
}
public boolean isPreferred(BluetoothDevice device) {
- if (mService == null) return false;
- return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+ if (mService == null) {
+ return false;
+ }
+ return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
public int getPreferred(BluetoothDevice device) {
- if (mService == null) return BluetoothProfile.PRIORITY_OFF;
- return mService.getPriority(device);
+ if (mService == null) {
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+ }
+ return mService.getConnectionPolicy(device);
}
public void setPreferred(BluetoothDevice device, boolean preferred) {
- if (mService == null) return;
+ if (mService == null) {
+ return;
+ }
if (preferred) {
- if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
}
} else {
- mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
}
}
boolean isA2dpPlaying() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
index 55765dd..9c896c8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
@@ -124,8 +124,8 @@
return false;
}
// Downgrade priority as user is disconnecting the headset.
- if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ if (mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
}
return mService.disconnect(device);
}
@@ -141,14 +141,14 @@
if (mService == null) {
return false;
}
- return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+ return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
public int getPreferred(BluetoothDevice device) {
if (mService == null) {
- return BluetoothProfile.PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
- return mService.getPriority(device);
+ return mService.getConnectionPolicy(device);
}
public void setPreferred(BluetoothDevice device, boolean preferred) {
@@ -156,11 +156,11 @@
return;
}
if (preferred) {
- if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
}
} else {
- mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index 0d972c5..2f34b2b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -116,7 +116,7 @@
}
return new Pair<>(
getBluetoothDrawable(context,
- com.android.internal.R.drawable.ic_settings_bluetooth),
+ com.android.internal.R.drawable.ic_settings_bluetooth).mutate(),
context.getString(R.string.bluetooth_talkback_bluetooth));
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 56be3bb..abfee1d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -164,9 +164,7 @@
public void disconnect() {
synchronized (mProfileLock) {
- for (LocalBluetoothProfile profile : mProfiles) {
- disconnect(profile);
- }
+ mLocalAdapter.disconnectAllEnabledProfiles(mDevice);
}
// Disconnect PBAP server in case its connected
// This is to ensure all the profiles are disconnected as some CK/Hs do not
@@ -645,12 +643,8 @@
refresh();
- if (bondState == BluetoothDevice.BOND_BONDED) {
- if (mDevice.isBluetoothDock()) {
- onBondingDockConnect();
- } else if (mDevice.isBondingInitiatedLocally()) {
- connect(false);
- }
+ if (bondState == BluetoothDevice.BOND_BONDED && mDevice.isBondingInitiatedLocally()) {
+ connect(false);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
index 9f7b718..560cb3b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
@@ -120,8 +120,8 @@
return false;
}
// Downgrade priority as user is disconnecting the headset.
- if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ if (mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
}
return mService.disconnect(device);
}
@@ -165,14 +165,14 @@
if (mService == null) {
return false;
}
- return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+ return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
public int getPreferred(BluetoothDevice device) {
if (mService == null) {
- return BluetoothProfile.PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
- return mService.getPriority(device);
+ return mService.getConnectionPolicy(device);
}
public void setPreferred(BluetoothDevice device, boolean preferred) {
@@ -180,11 +180,11 @@
return;
}
if (preferred) {
- if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
}
} else {
- mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index ebaeb74..58655a2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -153,8 +153,8 @@
public boolean disconnect(BluetoothDevice device) {
if (mService == null) return false;
// Downgrade priority as user is disconnecting the hearing aid.
- if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ if (mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
}
return mService.disconnect(device);
}
@@ -177,23 +177,29 @@
}
public boolean isPreferred(BluetoothDevice device) {
- if (mService == null) return false;
- return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+ if (mService == null) {
+ return false;
+ }
+ return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
public int getPreferred(BluetoothDevice device) {
- if (mService == null) return BluetoothProfile.PRIORITY_OFF;
- return mService.getPriority(device);
+ if (mService == null) {
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+ }
+ return mService.getConnectionPolicy(device);
}
public void setPreferred(BluetoothDevice device, boolean preferred) {
- if (mService == null) return;
+ if (mService == null) {
+ return;
+ }
if (preferred) {
- if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
}
} else {
- mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
index 860b77d..a372e23 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
@@ -135,8 +135,8 @@
return false;
}
// Downgrade priority as user is disconnecting the headset.
- if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ if (mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
}
return mService.disconnect(device);
}
@@ -154,15 +154,15 @@
if (mService == null) {
return false;
}
- return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+ return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
@Override
public int getPreferred(BluetoothDevice device) {
if (mService == null) {
- return BluetoothProfile.PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
- return mService.getPriority(device);
+ return mService.getConnectionPolicy(device);
}
@Override
@@ -171,11 +171,11 @@
return;
}
if (preferred) {
- if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
}
} else {
- mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
index 6d874ab..975a1e6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
@@ -116,23 +116,27 @@
}
public boolean isPreferred(BluetoothDevice device) {
- if (mService == null) return false;
- return mService.getPriority(device) != BluetoothProfile.PRIORITY_OFF;
+ if (mService == null) {
+ return false;
+ }
+ return mService.getConnectionPolicy(device) != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
public int getPreferred(BluetoothDevice device) {
- if (mService == null) return BluetoothProfile.PRIORITY_OFF;
- return mService.getPriority(device);
+ if (mService == null) {
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+ }
+ return mService.getConnectionPolicy(device);
}
public void setPreferred(BluetoothDevice device, boolean preferred) {
if (mService == null) return;
if (preferred) {
- if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
}
} else {
- mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
index d4dda32..95139a1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
@@ -123,8 +123,8 @@
return false;
}
// Downgrade priority as user is disconnecting.
- if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ if (mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
}
return mService.disconnect(device);
}
@@ -140,14 +140,14 @@
if (mService == null) {
return false;
}
- return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+ return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
public int getPreferred(BluetoothDevice device) {
if (mService == null) {
- return BluetoothProfile.PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
- return mService.getPriority(device);
+ return mService.getConnectionPolicy(device);
}
public void setPreferred(BluetoothDevice device, boolean preferred) {
@@ -155,11 +155,11 @@
return;
}
if (preferred) {
- if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
}
} else {
- mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
index b2a9a6a..31a0eea 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
@@ -119,8 +119,8 @@
if (mService == null) {
return false;
}
- if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ if (mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
}
return mService.disconnect(device);
}
@@ -136,14 +136,14 @@
if (mService == null) {
return false;
}
- return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+ return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
public int getPreferred(BluetoothDevice device) {
if (mService == null) {
- return BluetoothProfile.PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
- return mService.getPriority(device);
+ return mService.getConnectionPolicy(device);
}
public void setPreferred(BluetoothDevice device, boolean preferred) {
@@ -151,11 +151,11 @@
return;
}
if (preferred) {
- if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
}
} else {
- mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/OWNERS b/packages/SettingsLib/src/com/android/settingslib/bluetooth/OWNERS
index 7162121..387bae1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/OWNERS
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/OWNERS
@@ -1,8 +1,7 @@
# Default reviewers for this and subdirectories.
-asapperstein@google.com
-asargent@google.com
-eisenbach@google.com
-jackqdyulei@google.com
siyuanh@google.com
+hughchen@google.com
+timhypeng@google.com
+robertluo@google.com
-# Emergency approvers in case the above are not available
\ No newline at end of file
+# Emergency approvers in case the above are not available
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java
index e1e5dbe..8e3f3ed 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java
@@ -57,7 +57,7 @@
}
public int getPreferred(BluetoothDevice device) {
- return BluetoothProfile.PRIORITY_OFF; // Settings app doesn't handle OPP
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; // Settings app doesn't handle OPP
}
public void setPreferred(BluetoothDevice device, boolean preferred) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
index a2da4fb..4ea0df6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
@@ -151,14 +151,14 @@
if (mService == null) {
return false;
}
- return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+ return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
public int getPreferred(BluetoothDevice device) {
if (mService == null) {
- return BluetoothProfile.PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
- return mService.getPriority(device);
+ return mService.getConnectionPolicy(device);
}
public void setPreferred(BluetoothDevice device, boolean preferred) {
@@ -166,11 +166,11 @@
return;
}
if (preferred) {
- if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
}
} else {
- mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
index 9b733f2..0ca4d61 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
@@ -119,8 +119,8 @@
if (mService == null) {
return false;
}
- if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ if (mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
}
return mService.disconnect(device);
}
@@ -136,14 +136,14 @@
if (mService == null) {
return false;
}
- return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+ return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
public int getPreferred(BluetoothDevice device) {
if (mService == null) {
- return BluetoothProfile.PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
- return mService.getPriority(device);
+ return mService.getConnectionPolicy(device);
}
public void setPreferred(BluetoothDevice device, boolean preferred) {
@@ -151,11 +151,11 @@
return;
}
if (preferred) {
- if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
}
} else {
- mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+ mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 5e2b7c8..6821942 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -949,8 +949,7 @@
(1 << AudioManager.STREAM_NOTIFICATION) |
(1 << AudioManager.STREAM_SYSTEM) |
(1 << AudioManager.STREAM_SYSTEM_ENFORCED);
- if (!mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_voice_capable)) {
+ if (!getTelephonyManager().isVoiceCapable()) {
ringerModeAffectedStreams |= (1 << AudioManager.STREAM_MUSIC);
}
db.execSQL("DELETE FROM system WHERE name='"
@@ -2579,7 +2578,7 @@
String val = "";
String mode;
for (int phoneId = 0;
- phoneId < TelephonyManager.getDefault().getPhoneCount(); phoneId++) {
+ phoneId < getTelephonyManager().getPhoneCount(); phoneId++) {
mode = TelephonyManager.getTelephonyProperty(phoneId,
"ro.telephony.default_network",
Integer.toString(RILConstants.PREFERRED_NETWORK_MODE));
@@ -2693,4 +2692,9 @@
private String getDefaultDeviceName() {
return mContext.getResources().getString(R.string.def_device_name_simple, Build.MODEL);
}
+
+ private TelephonyManager getTelephonyManager() {
+ return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ }
+
}
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 4dbca47..9d9cad8 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -163,8 +163,7 @@
public CarrierTextController(Context context, CharSequence separator, boolean showAirplaneMode,
boolean showMissingSim) {
mContext = context;
- mIsEmergencyCallCapable = context.getResources().getBoolean(
- com.android.internal.R.bool.config_voice_capable);
+ mIsEmergencyCallCapable = getTelephonyManager().isVoiceCapable();
mShowAirplaneMode = showAirplaneMode;
mShowMissingSim = showMissingSim;
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
index 210b82d..1acccf9 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
@@ -26,6 +26,7 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.telecom.TelecomManager;
+import android.telephony.TelephonyManager;
import android.util.AttributeSet;
import android.util.Slog;
import android.view.MotionEvent;
@@ -92,13 +93,16 @@
public EmergencyButton(Context context, AttributeSet attrs) {
super(context, attrs);
- mIsVoiceCapable = context.getResources().getBoolean(
- com.android.internal.R.bool.config_voice_capable);
+ mIsVoiceCapable = getTelephonyManager().isVoiceCapable();
mEnableEmergencyCallWhileSimLocked = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked);
mEmergencyAffordanceManager = new EmergencyAffordanceManager(context);
}
+ private TelephonyManager getTelephonyManager() {
+ return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ }
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockInfo.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockInfo.java
index 812f215..0210e08 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockInfo.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockInfo.java
@@ -25,12 +25,12 @@
final class ClockInfo {
private final String mName;
- private final String mTitle;
+ private final Supplier<String> mTitle;
private final String mId;
private final Supplier<Bitmap> mThumbnail;
private final Supplier<Bitmap> mPreview;
- private ClockInfo(String name, String title, String id,
+ private ClockInfo(String name, Supplier<String> title, String id,
Supplier<Bitmap> thumbnail, Supplier<Bitmap> preview) {
mName = name;
mTitle = title;
@@ -50,7 +50,7 @@
* Gets the name (title) of the clock face to be shown in the picker app.
*/
String getTitle() {
- return mTitle;
+ return mTitle.get();
}
/**
@@ -80,7 +80,7 @@
static class Builder {
private String mName;
- private String mTitle;
+ private Supplier<String> mTitle;
private String mId;
private Supplier<Bitmap> mThumbnail;
private Supplier<Bitmap> mPreview;
@@ -94,7 +94,7 @@
return this;
}
- public Builder setTitle(String title) {
+ public Builder setTitle(Supplier<String> title) {
mTitle = title;
return this;
}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
index 9e2464e..5668c5f 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -243,11 +243,12 @@
mPreviewClocks.reloadCurrentClock();
mListeners.forEach((listener, clocks) -> {
clocks.reloadCurrentClock();
- ClockPlugin clock = clocks.getCurrentClock();
- if (clock instanceof DefaultClockController) {
- listener.onClockChanged(null);
+ final ClockPlugin clock = clocks.getCurrentClock();
+ if (Looper.myLooper() == Looper.getMainLooper()) {
+ listener.onClockChanged(clock instanceof DefaultClockController ? null : clock);
} else {
- listener.onClockChanged(clock);
+ mMainHandler.post(() -> listener.onClockChanged(
+ clock instanceof DefaultClockController ? null : clock));
}
});
}
@@ -322,7 +323,7 @@
mClocks.put(plugin.getClass().getName(), plugin);
mClockInfo.add(ClockInfo.builder()
.setName(plugin.getName())
- .setTitle(plugin.getTitle())
+ .setTitle(plugin::getTitle)
.setId(id)
.setThumbnail(plugin::getThumbnail)
.setPreview(() -> plugin.getPreview(mWidth, mHeight))
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 75231448..0278258 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -51,8 +51,8 @@
import java.io.PrintWriter;
import java.util.BitSet;
-import java.util.Objects;
import java.util.List;
+import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -556,8 +556,8 @@
// If this is the data subscription, update the currentState data name
if (mCurrentState.networkNameData.equals(mNetworkNameDefault) && mServiceState != null
&& mCurrentState.dataSim
- && !TextUtils.isEmpty(mServiceState.getDataOperatorAlphaShort())) {
- mCurrentState.networkNameData = mServiceState.getDataOperatorAlphaShort();
+ && !TextUtils.isEmpty(mServiceState.getOperatorAlphaShort())) {
+ mCurrentState.networkNameData = mServiceState.getOperatorAlphaShort();
}
notifyListenersIfNecessary();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockInfoTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockInfoTest.java
index d2b2654..4c0890a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockInfoTest.java
@@ -57,7 +57,7 @@
@Test
public void testGetTitle() {
final String title = "title";
- ClockInfo info = ClockInfo.builder().setTitle(title).build();
+ ClockInfo info = ClockInfo.builder().setTitle(() -> title).build();
assertThat(info.getTitle()).isEqualTo(title);
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockOptionsProviderTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockOptionsProviderTest.java
index 0cd6f9a..d2832fb9 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockOptionsProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockOptionsProviderTest.java
@@ -117,12 +117,12 @@
public void testQuery_listOptions() {
mClocks.add(ClockInfo.builder()
.setName("name_a")
- .setTitle("title_a")
+ .setTitle(() -> "title_a")
.setId("id_a")
.build());
mClocks.add(ClockInfo.builder()
.setName("name_b")
- .setTitle("title_b")
+ .setTitle(() -> "title_b")
.setId("id_b")
.build());
Cursor cursor = mProvider.query(mListOptionsUri, null, null, null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index aa4723a..99e5a76 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -500,7 +500,7 @@
public void testUpdateDataNetworkName() {
setupDefaultSignal();
String newDataName = "TestDataName";
- when(mServiceState.getDataOperatorAlphaShort()).thenReturn(newDataName);
+ when(mServiceState.getOperatorAlphaShort()).thenReturn(newDataName);
updateServiceState();
assertDataNetworkNameEquals(newDataName);
}
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index 7e8721d..3c953b3 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -31,6 +31,7 @@
"android.hardware.tetheroffload.control-V1.0-java",
"tethering-client",
],
+ libs: ["unsupportedappusage"],
manifest: "AndroidManifestBase.xml",
}
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
index eb0d443..7fb286b 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
@@ -17,6 +17,7 @@
import static android.Manifest.permission.NETWORK_STACK;
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
+import static android.net.ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -175,6 +176,10 @@
*/
@Deprecated
public int tether(@NonNull String iface) {
+ if (mConnector == null) {
+ Slog.wtf(TAG, "Tethering not ready yet");
+ return TETHER_ERROR_SERVICE_UNAVAIL;
+ }
try {
mConnector.tether(iface);
} catch (RemoteException e) {
@@ -191,6 +196,10 @@
*/
@Deprecated
public int untether(@NonNull String iface) {
+ if (mConnector == null) {
+ Slog.wtf(TAG, "Tethering not ready yet");
+ return TETHER_ERROR_SERVICE_UNAVAIL;
+ }
try {
mConnector.untether(iface);
} catch (RemoteException e) {
@@ -210,6 +219,10 @@
*/
@Deprecated
public int setUsbTethering(boolean enable) {
+ if (mConnector == null) {
+ Slog.wtf(TAG, "Tethering not ready yet");
+ return TETHER_ERROR_SERVICE_UNAVAIL;
+ }
try {
mConnector.setUsbTethering(enable);
} catch (RemoteException e) {
@@ -227,6 +240,10 @@
// TODO: improve the usage of ResultReceiver, b/145096122
public void startTethering(int type, @NonNull ResultReceiver receiver,
boolean showProvisioningUi) {
+ if (mConnector == null) {
+ Slog.wtf(TAG, "Tethering not ready yet");
+ return;
+ }
try {
mConnector.startTethering(type, receiver, showProvisioningUi);
} catch (RemoteException e) {
@@ -241,6 +258,10 @@
* {@hide}
*/
public void stopTethering(int type) {
+ if (mConnector == null) {
+ Slog.wtf(TAG, "Tethering not ready yet");
+ return;
+ }
try {
mConnector.stopTethering(type);
} catch (RemoteException e) {
@@ -258,6 +279,10 @@
// TODO: improve the usage of ResultReceiver, b/145096122
public void requestLatestTetheringEntitlementResult(int type, @NonNull ResultReceiver receiver,
boolean showEntitlementUi) {
+ if (mConnector == null) {
+ Slog.wtf(TAG, "Tethering not ready yet");
+ return;
+ }
try {
mConnector.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
} catch (RemoteException e) {
diff --git a/services/Android.bp b/services/Android.bp
index ef40a35..3b56607 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -1,3 +1,37 @@
+filegroup {
+ name: "services-main-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//visibility:private"],
+}
+
+filegroup {
+ name: "services-sources",
+ srcs: [
+ ":services.core-sources",
+ ":services.accessibility-sources",
+ ":services.appprediction-sources",
+ ":services.appwidget-sources",
+ ":services.autofill-sources",
+ ":services.backup-sources",
+ ":services.companion-sources",
+ ":services.contentcapture-sources",
+ ":services.contentsuggestions-sources",
+ ":services.coverage-sources",
+ ":services.devicepolicy-sources",
+ ":services.midi-sources",
+ ":services.net-sources",
+ ":services.print-sources",
+ ":services.restrictions-sources",
+ ":services.startop.iorap-sources",
+ ":services.systemcaptions-sources",
+ ":services.usage-sources",
+ ":services.usb-sources",
+ ":services.voiceinteraction-sources",
+ ],
+ visibility: ["//visibility:private"],
+}
+
// merge all required services into one jar
// ============================================================
java_library {
@@ -9,9 +43,7 @@
profile: "art-profile",
},
- srcs: [
- "java/**/*.java",
- ],
+ srcs: [":services-main-sources"],
// The convention is to name each service module 'services.$(module_name)'
static_libs: [
diff --git a/services/accessibility/Android.bp b/services/accessibility/Android.bp
index f991d7b..284a2f2 100644
--- a/services/accessibility/Android.bp
+++ b/services/accessibility/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.accessibility-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.accessibility",
- srcs: ["java/**/*.java"],
+ srcs: [":services.accessibility-sources"],
libs: ["services.core"],
}
diff --git a/services/appprediction/Android.bp b/services/appprediction/Android.bp
index a7be587..e14e1df 100644
--- a/services/appprediction/Android.bp
+++ b/services/appprediction/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.appprediction-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.appprediction",
- srcs: ["java/**/*.java"],
+ srcs: [":services.appprediction-sources"],
libs: ["services.core"],
}
diff --git a/services/appwidget/Android.bp b/services/appwidget/Android.bp
index aad2ad19..54cf6ce 100644
--- a/services/appwidget/Android.bp
+++ b/services/appwidget/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.appwidget-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.appwidget",
- srcs: ["java/**/*.java"],
+ srcs: [":services.appwidget-sources"],
libs: ["services.core"],
}
diff --git a/services/autofill/Android.bp b/services/autofill/Android.bp
index 2768c18..539eb1a 100644
--- a/services/autofill/Android.bp
+++ b/services/autofill/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.autofill-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.autofill",
- srcs: ["java/**/*.java"],
+ srcs: [":services.autofill-sources"],
libs: ["services.core"],
}
diff --git a/services/backup/Android.bp b/services/backup/Android.bp
index ef03d83..f945d0f 100644
--- a/services/backup/Android.bp
+++ b/services/backup/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.backup-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.backup",
- srcs: ["java/**/*.java"],
+ srcs: [":services.backup-sources"],
libs: ["services.core"],
}
diff --git a/services/companion/Android.bp b/services/companion/Android.bp
index d2dac35..9677a7d 100644
--- a/services/companion/Android.bp
+++ b/services/companion/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.companion-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.companion",
- srcs: ["java/**/*.java"],
+ srcs: [":services.companion-sources"],
libs: ["services.core"],
}
diff --git a/services/contentcapture/Android.bp b/services/contentcapture/Android.bp
index 57e859e..96e2072 100644
--- a/services/contentcapture/Android.bp
+++ b/services/contentcapture/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.contentcapture-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.contentcapture",
- srcs: ["java/**/*.java"],
+ srcs: [":services.contentcapture-sources"],
libs: ["services.core"],
}
diff --git a/services/contentsuggestions/Android.bp b/services/contentsuggestions/Android.bp
index fc09d2e..d17f06f 100644
--- a/services/contentsuggestions/Android.bp
+++ b/services/contentsuggestions/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.contentsuggestions-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.contentsuggestions",
- srcs: ["java/**/*.java"],
+ srcs: [":services.contentsuggestions-sources"],
libs: ["services.core"],
-}
\ No newline at end of file
+}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 4e75e00..725303d 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -1,24 +1,21 @@
+filegroup {
+ name: "services.core-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.core.unboosted",
-
- aidl: {
- include_dirs: [
- "frameworks/base/cmds/idmap2/idmap2d/aidl",
- "frameworks/native/aidl/binder",
- "frameworks/native/cmds/dumpstate/binder",
- "system/core/storaged/binder",
- "system/vold/binder",
- "system/gsid/aidl",
- ],
- },
srcs: [
"java/**/*.java",
":dumpstate_aidl",
+ ":framework_native_aidl",
+ ":gsiservice_aidl",
":idmap2_aidl",
":installd_aidl",
":storaged_aidl",
":vold_aidl",
- ":gsiservice_aidl",
":platform-compat-config",
"java/com/android/server/EventLogTags.logtags",
"java/com/android/server/am/EventLogTags.logtags",
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 798a4c6..cdfd310 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -613,22 +613,7 @@
}
public boolean isEnabled() {
- if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
- Slog.w(TAG, "isEnabled(): not allowed for non-active and non system user");
- return false;
- }
-
- try {
- mBluetoothLock.readLock().lock();
- if (mBluetooth != null) {
- return mBluetooth.isEnabled();
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "isEnabled()", e);
- } finally {
- mBluetoothLock.readLock().unlock();
- }
- return false;
+ return getState() == BluetoothAdapter.STATE_ON;
}
public int getState() {
@@ -1766,14 +1751,8 @@
//Do enable request
try {
- if (!mQuietEnable) {
- if (!mBluetooth.enable()) {
- Slog.e(TAG, "IBluetooth.enable() returned false");
- }
- } else {
- if (!mBluetooth.enableNoAutoConnect()) {
- Slog.e(TAG, "IBluetooth.enableNoAutoConnect() returned false");
- }
+ if (!mBluetooth.enable(mQuietEnable)) {
+ Slog.e(TAG, "IBluetooth.enable() returned false");
}
} catch (RemoteException e) {
Slog.e(TAG, "Unable to call enable()", e);
@@ -2048,14 +2027,8 @@
} else if (mBluetooth != null) {
//Enable bluetooth
try {
- if (!mQuietEnable) {
- if (!mBluetooth.enable()) {
- Slog.e(TAG, "IBluetooth.enable() returned false");
- }
- } else {
- if (!mBluetooth.enableNoAutoConnect()) {
- Slog.e(TAG, "IBluetooth.enableNoAutoConnect() returned false");
- }
+ if (!mBluetooth.enable(mQuietEnable)) {
+ Slog.e(TAG, "IBluetooth.enable() returned false");
}
} catch (RemoteException e) {
Slog.e(TAG, "Unable to call enable()", e);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 753c117..b719435 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -5573,7 +5573,7 @@
* @param linkProperties the initial link properties of this network. They can be updated
* later : see {@link #updateLinkProperties}.
* @param networkCapabilities the initial capabilites of this network. They can be updated
- * later : see {@link #updateNetworkCapabilities}.
+ * later : see {@link #updateCapabilities}.
* @param currentScore the initial score of the network. See
* {@link NetworkAgentInfo#getCurrentScore}.
* @param networkMisc metadata about the network. This is never updated.
@@ -5596,7 +5596,7 @@
ns, mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd,
mDnsResolver, mNMS, factorySerialNumber);
// Make sure the network capabilities reflect what the agent info says.
- nai.setNetworkCapabilities(mixInCapabilities(nai, nc));
+ nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc));
final String extraInfo = networkInfo.getExtraInfo();
final String name = TextUtils.isEmpty(extraInfo)
? nai.networkCapabilities.getSSID() : extraInfo;
@@ -5950,11 +5950,7 @@
}
}
- final NetworkCapabilities prevNc;
- synchronized (nai) {
- prevNc = nai.networkCapabilities;
- nai.setNetworkCapabilities(newNc);
- }
+ final NetworkCapabilities prevNc = nai.getAndSetNetworkCapabilities(newNc);
updateUids(nai, prevNc, newNc);
@@ -5963,7 +5959,7 @@
// the change we're processing can't affect any requests, it can only affect the listens
// on this network. We might have been called by rematchNetworkAndRequests when a
// network changed foreground state.
- processListenRequests(nai, true);
+ processListenRequests(nai);
} else {
// If the requestable capabilities have changed or the score changed, we can't have been
// called by rematchNetworkAndRequests, so it's safe to start a rematch.
@@ -6271,8 +6267,14 @@
updateAllVpnsCapabilities();
}
- private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) {
+ private void processListenRequests(@NonNull final NetworkAgentInfo nai) {
// For consistency with previous behaviour, send onLost callbacks before onAvailable.
+ processNewlyLostListenRequests(nai);
+ notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
+ processNewlySatisfiedListenRequests(nai);
+ }
+
+ private void processNewlyLostListenRequests(@NonNull final NetworkAgentInfo nai) {
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
NetworkRequest nr = nri.request;
if (!nr.isListen()) continue;
@@ -6281,11 +6283,9 @@
callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_LOST, 0);
}
}
+ }
- if (capabilitiesChanged) {
- notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
- }
-
+ private void processNewlySatisfiedListenRequests(@NonNull final NetworkAgentInfo nai) {
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
NetworkRequest nr = nri.request;
if (!nr.isListen()) continue;
@@ -6468,19 +6468,20 @@
// before LegacyTypeTracker sends legacy broadcasts
for (NetworkRequestInfo nri : addedRequests) notifyNetworkAvailable(newNetwork, nri);
- // Second pass: process all listens.
- if (wasBackgroundNetwork != newNetwork.isBackgroundNetwork()) {
- // TODO : most of the following is useless because the only thing that changed
- // here is whether the network is a background network. Clean this up.
+ // Finally, process listen requests and update capabilities if the background state has
+ // changed for this network. For consistency with previous behavior, send onLost callbacks
+ // before onAvailable.
+ processNewlyLostListenRequests(newNetwork);
- NetworkCapabilities newNc = mixInCapabilities(newNetwork,
+ // Maybe the network changed background states. Update its capabilities.
+ final boolean backgroundChanged = wasBackgroundNetwork != newNetwork.isBackgroundNetwork();
+ if (backgroundChanged) {
+ final NetworkCapabilities newNc = mixInCapabilities(newNetwork,
newNetwork.networkCapabilities);
- if (Objects.equals(newNetwork.networkCapabilities, newNc)) return;
-
final int oldPermission = getNetworkPermission(newNetwork.networkCapabilities);
final int newPermission = getNetworkPermission(newNc);
- if (oldPermission != newPermission && newNetwork.created && !newNetwork.isVPN()) {
+ if (oldPermission != newPermission) {
try {
mNMS.setNetworkPermission(newNetwork.network.netId, newPermission);
} catch (RemoteException e) {
@@ -6488,53 +6489,11 @@
}
}
- final NetworkCapabilities prevNc;
- synchronized (newNetwork) {
- prevNc = newNetwork.networkCapabilities;
- newNetwork.setNetworkCapabilities(newNc);
- }
-
- updateUids(newNetwork, prevNc, newNc);
-
- if (newNetwork.getCurrentScore() == score
- && newNc.equalRequestableCapabilities(prevNc)) {
- // If the requestable capabilities haven't changed, and the score hasn't changed,
- // then the change we're processing can't affect any requests, it can only affect
- // the listens on this network.
- processListenRequests(newNetwork, true);
- } else {
- rematchAllNetworksAndRequests();
- notifyNetworkCallbacks(newNetwork, ConnectivityManager.CALLBACK_CAP_CHANGED);
- }
-
- if (prevNc != null) {
- final boolean oldMetered = prevNc.isMetered();
- final boolean newMetered = newNc.isMetered();
- final boolean meteredChanged = oldMetered != newMetered;
-
- if (meteredChanged) {
- maybeNotifyNetworkBlocked(newNetwork, oldMetered, newMetered,
- mRestrictBackground, mRestrictBackground);
- }
-
- final boolean roamingChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING)
- != newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING);
-
- // Report changes that are interesting for network statistics tracking.
- if (meteredChanged || roamingChanged) {
- notifyIfacesChangedForNetworkStats();
- }
- }
-
- if (!newNc.hasTransport(TRANSPORT_VPN)) {
- // Tell VPNs about updated capabilities, since they may need to
- // bubble those changes through.
- updateAllVpnsCapabilities();
- }
-
- } else {
- processListenRequests(newNetwork, false);
+ newNetwork.getAndSetNetworkCapabilities(newNc);
+ notifyNetworkCallbacks(newNetwork, ConnectivityManager.CALLBACK_CAP_CHANGED);
}
+
+ processNewlySatisfiedListenRequests(newNetwork);
}
/**
@@ -6719,9 +6678,8 @@
// NetworkCapabilities need to be set before sending the private DNS config to
// NetworkMonitor, otherwise NetworkMonitor cannot determine if validation is required.
- synchronized (networkAgent) {
- networkAgent.setNetworkCapabilities(networkAgent.networkCapabilities);
- }
+ networkAgent.getAndSetNetworkCapabilities(networkAgent.networkCapabilities);
+
handlePerNetworkPrivateDnsConfig(networkAgent, mDnsManager.getPrivateDnsConfig());
updateLinkProperties(networkAgent, new LinkProperties(networkAgent.linkProperties),
null);
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index e79a289..0d496b6 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.Manifest.permission.OBSERVE_NETWORK_POLICY;
import static android.Manifest.permission.SHUTDOWN;
@@ -57,6 +58,7 @@
import android.net.NetworkStats;
import android.net.NetworkUtils;
import android.net.RouteInfo;
+import android.net.TetherConfigParcel;
import android.net.TetherStatsParcel;
import android.net.UidRange;
import android.net.UidRangeParcel;
@@ -737,7 +739,9 @@
//
@Override
public String[] listInterfaces() {
- NetworkStack.checkNetworkStackPermission(mContext);
+ // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
+ // APIs.
+ NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
try {
return mNetdService.interfaceGetList();
} catch (RemoteException | ServiceSpecificException e) {
@@ -787,7 +791,9 @@
@Override
public InterfaceConfiguration getInterfaceConfig(String iface) {
- NetworkStack.checkNetworkStackPermission(mContext);
+ // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
+ // APIs.
+ NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
final InterfaceConfigurationParcel result;
try {
result = mNetdService.interfaceGetCfg(iface);
@@ -805,7 +811,9 @@
@Override
public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
- NetworkStack.checkNetworkStackPermission(mContext);
+ // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
+ // APIs.
+ NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
LinkAddress linkAddr = cfg.getLinkAddress();
if (linkAddr == null || linkAddr.getAddress() == null) {
throw new IllegalStateException("Null LinkAddress given");
@@ -1016,7 +1024,10 @@
NetworkStack.checkNetworkStackPermission(mContext);
// an odd number of addrs will fail
try {
- mNetdService.tetherStartWithConfiguration(usingLegacyDnsProxy, dhcpRange);
+ final TetherConfigParcel config = new TetherConfigParcel();
+ config.usingLegacyDnsProxy = usingLegacyDnsProxy;
+ config.dhcpRanges = dhcpRange;
+ mNetdService.tetherStartWithConfiguration(config);
} catch (RemoteException | ServiceSpecificException e) {
throw new IllegalStateException(e);
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 950e9cb..92f6241 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -71,7 +71,6 @@
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.IPhoneStateListener;
import com.android.internal.telephony.ITelephonyRegistry;
-import com.android.internal.telephony.PhoneConstantConversions;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyPermissions;
@@ -356,7 +355,7 @@
SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
SubscriptionManager.getDefaultSubscriptionId());
int newDefaultPhoneId = intent.getIntExtra(
- PhoneConstants.PHONE_KEY,
+ SubscriptionManager.EXTRA_SLOT_INDEX,
SubscriptionManager.getPhoneId(newDefaultSubId));
if (DBG) {
log("onReceive:current mDefaultSubId=" + mDefaultSubId
@@ -445,9 +444,9 @@
mOtaspMode[i] = TelephonyManager.OTASP_UNKNOWN;
mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
- mCallQuality[i] = new CallQuality();
+ mCallQuality[i] = createCallQuality();
mCallAttributes[i] = new CallAttributes(new PreciseCallState(),
- TelephonyManager.NETWORK_TYPE_UNKNOWN, new CallQuality());
+ TelephonyManager.NETWORK_TYPE_UNKNOWN, createCallQuality());
mCallNetworkType[i] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
mPreciseCallState[i] = new PreciseCallState();
mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
@@ -540,9 +539,9 @@
mOtaspMode[i] = TelephonyManager.OTASP_UNKNOWN;
mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
- mCallQuality[i] = new CallQuality();
+ mCallQuality[i] = createCallQuality();
mCallAttributes[i] = new CallAttributes(new PreciseCallState(),
- TelephonyManager.NETWORK_TYPE_UNKNOWN, new CallQuality());
+ TelephonyManager.NETWORK_TYPE_UNKNOWN, createCallQuality());
mCallNetworkType[i] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
mPreciseCallState[i] = new PreciseCallState();
mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
@@ -1559,8 +1558,6 @@
}
broadcastDataConnectionStateChanged(state, isDataAllowed, apn, apnType, linkProperties,
networkCapabilities, roaming, subId);
- broadcastPreciseDataConnectionStateChanged(state, networkType, apnType, apn,
- linkProperties, DataFailCause.NONE);
}
public void notifyDataConnectionFailed(String apnType) {
@@ -1600,9 +1597,6 @@
handleRemoveListLocked();
}
broadcastDataConnectionFailed(apnType, subId);
- broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
- TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, null, null,
- DataFailCause.NONE);
}
public void notifyCellLocation(Bundle cellLocation) {
@@ -1692,7 +1686,7 @@
if (mPreciseCallState[phoneId].getForegroundCallState()
!= PreciseCallState.PRECISE_CALL_STATE_ACTIVE) {
mCallNetworkType[phoneId] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
- mCallQuality[phoneId] = new CallQuality();
+ mCallQuality[phoneId] = createCallQuality();
}
mCallAttributes[phoneId] = new CallAttributes(mPreciseCallState[phoneId],
mCallNetworkType[phoneId], mCallQuality[phoneId]);
@@ -1720,8 +1714,6 @@
}
handleRemoveListLocked();
}
- broadcastPreciseCallStateChanged(ringingCallState, foregroundCallState,
- backgroundCallState);
}
public void notifyDisconnectCause(int phoneId, int subId, int disconnectCause,
@@ -1803,8 +1795,6 @@
handleRemoveListLocked();
}
- broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
- TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, apn, null, failCause);
}
@Override
@@ -2134,6 +2124,16 @@
// the legacy intent broadcasting
//
+ // Legacy intent action.
+ /** Fired when a subscription's phone state changes. */
+ private static final String ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED =
+ "android.intent.action.SUBSCRIPTION_PHONE_STATE";
+
+ // Legacy intent extra keys, copied from PhoneConstants.
+ // Used in legacy intents sent here, for backward compatibility.
+ private static final String PHONE_CONSTANTS_SLOT_KEY = "slot";
+ private static final String PHONE_CONSTANTS_SUBSCRIPTION_KEY = "subscription";
+
private void broadcastServiceStateChanged(ServiceState state, int phoneId, int subId) {
long ident = Binder.clearCallingIdentity();
try {
@@ -2150,9 +2150,10 @@
state.fillInNotifierBundle(data);
intent.putExtras(data);
// Pass the subscription along with the intent.
- intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+ intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId);
intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
- intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
+ intent.putExtra(PHONE_CONSTANTS_SLOT_KEY, phoneId);
+ intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, phoneId);
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
@@ -2171,8 +2172,8 @@
Bundle data = new Bundle();
signalStrength.fillInNotifierBundle(data);
intent.putExtras(data);
- intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
- intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
+ intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId);
+ intent.putExtra(PHONE_CONSTANTS_SLOT_KEY, phoneId);
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
@@ -2202,19 +2203,19 @@
}
Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
- intent.putExtra(PhoneConstants.STATE_KEY,
- PhoneConstantConversions.convertCallState(state).toString());
+ intent.putExtra(TelephonyManager.EXTRA_STATE, callStateToString(state));
// If a valid subId was specified, we should fire off a subId-specific state
// change intent and include the subId.
if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- intent.setAction(PhoneConstants.ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED);
- intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+ intent.setAction(ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED);
+ intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId);
intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
}
// If the phoneId is invalid, the broadcast is for overall call state.
if (phoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
- intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
+ intent.putExtra(PHONE_CONSTANTS_SLOT_KEY, phoneId);
+ intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, phoneId);
}
// Wakeup apps for the (SUBSCRIPTION_)PHONE_STATE broadcast.
@@ -2236,6 +2237,18 @@
android.Manifest.permission.READ_CALL_LOG});
}
+ /** Converts TelephonyManager#CALL_STATE_* to TelephonyManager#EXTRA_STATE_*. */
+ private static String callStateToString(int callState) {
+ switch (callState) {
+ case TelephonyManager.CALL_STATE_RINGING:
+ return TelephonyManager.EXTRA_STATE_RINGING;
+ case TelephonyManager.CALL_STATE_OFFHOOK:
+ return TelephonyManager.EXTRA_STATE_OFFHOOK;
+ default:
+ return TelephonyManager.EXTRA_STATE_IDLE;
+ }
+ }
+
private void broadcastDataConnectionStateChanged(int state, boolean isDataAllowed, String apn,
String apnType, LinkProperties linkProperties,
NetworkCapabilities networkCapabilities,
@@ -2244,8 +2257,7 @@
// status bar takes care of that after taking into account all of the
// required info.
Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
- intent.putExtra(PhoneConstants.STATE_KEY,
- PhoneConstantConversions.convertDataState(state).toString());
+ intent.putExtra(TelephonyManager.EXTRA_STATE, dataStateToString(state));
if (!isDataAllowed) {
intent.putExtra(PhoneConstants.NETWORK_UNAVAILABLE_KEY, true);
}
@@ -2263,44 +2275,17 @@
intent.putExtra(PhoneConstants.DATA_APN_KEY, apn);
intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
- intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+ intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId);
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
private void broadcastDataConnectionFailed(String apnType, int subId) {
Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
- intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+ intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId);
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
- private void broadcastPreciseCallStateChanged(int ringingCallState, int foregroundCallState,
- int backgroundCallState) {
- Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_CALL_STATE_CHANGED);
- intent.putExtra(TelephonyManager.EXTRA_RINGING_CALL_STATE, ringingCallState);
- intent.putExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, foregroundCallState);
- intent.putExtra(TelephonyManager.EXTRA_BACKGROUND_CALL_STATE, backgroundCallState);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
- android.Manifest.permission.READ_PRECISE_PHONE_STATE);
- }
-
- private void broadcastPreciseDataConnectionStateChanged(int state, int networkType,
- String apnType, String apn, LinkProperties linkProperties,
- @DataFailureCause int failCause) {
- Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED);
- intent.putExtra(PhoneConstants.STATE_KEY, state);
- intent.putExtra(PhoneConstants.DATA_NETWORK_TYPE_KEY, networkType);
- if (apnType != null) intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
- if (apn != null) intent.putExtra(PhoneConstants.DATA_APN_KEY, apn);
- if (linkProperties != null) {
- intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties);
- }
- intent.putExtra(PhoneConstants.DATA_FAILURE_CAUSE_KEY, failCause);
-
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
- android.Manifest.permission.READ_PRECISE_PHONE_STATE);
- }
-
private void enforceNotifyPermissionOrCarrierPrivilege(String method) {
if (checkNotifyPermission()) {
return;
@@ -2629,11 +2614,11 @@
}
/**
- * Convert data state to string
+ * Convert TelephonyManager.DATA_* to string.
*
* @return The data state in string format.
*/
- private String dataStateToString(@TelephonyManager.DataState int state) {
+ private static String dataStateToString(int state) {
switch (state) {
case TelephonyManager.DATA_DISCONNECTED: return "DISCONNECTED";
case TelephonyManager.DATA_CONNECTING: return "CONNECTING";
@@ -2696,4 +2681,9 @@
return "UNKNOWN";
}
}
+
+ /** Returns a new CallQuality object with default values. */
+ private static CallQuality createCallQuality() {
+ return new CallQuality(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ }
}
diff --git a/services/core/java/com/android/server/ZramWriteback.java b/services/core/java/com/android/server/ZramWriteback.java
index 49bf29b..5d97def 100644
--- a/services/core/java/com/android/server/ZramWriteback.java
+++ b/services/core/java/com/android/server/ZramWriteback.java
@@ -60,6 +60,7 @@
private static final String MARK_IDLE_DELAY_PROP = "ro.zram.mark_idle_delay_mins";
private static final String FIRST_WB_DELAY_PROP = "ro.zram.first_wb_delay_mins";
private static final String PERIODIC_WB_DELAY_PROP = "ro.zram.periodic_wb_delay_hours";
+ private static final String FORCE_WRITEBACK_PROP = "zram.force_writeback";
private void markPagesAsIdle() {
String idlePath = String.format(IDLE_SYS, sZramDeviceId);
@@ -122,11 +123,12 @@
private static void schedNextWriteback(Context context) {
int nextWbDelay = SystemProperties.getInt(PERIODIC_WB_DELAY_PROP, 24);
+ boolean forceWb = SystemProperties.getBoolean(FORCE_WRITEBACK_PROP, false);
JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
js.schedule(new JobInfo.Builder(WRITEBACK_IDLE_JOB_ID, sZramWriteback)
.setMinimumLatency(TimeUnit.HOURS.toMillis(nextWbDelay))
- .setRequiresDeviceIdle(true)
+ .setRequiresDeviceIdle(!forceWb)
.build());
}
@@ -167,6 +169,7 @@
public static void scheduleZramWriteback(Context context) {
int markIdleDelay = SystemProperties.getInt(MARK_IDLE_DELAY_PROP, 20);
int firstWbDelay = SystemProperties.getInt(FIRST_WB_DELAY_PROP, 180);
+ boolean forceWb = SystemProperties.getBoolean(FORCE_WRITEBACK_PROP, false);
JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
@@ -182,7 +185,7 @@
// by ro.zram.periodic_wb_delay_hours.
js.schedule(new JobInfo.Builder(WRITEBACK_IDLE_JOB_ID, sZramWriteback)
.setMinimumLatency(TimeUnit.MINUTES.toMillis(firstWbDelay))
- .setRequiresDeviceIdle(true)
+ .setRequiresDeviceIdle(!forceWb)
.build());
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5ffdf02..35774ed 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2411,7 +2411,8 @@
mConstants = hasHandlerThread
? new ActivityManagerConstants(mContext, this, mHandler) : null;
final ActiveUids activeUids = new ActiveUids(this, false /* postChangesToAtm */);
- mProcessList.init(this, activeUids);
+ mPlatformCompat = null;
+ mProcessList.init(this, activeUids, mPlatformCompat);
mLowMemDetector = null;
mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);
@@ -2432,7 +2433,6 @@
mProcStartHandler = null;
mHiddenApiBlacklist = null;
mFactoryTest = FACTORY_TEST_OFF;
- mPlatformCompat = null;
}
// Note: This method is invoked on the main thread but may need to attach various
@@ -2461,7 +2461,9 @@
mConstants = new ActivityManagerConstants(mContext, this, mHandler);
final ActiveUids activeUids = new ActiveUids(this, true /* postChangesToAtm */);
- mProcessList.init(this, activeUids);
+ mPlatformCompat = (PlatformCompat) ServiceManager.getService(
+ Context.PLATFORM_COMPAT_SERVICE);
+ mProcessList.init(this, activeUids, mPlatformCompat);
mLowMemDetector = new LowMemDetector(this);
mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);
@@ -2569,9 +2571,6 @@
mHiddenApiBlacklist = new HiddenApiSettings(mHandler, mContext);
- mPlatformCompat = (PlatformCompat) ServiceManager.getService(
- Context.PLATFORM_COMPAT_SERVICE);
-
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
@@ -5048,9 +5047,7 @@
bindApplicationTimeMillis = SystemClock.elapsedRealtime();
mAtmInternal.preBindApplication(app.getWindowProcessController());
final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
- long[] disabledCompatChanges = {};
if (mPlatformCompat != null) {
- disabledCompatChanges = mPlatformCompat.getDisabledChanges(app.info);
mPlatformCompat.resetReporting(app.info);
}
if (app.isolatedEntryPoint != null) {
@@ -5069,7 +5066,7 @@
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
- disabledCompatChanges);
+ app.mDisabledCompatChanges);
} else {
thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
null, null, null, testMode,
@@ -5079,7 +5076,7 @@
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
- disabledCompatChanges);
+ app.mDisabledCompatChanges);
}
if (profilerInfo != null) {
profilerInfo.closeFd();
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 59070c7..b406ce6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -2875,6 +2875,12 @@
final PlatformCompat platformCompat = (PlatformCompat)
ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
String toggleValue = getNextArgRequired();
+ if (toggleValue.equals("reset-all")) {
+ final String packageName = getNextArgRequired();
+ pw.println("Reset all changes for " + packageName + " to default value.");
+ platformCompat.clearOverrides(packageName);
+ return 0;
+ }
long changeId;
String changeIdString = getNextArgRequired();
try {
@@ -3233,9 +3239,14 @@
pw.println(" without restarting any processes.");
pw.println(" write");
pw.println(" Write all pending state to storage.");
- pw.println(" compat enable|disable|reset <CHANGE_ID|CHANGE_NAME> <PACKAGE_NAME>");
- pw.println(" Toggles a change either by id or by name for <PACKAGE_NAME>.");
- pw.println(" It kills <PACKAGE_NAME> (to allow the toggle to take effect).");
+ pw.println(" compat [COMMAND] [...]: sub-commands for toggling app-compat changes.");
+ pw.println(" enable|disable|reset <CHANGE_ID|CHANGE_NAME> <PACKAGE_NAME>");
+ pw.println(" Toggles a change either by id or by name for <PACKAGE_NAME>.");
+ pw.println(" It kills <PACKAGE_NAME> (to allow the toggle to take effect).");
+ pw.println(" reset-all <PACKAGE_NAME>");
+ pw.println(" Removes all existing overrides for all changes for ");
+ pw.println(" <PACKAGE_NAME> (back to default behaviour).");
+ pw.println(" It kills <PACKAGE_NAME> (to allow the toggle to take effect).");
pw.println();
Intent.printIntentArgsHelp(pw, "");
}
diff --git a/services/core/java/com/android/server/am/LmkdConnection.java b/services/core/java/com/android/server/am/LmkdConnection.java
new file mode 100644
index 0000000..cacf676
--- /dev/null
+++ b/services/core/java/com/android/server/am/LmkdConnection.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
+import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
+
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
+import android.os.MessageQueue;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import libcore.io.IoUtils;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+/**
+ * Lmkd connection to communicate with lowmemorykiller daemon.
+ */
+public class LmkdConnection {
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "LmkdConnection" : TAG_AM;
+
+ // lmkd reply max size in bytes
+ private static final int LMKD_REPLY_MAX_SIZE = 12;
+
+ // connection listener interface
+ interface LmkdConnectionListener {
+ boolean onConnect(OutputStream ostream);
+ void onDisconnect();
+ /**
+ * Check if received reply was expected (reply to an earlier request)
+ *
+ * @param replyBuf The buffer provided in exchange() to receive the reply.
+ * It can be used by exchange() caller to store reply-specific
+ * tags for later use in isReplyExpected() to verify if
+ * received packet is the expected reply.
+ * @param dataReceived The buffer holding received data
+ * @param receivedLen Size of the data received
+ */
+ boolean isReplyExpected(ByteBuffer replyBuf, ByteBuffer dataReceived,
+ int receivedLen);
+
+ /**
+ * Handle the received message if it's unsolicited.
+ *
+ * @param dataReceived The buffer holding received data
+ * @param receivedLen Size of the data received
+ * @return True if the message has been handled correctly, false otherwise.
+ */
+ boolean handleUnsolicitedMessage(ByteBuffer dataReceived, int receivedLen);
+ }
+
+ private final MessageQueue mMsgQueue;
+
+ // lmkd connection listener
+ private final LmkdConnectionListener mListener;
+
+ // mutex to synchronize access to the socket
+ private final Object mLmkdSocketLock = new Object();
+
+ // socket to communicate with lmkd
+ @GuardedBy("mLmkdSocketLock")
+ private LocalSocket mLmkdSocket = null;
+
+ // socket I/O streams
+ @GuardedBy("mLmkdSocketLock")
+ private OutputStream mLmkdOutputStream = null;
+ @GuardedBy("mLmkdSocketLock")
+ private InputStream mLmkdInputStream = null;
+
+ // buffer to store incoming data
+ private final ByteBuffer mInputBuf =
+ ByteBuffer.allocate(LMKD_REPLY_MAX_SIZE);
+
+ // object to protect mReplyBuf and to wait/notify when reply is received
+ private final Object mReplyBufLock = new Object();
+
+ // reply buffer
+ @GuardedBy("mReplyBufLock")
+ private ByteBuffer mReplyBuf = null;
+
+ //////////////////// END FIELDS ////////////////////
+
+ LmkdConnection(MessageQueue msgQueue, LmkdConnectionListener listener) {
+ mMsgQueue = msgQueue;
+ mListener = listener;
+ }
+
+ boolean connect() {
+ synchronized (mLmkdSocketLock) {
+ if (mLmkdSocket != null) {
+ return true;
+ }
+ // temporary sockets and I/O streams
+ final LocalSocket socket = openSocket();
+
+ if (socket == null) {
+ Slog.w(TAG, "Failed to connect to lowmemorykiller, retry later");
+ return false;
+ }
+
+ final OutputStream ostream;
+ final InputStream istream;
+ try {
+ ostream = socket.getOutputStream();
+ istream = socket.getInputStream();
+ } catch (IOException ex) {
+ IoUtils.closeQuietly(socket);
+ return false;
+ }
+ // execute onConnect callback
+ if (mListener != null && !mListener.onConnect(ostream)) {
+ Slog.w(TAG, "Failed to communicate with lowmemorykiller, retry later");
+ IoUtils.closeQuietly(socket);
+ return false;
+ }
+ // connection established
+ mLmkdSocket = socket;
+ mLmkdOutputStream = ostream;
+ mLmkdInputStream = istream;
+ mMsgQueue.addOnFileDescriptorEventListener(mLmkdSocket.getFileDescriptor(),
+ EVENT_INPUT | EVENT_ERROR,
+ new MessageQueue.OnFileDescriptorEventListener() {
+ public int onFileDescriptorEvents(FileDescriptor fd, int events) {
+ return fileDescriptorEventHandler(fd, events);
+ }
+ }
+ );
+ mLmkdSocketLock.notifyAll();
+ }
+ return true;
+ }
+
+ private int fileDescriptorEventHandler(FileDescriptor fd, int events) {
+ if (mListener == null) {
+ return 0;
+ }
+ if ((events & EVENT_INPUT) != 0) {
+ processIncomingData();
+ }
+ if ((events & EVENT_ERROR) != 0) {
+ synchronized (mLmkdSocketLock) {
+ // stop listening on this socket
+ mMsgQueue.removeOnFileDescriptorEventListener(
+ mLmkdSocket.getFileDescriptor());
+ IoUtils.closeQuietly(mLmkdSocket);
+ mLmkdSocket = null;
+ }
+ // wake up reply waiters if any
+ synchronized (mReplyBufLock) {
+ if (mReplyBuf != null) {
+ mReplyBuf = null;
+ mReplyBufLock.notifyAll();
+ }
+ }
+ // notify listener
+ mListener.onDisconnect();
+ return 0;
+ }
+ return (EVENT_INPUT | EVENT_ERROR);
+ }
+
+ private void processIncomingData() {
+ int len = read(mInputBuf);
+ if (len > 0) {
+ synchronized (mReplyBufLock) {
+ if (mReplyBuf != null) {
+ if (mListener.isReplyExpected(mReplyBuf, mInputBuf, len)) {
+ // copy into reply buffer
+ mReplyBuf.put(mInputBuf.array(), 0, len);
+ mReplyBuf.rewind();
+ // wakeup the waiting thread
+ mReplyBufLock.notifyAll();
+ } else if (!mListener.handleUnsolicitedMessage(mInputBuf, len)) {
+ // received unexpected packet
+ // treat this as an error
+ mReplyBuf = null;
+ mReplyBufLock.notifyAll();
+ Slog.e(TAG, "Received an unexpected packet from lmkd");
+ }
+ } else if (!mListener.handleUnsolicitedMessage(mInputBuf, len)) {
+ // received asynchronous communication from lmkd
+ // but we don't recognize it.
+ Slog.w(TAG, "Received an unexpected packet from lmkd");
+ }
+ }
+ }
+ }
+
+ boolean isConnected() {
+ synchronized (mLmkdSocketLock) {
+ return (mLmkdSocket != null);
+ }
+ }
+
+ boolean waitForConnection(long timeoutMs) {
+ synchronized (mLmkdSocketLock) {
+ if (mLmkdSocket != null) {
+ return true;
+ }
+ try {
+ mLmkdSocketLock.wait(timeoutMs);
+ return (mLmkdSocket != null);
+ } catch (InterruptedException e) {
+ return false;
+ }
+ }
+ }
+
+ private LocalSocket openSocket() {
+ final LocalSocket socket;
+
+ try {
+ socket = new LocalSocket(LocalSocket.SOCKET_SEQPACKET);
+ socket.connect(
+ new LocalSocketAddress("lmkd",
+ LocalSocketAddress.Namespace.RESERVED));
+ } catch (IOException ex) {
+ Slog.e(TAG, "Connection failed: " + ex.toString());
+ return null;
+ }
+ return socket;
+ }
+
+ private boolean write(ByteBuffer buf) {
+ synchronized (mLmkdSocketLock) {
+ try {
+ mLmkdOutputStream.write(buf.array(), 0, buf.position());
+ } catch (IOException ex) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ private int read(ByteBuffer buf) {
+ synchronized (mLmkdSocketLock) {
+ try {
+ return mLmkdInputStream.read(buf.array(), 0, buf.array().length);
+ } catch (IOException ex) {
+ }
+ return -1;
+ }
+ }
+
+ /**
+ * Exchange a request/reply packets with lmkd
+ *
+ * @param req The buffer holding the request data to be sent
+ * @param repl The buffer to receive the reply
+ */
+ public boolean exchange(ByteBuffer req, ByteBuffer repl) {
+ if (repl == null) {
+ return write(req);
+ }
+
+ boolean result = false;
+ // set reply buffer to user-defined one to fill it
+ synchronized (mReplyBufLock) {
+ mReplyBuf = repl;
+
+ if (write(req)) {
+ try {
+ // wait for the reply
+ mReplyBufLock.wait();
+ result = (mReplyBuf != null);
+ } catch (InterruptedException ie) {
+ result = false;
+ }
+ }
+
+ // reset reply buffer
+ mReplyBuf = null;
+ }
+ return result;
+ }
+}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index a2670d8..3b8d39b 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -57,8 +57,6 @@
import android.content.pm.IPackageManager;
import android.content.res.Resources;
import android.graphics.Point;
-import android.net.LocalSocket;
-import android.net.LocalSocketAddress;
import android.os.AppZygote;
import android.os.Binder;
import android.os.Build;
@@ -96,17 +94,15 @@
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.Watchdog;
+import com.android.server.compat.PlatformCompat;
import com.android.server.pm.dex.DexManager;
import com.android.server.wm.ActivityServiceConnectionsHolder;
import com.android.server.wm.WindowManagerService;
import dalvik.system.VMRuntime;
-import libcore.io.IoUtils;
-
import java.io.File;
import java.io.IOException;
-import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
@@ -117,11 +113,6 @@
/**
* Activity manager code dealing with processes.
- *
- * Method naming convention:
- * <ul>
- * <li> Methods suffixed with "LS" should be called within the {@link #sLmkdSocketLock} lock.
- * </ul>
*/
public final class ProcessList {
static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessList" : TAG_AM;
@@ -262,11 +253,16 @@
// LMK_PROCREMOVE <pid>
// LMK_PROCPURGE
// LMK_GETKILLCNT
+ // LMK_PROCKILL
static final byte LMK_TARGET = 0;
static final byte LMK_PROCPRIO = 1;
static final byte LMK_PROCREMOVE = 2;
static final byte LMK_PROCPURGE = 3;
static final byte LMK_GETKILLCNT = 4;
+ static final byte LMK_PROCKILL = 5; // Note: this is an unsolicated command
+
+ // lmkd reconnect delay in msecs
+ private static final long LMKD_RECONNECT_DELAY_MS = 1000;
ActivityManagerService mService = null;
@@ -302,16 +298,9 @@
private boolean mHaveDisplaySize;
- private static Object sLmkdSocketLock = new Object();
+ private static LmkdConnection sLmkdConnection = null;
- @GuardedBy("sLmkdSocketLock")
- private static LocalSocket sLmkdSocket;
-
- @GuardedBy("sLmkdSocketLock")
- private static OutputStream sLmkdOutputStream;
-
- @GuardedBy("sLmkdSocketLock")
- private static InputStream sLmkdInputStream;
+ private boolean mOomLevelsSet = false;
/**
* Temporary to avoid allocations. Protected by main lock.
@@ -369,6 +358,12 @@
ActiveUids mActiveUids;
/**
+ * The listener who is intereted with the lmkd kills.
+ */
+ @GuardedBy("mService")
+ private LmkdKillListener mLmkdKillListener = null;
+
+ /**
* The currently running isolated processes.
*/
final SparseArray<ProcessRecord> mIsolatedProcesses = new SparseArray<>();
@@ -384,6 +379,15 @@
final ArrayMap<AppZygote, ArrayList<ProcessRecord>> mAppZygoteProcesses =
new ArrayMap<AppZygote, ArrayList<ProcessRecord>>();
+ private PlatformCompat mPlatformCompat = null;
+
+ interface LmkdKillListener {
+ /**
+ * Called when there is a process kill by lmkd.
+ */
+ void onLmkdKillOccurred(int pid, int uid);
+ }
+
final class IsolatedUidRange {
@VisibleForTesting
public final int mFirstUid;
@@ -536,6 +540,8 @@
final class KillHandler extends Handler {
static final int KILL_PROCESS_GROUP_MSG = 4000;
+ static final int LMKD_RECONNECT_MSG = 4001;
+ static final int LMKD_PROC_KILLED_MSG = 4002;
public KillHandler(Looper looper) {
super(looper, null, true);
@@ -549,6 +555,18 @@
Process.killProcessGroup(msg.arg1 /* uid */, msg.arg2 /* pid */);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
+ case LMKD_RECONNECT_MSG:
+ if (!sLmkdConnection.connect()) {
+ Slog.i(TAG, "Failed to connect to lmkd, retry after "
+ + LMKD_RECONNECT_DELAY_MS + " ms");
+ // retry after LMKD_RECONNECT_DELAY_MS
+ sKillHandler.sendMessageDelayed(sKillHandler.obtainMessage(
+ KillHandler.LMKD_RECONNECT_MSG), LMKD_RECONNECT_DELAY_MS);
+ }
+ break;
+ case LMKD_PROC_KILLED_MSG:
+ handleLmkdProcKilled(msg.arg1 /* pid */, msg.arg2 /* uid */);
+ break;
default:
super.handleMessage(msg);
@@ -565,15 +583,61 @@
updateOomLevels(0, 0, false);
}
- void init(ActivityManagerService service, ActiveUids activeUids) {
+ void init(ActivityManagerService service, ActiveUids activeUids,
+ PlatformCompat platformCompat) {
mService = service;
mActiveUids = activeUids;
+ mPlatformCompat = platformCompat;
if (sKillHandler == null) {
sKillThread = new ServiceThread(TAG + ":kill",
THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
sKillThread.start();
sKillHandler = new KillHandler(sKillThread.getLooper());
+ sLmkdConnection = new LmkdConnection(sKillThread.getLooper().getQueue(),
+ new LmkdConnection.LmkdConnectionListener() {
+ @Override
+ public boolean onConnect(OutputStream ostream) {
+ Slog.i(TAG, "Connection with lmkd established");
+ return onLmkdConnect(ostream);
+ }
+ @Override
+ public void onDisconnect() {
+ Slog.w(TAG, "Lost connection to lmkd");
+ // start reconnection after delay to let lmkd restart
+ sKillHandler.sendMessageDelayed(sKillHandler.obtainMessage(
+ KillHandler.LMKD_RECONNECT_MSG), LMKD_RECONNECT_DELAY_MS);
+ }
+ @Override
+ public boolean isReplyExpected(ByteBuffer replyBuf,
+ ByteBuffer dataReceived, int receivedLen) {
+ // compare the preambule (currently one integer) to check if
+ // this is the reply packet we are waiting for
+ return (receivedLen == replyBuf.array().length
+ && dataReceived.getInt(0) == replyBuf.getInt(0));
+ }
+
+ @Override
+ public boolean handleUnsolicitedMessage(ByteBuffer dataReceived,
+ int receivedLen) {
+ if (receivedLen < 4) {
+ return false;
+ }
+ switch (dataReceived.getInt(0)) {
+ case LMK_PROCKILL:
+ if (receivedLen != 12) {
+ return false;
+ }
+ sKillHandler.obtainMessage(KillHandler.LMKD_PROC_KILLED_MSG,
+ dataReceived.getInt(4), dataReceived.getInt(8))
+ .sendToTarget();
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+ );
}
}
@@ -679,6 +743,7 @@
writeLmkd(buf, null);
SystemProperties.set("sys.sysctl.extra_free_kbytes", Integer.toString(reserve));
+ mOomLevelsSet = true;
}
// GB: 2048,3072,4096,6144,7168,8192
// HC: 8192,10240,12288,14336,16384,20480
@@ -1218,93 +1283,50 @@
buf.putInt(LMK_GETKILLCNT);
buf.putInt(min_oom_adj);
buf.putInt(max_oom_adj);
- if (writeLmkd(buf, repl)) {
- int i = repl.getInt();
- if (i != LMK_GETKILLCNT) {
- Slog.e("ActivityManager", "Failed to get kill count, code mismatch");
- return null;
- }
+ // indicate what we are waiting for
+ repl.putInt(LMK_GETKILLCNT);
+ repl.rewind();
+ if (writeLmkd(buf, repl) && repl.getInt() == LMK_GETKILLCNT) {
return new Integer(repl.getInt());
}
return null;
}
- @GuardedBy("sLmkdSocketLock")
- private static boolean openLmkdSocketLS() {
+ boolean onLmkdConnect(OutputStream ostream) {
try {
- sLmkdSocket = new LocalSocket(LocalSocket.SOCKET_SEQPACKET);
- sLmkdSocket.connect(
- new LocalSocketAddress("lmkd",
- LocalSocketAddress.Namespace.RESERVED));
- sLmkdOutputStream = sLmkdSocket.getOutputStream();
- sLmkdInputStream = sLmkdSocket.getInputStream();
- } catch (IOException ex) {
- Slog.w(TAG, "lowmemorykiller daemon socket open failed");
- sLmkdSocket = null;
- return false;
- }
-
- return true;
- }
-
- // Never call directly, use writeLmkd() instead
- @GuardedBy("sLmkdSocketLock")
- private static boolean writeLmkdCommandLS(ByteBuffer buf) {
- try {
- sLmkdOutputStream.write(buf.array(), 0, buf.position());
- } catch (IOException ex) {
- Slog.w(TAG, "Error writing to lowmemorykiller socket");
- IoUtils.closeQuietly(sLmkdSocket);
- sLmkdSocket = null;
- return false;
- }
- return true;
- }
-
- // Never call directly, use writeLmkd() instead
- @GuardedBy("sLmkdSocketLock")
- private static boolean readLmkdReplyLS(ByteBuffer buf) {
- int len;
- try {
- len = sLmkdInputStream.read(buf.array(), 0, buf.array().length);
- if (len == buf.array().length) {
- return true;
+ // Purge any previously registered pids
+ ByteBuffer buf = ByteBuffer.allocate(4);
+ buf.putInt(LMK_PROCPURGE);
+ ostream.write(buf.array(), 0, buf.position());
+ if (mOomLevelsSet) {
+ // Reset oom_adj levels
+ buf = ByteBuffer.allocate(4 * (2 * mOomAdj.length + 1));
+ buf.putInt(LMK_TARGET);
+ for (int i = 0; i < mOomAdj.length; i++) {
+ buf.putInt((mOomMinFree[i] * 1024) / PAGE_SIZE);
+ buf.putInt(mOomAdj[i]);
+ }
+ ostream.write(buf.array(), 0, buf.position());
}
} catch (IOException ex) {
- Slog.w(TAG, "Error reading from lowmemorykiller socket");
+ return false;
}
-
- IoUtils.closeQuietly(sLmkdSocket);
- sLmkdSocket = null;
- return false;
+ return true;
}
private static boolean writeLmkd(ByteBuffer buf, ByteBuffer repl) {
- synchronized (sLmkdSocketLock) {
- for (int i = 0; i < 3; i++) {
- if (sLmkdSocket == null) {
- if (openLmkdSocketLS() == false) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException ie) {
- }
- continue;
- }
+ if (!sLmkdConnection.isConnected()) {
+ // try to connect immediately and then keep retrying
+ sKillHandler.sendMessage(
+ sKillHandler.obtainMessage(KillHandler.LMKD_RECONNECT_MSG));
- // Purge any previously registered pids
- ByteBuffer purge_buf = ByteBuffer.allocate(4);
- purge_buf.putInt(LMK_PROCPURGE);
- if (writeLmkdCommandLS(purge_buf) == false) {
- // Write failed, skip the rest and retry
- continue;
- }
- }
- if (writeLmkdCommandLS(buf) && (repl == null || readLmkdReplyLS(repl))) {
- return true;
- }
+ // wait for connection retrying 3 times (up to 3 seconds)
+ if (!sLmkdConnection.waitForConnection(3 * LMKD_RECONNECT_DELAY_MS)) {
+ return false;
}
}
- return false;
+
+ return sLmkdConnection.exchange(buf, repl);
}
static void killProcessGroup(int uid, int pid) {
@@ -1657,6 +1679,10 @@
Slog.wtf(TAG, "startProcessLocked processName:" + app.processName
+ " with non-zero pid:" + app.pid);
}
+ app.mDisabledCompatChanges = null;
+ if (mPlatformCompat != null) {
+ app.mDisabledCompatChanges = mPlatformCompat.getDisabledChanges(app.info);
+ }
final long startSeq = app.startSeq = ++mProcStartSeqCounter;
app.setStartParams(uid, hostingRecord, seInfo, startTime);
app.setUsingWrapper(invokeWith != null
@@ -1811,8 +1837,8 @@
startResult = startWebView(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
- app.info.dataDir, null, app.info.packageName,
- new String[] {PROC_START_SEQ_IDENT + app.startSeq});
+ app.info.dataDir, null, app.info.packageName, app.mDisabledCompatChanges,
+ new String[]{PROC_START_SEQ_IDENT + app.startSeq});
} else if (hostingRecord.usesAppZygote()) {
final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
@@ -1820,14 +1846,15 @@
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
- /*useUsapPool=*/ false,
- new String[] {PROC_START_SEQ_IDENT + app.startSeq});
+ /*useUsapPool=*/ false, app.mDisabledCompatChanges,
+ new String[]{PROC_START_SEQ_IDENT + app.startSeq});
} else {
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, app.info.packageName,
- new String[] {PROC_START_SEQ_IDENT + app.startSeq});
+ app.mDisabledCompatChanges,
+ new String[]{PROC_START_SEQ_IDENT + app.startSeq});
}
checkSlow(startTime, "startProcess: returned from zygote!");
return startResult;
@@ -3204,4 +3231,28 @@
mService.doStopUidLocked(uidRec.uid, uidRec);
}
}
+
+ void setLmkdKillListener(final LmkdKillListener listener) {
+ synchronized (mService) {
+ mLmkdKillListener = listener;
+ }
+ }
+
+ private void handleLmkdProcKilled(final int pid, final int uid) {
+ // Log only now
+ if (DEBUG_PROCESSES) {
+ Slog.i(TAG, "lmkd kill: pid=" + pid + " uid=" + uid);
+ }
+
+ if (mService == null) {
+ return;
+ }
+ // Notify any interesed party regarding the lmkd kills
+ synchronized (mService) {
+ final LmkdKillListener listener = mLmkdKillListener;
+ if (listener != null) {
+ mService.mHandler.post(()-> listener.onLmkdKillOccurred(pid, uid));
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index ea30842..8c1a0d3 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -307,6 +307,8 @@
long startTime;
// This will be same as {@link #uid} usually except for some apps used during factory testing.
int startUid;
+ // set of disabled compat changes for the process (all others are enabled)
+ long[] mDisabledCompatChanges;
void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo,
long startTime) {
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index a2b3574..135f199d 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -35,7 +35,6 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
-import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
@@ -45,6 +44,7 @@
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.Set;
/**
@@ -58,13 +58,10 @@
// Actual list of connected devices
// Key for map created from DeviceInfo.makeDeviceListKey()
- private final ArrayMap<String, DeviceInfo> mConnectedDevices = new ArrayMap<>();
+ private final LinkedHashMap<String, DeviceInfo> mConnectedDevices = new LinkedHashMap<>();
private @NonNull AudioDeviceBroker mDeviceBroker;
- // cache of the address of the last dock the device was connected to
- private String mDockAddress;
-
// Monitoring of audio routes. Protected by mAudioRoutes.
final AudioRoutesInfo mCurAudioRoutes = new AudioRoutesInfo();
final RemoteCallbackList<IAudioRoutesObserver> mRoutesObservers =
@@ -148,8 +145,7 @@
*/
/*package*/ void onRestoreDevices() {
synchronized (mConnectedDevices) {
- for (int i = 0; i < mConnectedDevices.size(); i++) {
- DeviceInfo di = mConnectedDevices.valueAt(i);
+ for (DeviceInfo di : mConnectedDevices.values()) {
AudioSystem.setDeviceConnectionState(
di.mDeviceType,
AudioSystem.DEVICE_STATE_AVAILABLE,
@@ -169,7 +165,7 @@
int a2dpVolume = btInfo.getVolume();
if (AudioService.DEBUG_DEVICES) {
Log.d(TAG, "onSetA2dpSinkConnectionState btDevice=" + btDevice + " state="
- + state + " is dock=" + btDevice.isBluetoothDock() + " vol=" + a2dpVolume);
+ + state + " vol=" + a2dpVolume);
}
String address = btDevice.getAddress();
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
@@ -197,42 +193,17 @@
mDeviceBroker.postBluetoothA2dpDeviceConfigChange(btDevice);
}
} else {
- if (btDevice.isBluetoothDock()) {
- if (state == BluetoothProfile.STATE_DISCONNECTED) {
- // introduction of a delay for transient disconnections of docks when
- // power is rapidly turned off/on, this message will be canceled if
- // we reconnect the dock under a preset delay
- makeA2dpDeviceUnavailableLater(address,
- AudioDeviceBroker.BTA2DP_DOCK_TIMEOUT_MS);
- // the next time isConnected is evaluated, it will be false for the dock
- }
- } else {
- makeA2dpDeviceUnavailableNow(address, di.mDeviceCodecFormat);
- }
+ makeA2dpDeviceUnavailableNow(address, di.mDeviceCodecFormat);
}
- } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
- if (btDevice.isBluetoothDock()) {
- // this could be a reconnection after a transient disconnection
- mDeviceBroker.cancelA2dpDockTimeout();
- mDockAddress = address;
- } else {
- // this could be a connection of another A2DP device before the timeout of
- // a dock: cancel the dock timeout, and make the dock unavailable now
- if (mDeviceBroker.hasScheduledA2dpDockTimeout() && mDockAddress != null) {
- mDeviceBroker.cancelA2dpDockTimeout();
- makeA2dpDeviceUnavailableNow(mDockAddress,
- AudioSystem.AUDIO_FORMAT_DEFAULT);
- }
- }
- if (a2dpVolume != -1) {
- mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC,
- // convert index to internal representation in VolumeStreamState
- a2dpVolume * 10,
- AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "onSetA2dpSinkConnectionState");
- }
- makeA2dpDeviceAvailable(address, BtHelper.getName(btDevice),
- "onSetA2dpSinkConnectionState", a2dpCodec);
}
+ if (a2dpVolume != -1) {
+ mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC,
+ // convert index to internal representation in VolumeStreamState
+ a2dpVolume * 10,
+ AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "onSetA2dpSinkConnectionState");
+ }
+ makeA2dpDeviceAvailable(address, BtHelper.getName(btDevice),
+ "onSetA2dpSinkConnectionState", a2dpCodec);
}
}
@@ -673,9 +644,6 @@
DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address));
// Remove A2DP routes as well
setCurrentAudioRouteNameIfPossible(null);
- if (mDockAddress == address) {
- mDockAddress = null;
- }
}
@GuardedBy("mConnectedDevices")
@@ -799,11 +767,10 @@
}
int delay = 0;
Set<Integer> devices = new HashSet<>();
- for (int i = 0; i < mConnectedDevices.size(); i++) {
- int dev = mConnectedDevices.valueAt(i).mDeviceType;
- if (((dev & AudioSystem.DEVICE_BIT_IN) == 0)
- && BECOMING_NOISY_INTENT_DEVICES_SET.contains(dev)) {
- devices.add(dev);
+ for (DeviceInfo di : mConnectedDevices.values()) {
+ if (((di.mDeviceType & AudioSystem.DEVICE_BIT_IN) == 0)
+ && BECOMING_NOISY_INTENT_DEVICES_SET.contains(di.mDeviceType)) {
+ devices.add(di.mDeviceType);
}
}
if (musicDevice == AudioSystem.DEVICE_NONE) {
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 9f1a6bd..36332c0 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -295,6 +295,7 @@
&& mScoAudioState != SCO_STATE_DEACTIVATE_REQ) {
mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
}
+ broadcast = false;
break;
default:
// do not broadcast CONNECTING or invalid state
diff --git a/services/core/java/com/android/server/connectivity/DataConnectionStats.java b/services/core/java/com/android/server/connectivity/DataConnectionStats.java
index 27f11ff..1b1c546 100644
--- a/services/core/java/com/android/server/connectivity/DataConnectionStats.java
+++ b/services/core/java/com/android/server/connectivity/DataConnectionStats.java
@@ -31,8 +31,6 @@
import android.util.Log;
import com.android.internal.app.IBatteryStats;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.TelephonyIntents;
import com.android.server.am.BatteryStatsService;
public class DataConnectionStats extends BroadcastReceiver {
@@ -44,7 +42,7 @@
private final Handler mListenerHandler;
private final PhoneStateListener mPhoneStateListener;
- private IccCardConstants.State mSimState = IccCardConstants.State.READY;
+ private int mSimState = TelephonyManager.SIM_STATE_READY;
private SignalStrength mSignalStrength;
private ServiceState mServiceState;
private int mDataState = TelephonyManager.DATA_DISCONNECTED;
@@ -66,7 +64,7 @@
| PhoneStateListener.LISTEN_DATA_ACTIVITY);
IntentFilter filter = new IntentFilter();
- filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+ filter.addAction(Intent.ACTION_SIM_STATE_CHANGED);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
mContext.registerReceiver(this, filter, null /* broadcastPermission */, mListenerHandler);
@@ -75,7 +73,7 @@
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
- if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
+ if (action.equals(Intent.ACTION_SIM_STATE_CHANGED)) {
updateSimState(intent);
notePhoneDataConnectionState();
} else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
@@ -88,8 +86,8 @@
if (mServiceState == null) {
return;
}
- boolean simReadyOrUnknown = mSimState == IccCardConstants.State.READY
- || mSimState == IccCardConstants.State.UNKNOWN;
+ boolean simReadyOrUnknown = mSimState == TelephonyManager.SIM_STATE_READY
+ || mSimState == TelephonyManager.SIM_STATE_UNKNOWN;
boolean visible = (simReadyOrUnknown || isCdma()) // we only check the sim state for GSM
&& hasService()
&& mDataState == TelephonyManager.DATA_CONNECTED;
@@ -105,23 +103,23 @@
}
private final void updateSimState(Intent intent) {
- String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
- if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
- mSimState = IccCardConstants.State.ABSENT;
- } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
- mSimState = IccCardConstants.State.READY;
- } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
+ String stateExtra = intent.getStringExtra(Intent.EXTRA_SIM_STATE);
+ if (Intent.SIM_STATE_ABSENT.equals(stateExtra)) {
+ mSimState = TelephonyManager.SIM_STATE_ABSENT;
+ } else if (Intent.SIM_STATE_READY.equals(stateExtra)) {
+ mSimState = TelephonyManager.SIM_STATE_READY;
+ } else if (Intent.SIM_STATE_LOCKED.equals(stateExtra)) {
final String lockedReason =
- intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
- if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
- mSimState = IccCardConstants.State.PIN_REQUIRED;
- } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
- mSimState = IccCardConstants.State.PUK_REQUIRED;
+ intent.getStringExtra(Intent.EXTRA_SIM_LOCKED_REASON);
+ if (Intent.SIM_LOCKED_ON_PIN.equals(lockedReason)) {
+ mSimState = TelephonyManager.SIM_STATE_PIN_REQUIRED;
+ } else if (Intent.SIM_LOCKED_ON_PUK.equals(lockedReason)) {
+ mSimState = TelephonyManager.SIM_STATE_PUK_REQUIRED;
} else {
- mSimState = IccCardConstants.State.NETWORK_LOCKED;
+ mSimState = TelephonyManager.SIM_STATE_NETWORK_LOCKED;
}
} else {
- mSimState = IccCardConstants.State.UNKNOWN;
+ mSimState = TelephonyManager.SIM_STATE_UNKNOWN;
}
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index bb7f862..5e085ca 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -291,13 +291,18 @@
*
* <p>If {@link NetworkMonitor#notifyNetworkCapabilitiesChanged(NetworkCapabilities)} fails,
* the exception is logged but not reported to callers.
+ *
+ * @return the old capabilities of this network.
*/
- public void setNetworkCapabilities(NetworkCapabilities nc) {
+ public synchronized NetworkCapabilities getAndSetNetworkCapabilities(
+ @NonNull final NetworkCapabilities nc) {
+ final NetworkCapabilities oldNc = networkCapabilities;
networkCapabilities = nc;
final NetworkMonitorManager nm = mNetworkMonitor;
if (nm != null) {
nm.notifyNetworkCapabilitiesChanged(nc);
}
+ return oldNc;
}
public ConnectivityService connService() {
diff --git a/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java b/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
index a91fe77..1cf27ff 100644
--- a/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
+++ b/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
@@ -231,7 +231,8 @@
// a Sim with a different mcc code was found
neededNow = false;
}
- String simOperator = mTelephonyManager.getSimOperator(info.getSubscriptionId());
+ String simOperator = mTelephonyManager
+ .createForSubscriptionId(info.getSubscriptionId()).getSimOperator();
mcc = 0;
if (simOperator != null && simOperator.length() >= 3) {
mcc = Integer.parseInt(simOperator.substring(0, 3));
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java b/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java
index 52cede2..23b5c14 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java
@@ -250,7 +250,11 @@
new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_LEFT_UP),
// No Android keycode defined for CEC_KEYCODE_LEFT_DOWN
new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_LEFT_DOWN),
+ // Both KEYCODE_HOME and KEYCODE_MENU keys are sent as CEC_KEYCODE_ROOT_MENU
+ // NOTE that the HOME key is not usually forwarded.
+ // When CEC_KEYCODE_ROOT_MENU is received, it is translated to KEYCODE_HOME
new KeycodeEntry(KeyEvent.KEYCODE_HOME, CEC_KEYCODE_ROOT_MENU),
+ new KeycodeEntry(KeyEvent.KEYCODE_MENU, CEC_KEYCODE_ROOT_MENU),
new KeycodeEntry(KeyEvent.KEYCODE_SETTINGS, CEC_KEYCODE_SETUP_MENU),
new KeycodeEntry(KeyEvent.KEYCODE_TV_CONTENTS_MENU, CEC_KEYCODE_CONTENTS_MENU, false),
// No Android keycode defined for CEC_KEYCODE_FAVORITE_MENU
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 181a435..3fc8438 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -508,8 +508,10 @@
CarrierConfigManager configManager = (CarrierConfigManager)
mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
int ddSubId = SubscriptionManager.getDefaultDataSubscriptionId();
- String mccMnc = SubscriptionManager.isValidSubscriptionId(ddSubId)
- ? phone.getSimOperator(ddSubId) : phone.getSimOperator();
+ if (SubscriptionManager.isValidSubscriptionId(ddSubId)) {
+ phone = phone.createForSubscriptionId(ddSubId);
+ }
+ String mccMnc = phone.getSimOperator();
boolean isKeepLppProfile = false;
if (!TextUtils.isEmpty(mccMnc)) {
if (DEBUG) Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc);
@@ -1903,24 +1905,17 @@
String setId = null;
int ddSubId = SubscriptionManager.getDefaultDataSubscriptionId();
+ if (SubscriptionManager.isValidSubscriptionId(ddSubId)) {
+ phone = phone.createForSubscriptionId(ddSubId);
+ }
if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
- if (SubscriptionManager.isValidSubscriptionId(ddSubId)) {
- setId = phone.getSubscriberId(ddSubId);
- }
- if (setId == null) {
- setId = phone.getSubscriberId();
- }
+ setId = phone.getSubscriberId();
if (setId != null) {
// This means the framework has the SIM card.
type = AGPS_SETID_TYPE_IMSI;
}
} else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
- if (SubscriptionManager.isValidSubscriptionId(ddSubId)) {
- setId = phone.getLine1Number(ddSubId);
- }
- if (setId == null) {
- setId = phone.getLine1Number();
- }
+ setId = phone.getLine1Number();
if (setId != null) {
// This means the framework has the SIM card.
type = AGPS_SETID_TYPE_MSISDN;
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 327b685..4db71c5 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -223,7 +223,6 @@
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.RoSystemProperties;
-import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.DumpUtils;
@@ -1650,10 +1649,10 @@
// No need to do a permission check, because the ACTION_CARRIER_CONFIG_CHANGED
// broadcast is protected and can't be spoofed. Runs on a background handler thread.
- if (!intent.hasExtra(PhoneConstants.SUBSCRIPTION_KEY)) {
+ if (!intent.hasExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX)) {
return;
}
- final int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, -1);
+ final int subId = intent.getIntExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, -1);
// Get all of our cross-process communication with telephony out of
// the way before we acquire internal locks.
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index 9b9f4de..f295ed3 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -23,7 +23,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.provider.Settings;
import android.telecom.TelecomManager;
import com.android.internal.util.NotificationMessagingUtil;
@@ -55,14 +54,9 @@
final boolean isLeftHighImportance = leftImportance >= IMPORTANCE_DEFAULT;
final boolean isRightHighImportance = rightImportance >= IMPORTANCE_DEFAULT;
- // With new interruption model, prefer importance bucket above all other criteria
- // (to ensure buckets are contiguous)
- if (Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL, 1) == 1) {
- if (isLeftHighImportance != isRightHighImportance) {
- // by importance bucket, high importance higher than low importance
- return -1 * Boolean.compare(isLeftHighImportance, isRightHighImportance);
- }
+ if (isLeftHighImportance != isRightHighImportance) {
+ // by importance bucket, high importance higher than low importance
+ return -1 * Boolean.compare(isLeftHighImportance, isRightHighImportance);
}
// first all colorized notifications
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index adcd19e..b3b0029 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -85,6 +85,9 @@
public static final int FLAG_USE_QUOTA = IInstalld.FLAG_USE_QUOTA;
public static final int FLAG_FORCE = IInstalld.FLAG_FORCE;
+ public static final int FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES =
+ IInstalld.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES;
+
private final boolean mIsolated;
private volatile IInstalld mInstalld;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index cec5c6d..7e7822c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3136,7 +3136,8 @@
// No apps are running this early, so no need to freeze
clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
- | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ | Installer.FLAG_CLEAR_CODE_CACHE_ONLY
+ | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES);
}
}
ver.fingerprint = Build.FINGERPRINT;
@@ -10222,7 +10223,9 @@
clearAppDataLeafLIF(pkg.childPackages.get(i), userId, flags);
}
- clearAppProfilesLIF(pkg, UserHandle.USER_ALL);
+ if ((flags & Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES) == 0) {
+ clearAppProfilesLIF(pkg, UserHandle.USER_ALL);
+ }
}
private void clearAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) {
@@ -17471,8 +17474,7 @@
if (new File(signaturePath).exists() && !VerityUtils.hasFsverity(filePath)) {
try {
VerityUtils.setUpFsverity(filePath, signaturePath);
- } catch (IOException | DigestException | NoSuchAlgorithmException
- | SecurityException e) {
+ } catch (IOException e) {
throw new PrepareFailure(PackageManager.INSTALL_FAILED_BAD_SIGNATURE,
"Failed to enable fs-verity: " + e);
}
@@ -22047,7 +22049,8 @@
if (!Build.FINGERPRINT.equals(ver.fingerprint)) {
clearAppDataLIF(ps.pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
- | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY
+ | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES);
}
}
}
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index fff9ec7..0caf8f8 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -50,7 +50,6 @@
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.service.sms.FinancialSmsService;
-import android.telephony.IFinancialSmsCallback;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -675,40 +674,6 @@
dumpOutputStream.flush();
}
- /**
- * Get filtered SMS messages for financial app.
- */
- @Override
- public void getSmsMessagesForFinancialApp(
- String callingPkg, Bundle params, IFinancialSmsCallback callback) {
- int mode = PermissionChecker.checkCallingOrSelfPermissionForDataDelivery(
- getContext(),
- AppOpsManager.OPSTR_SMS_FINANCIAL_TRANSACTIONS);
-
- if (mode == PermissionChecker.PERMISSION_GRANTED) {
- FinancialSmsManager financialSmsManager = new FinancialSmsManager(getContext());
- financialSmsManager.getSmsMessages(new RemoteCallback((result) -> {
- CursorWindow messages = null;
- if (result == null) {
- Slog.w(LOG_TAG, "result is null.");
- } else {
- messages = result.getParcelable(FinancialSmsService.EXTRA_SMS_MSGS);
- }
- try {
- callback.onGetSmsMessagesForFinancialApp(messages);
- } catch (RemoteException e) {
- // do nothing
- }
- }), params);
- } else {
- try {
- callback.onGetSmsMessagesForFinancialApp(null);
- } catch (RemoteException e) {
- // do nothing
- }
- }
- }
-
private int getUidForPackage(String packageName) {
long ident = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/security/VerityUtils.java b/services/core/java/com/android/server/security/VerityUtils.java
index b1db46f..856a40f 100644
--- a/services/core/java/com/android/server/security/VerityUtils.java
+++ b/services/core/java/com/android/server/security/VerityUtils.java
@@ -26,27 +26,19 @@
import android.util.apk.ApkSignatureVerifier;
import android.util.apk.ByteBufferFactory;
import android.util.apk.SignatureNotFoundException;
-import android.util.apk.VerityBuilder;
import libcore.util.HexEncoding;
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
-import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.channels.FileChannel;
import java.nio.file.Files;
-import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.DigestException;
-import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
-import sun.security.pkcs.PKCS7;
-
/** Provides fsverity related operations. */
abstract public class VerityUtils {
private static final String TAG = "VerityUtils";
@@ -60,8 +52,6 @@
/** The maximum size of signature file. This is just to avoid potential abuse. */
private static final int MAX_SIGNATURE_FILE_SIZE_BYTES = 8192;
- private static final int COMMON_LINUX_PAGE_SIZE_IN_BYTES = 4096;
-
private static final boolean DEBUG = false;
/** Returns true if the given file looks like containing an fs-verity signature. */
@@ -74,42 +64,15 @@
return filePath + FSVERITY_SIGNATURE_FILE_EXTENSION;
}
- /** Generates Merkle tree and fs-verity metadata then enables fs-verity. */
- public static void setUpFsverity(@NonNull String filePath, String signaturePath)
- throws IOException, DigestException, NoSuchAlgorithmException {
- final PKCS7 pkcs7 = new PKCS7(Files.readAllBytes(Paths.get(signaturePath)));
- final byte[] expectedMeasurement = pkcs7.getContentInfo().getContentBytes();
- if (DEBUG) {
- Slog.d(TAG, "Enabling fs-verity with signed fs-verity measurement "
- + bytesToString(expectedMeasurement));
- Slog.d(TAG, "PKCS#7 info: " + pkcs7);
+ /** Enables fs-verity for the file with a PKCS#7 detached signature file. */
+ public static void setUpFsverity(@NonNull String filePath, @NonNull String signaturePath)
+ throws IOException {
+ if (Files.size(Paths.get(signaturePath)) > MAX_SIGNATURE_FILE_SIZE_BYTES) {
+ throw new SecurityException("Signature file is unexpectedly large: " + signaturePath);
}
-
- final TrackedBufferFactory bufferFactory = new TrackedBufferFactory();
- final byte[] actualMeasurement = generateFsverityMetadata(filePath, signaturePath,
- bufferFactory);
- try (RandomAccessFile raf = new RandomAccessFile(filePath, "rw")) {
- FileChannel ch = raf.getChannel();
- ch.position(roundUpToNextMultiple(ch.size(), COMMON_LINUX_PAGE_SIZE_IN_BYTES));
- ByteBuffer buffer = bufferFactory.getBuffer();
-
- long offset = buffer.position();
- long size = buffer.limit();
- while (offset < size) {
- long s = ch.write(buffer);
- offset += s;
- size -= s;
- }
- }
-
- if (!Arrays.equals(expectedMeasurement, actualMeasurement)) {
- throw new SecurityException("fs-verity measurement mismatch: "
- + bytesToString(actualMeasurement) + " != "
- + bytesToString(expectedMeasurement));
- }
-
- // This can fail if the public key is not already in .fs-verity kernel keyring.
- int errno = enableFsverityNative(filePath);
+ byte[] pkcs7Signature = Files.readAllBytes(Paths.get(signaturePath));
+ // This will fail if the public key is not already in .fs-verity kernel keyring.
+ int errno = enableFsverityNative(filePath, pkcs7Signature);
if (errno != 0) {
throw new IOException("Failed to enable fs-verity on " + filePath + ": "
+ Os.strerror(errno));
@@ -131,12 +94,19 @@
return true;
}
+ private static native int enableFsverityNative(@NonNull String filePath,
+ @NonNull byte[] pkcs7Signature);
+ private static native int measureFsverityNative(@NonNull String filePath);
+
/**
* Generates legacy Merkle tree and fs-verity metadata with Signing Block skipped.
*
+ * @deprecated This is only used for previous fs-verity implementation, and should never be used
+ * on new devices.
* @return {@code SetupResult} that contains the result code, and when success, the
* {@code FileDescriptor} to read all the data from.
*/
+ @Deprecated
public static SetupResult generateApkVeritySetupData(@NonNull String apkPath) {
if (DEBUG) {
Slog.d(TAG, "Trying to install legacy apk verity to " + apkPath);
@@ -173,7 +143,10 @@
/**
* {@see ApkSignatureVerifier#generateApkVerityRootHash(String)}.
+ * @deprecated This is only used for previous fs-verity implementation, and should never be used
+ * on new devices.
*/
+ @Deprecated
public static byte[] generateApkVerityRootHash(@NonNull String apkPath)
throws NoSuchAlgorithmException, DigestException, IOException {
return ApkSignatureVerifier.generateApkVerityRootHash(apkPath);
@@ -181,104 +154,16 @@
/**
* {@see ApkSignatureVerifier#getVerityRootHash(String)}.
+ * @deprecated This is only used for previous fs-verity implementation, and should never be used
+ * on new devices.
*/
+ @Deprecated
public static byte[] getVerityRootHash(@NonNull String apkPath)
throws IOException, SignatureNotFoundException {
return ApkSignatureVerifier.getVerityRootHash(apkPath);
}
/**
- * Generates fs-verity metadata for {@code filePath} in the buffer created by {@code
- * trackedBufferFactory}. The metadata contains the Merkle tree, fs-verity descriptor and
- * extensions, including a PKCS#7 signature provided in {@code signaturePath}.
- *
- * <p>It is worthy to note that {@code trackedBufferFactory} generates a "tracked" {@code
- * ByteBuffer}. The data will be used outside this method via the factory itself.
- *
- * @return fs-verity signed data (struct fsverity_digest_disk) of {@code filePath}, which
- * includes SHA-256 of fs-verity descriptor and authenticated extensions.
- */
- private static byte[] generateFsverityMetadata(String filePath, String signaturePath,
- @NonNull ByteBufferFactory trackedBufferFactory)
- throws IOException, DigestException, NoSuchAlgorithmException {
- try (RandomAccessFile file = new RandomAccessFile(filePath, "r")) {
- VerityBuilder.VerityResult result = VerityBuilder.generateFsVerityTree(
- file, trackedBufferFactory);
-
- ByteBuffer buffer = result.verityData;
- buffer.position(result.merkleTreeSize);
-
- final byte[] measurement = generateFsverityDescriptorAndMeasurement(file,
- result.rootHash, signaturePath, buffer);
- buffer.flip();
- return constructFsveritySignedDataNative(measurement);
- }
- }
-
- /**
- * Generates fs-verity descriptor including the extensions to the {@code output} and returns the
- * fs-verity measurement.
- *
- * @return fs-verity measurement, which is a SHA-256 of fs-verity descriptor and authenticated
- * extensions.
- */
- private static byte[] generateFsverityDescriptorAndMeasurement(
- @NonNull RandomAccessFile file, @NonNull byte[] rootHash,
- @NonNull String pkcs7SignaturePath, @NonNull ByteBuffer output)
- throws IOException, NoSuchAlgorithmException, DigestException {
- final short kRootHashExtensionId = 1;
- final short kPkcs7SignatureExtensionId = 3;
- final int origPosition = output.position();
-
- // For generating fs-verity file measurement, which consists of the descriptor and
- // authenticated extensions (but not unauthenticated extensions and the footer).
- MessageDigest md = MessageDigest.getInstance("SHA-256");
-
- // 1. Generate fs-verity descriptor.
- final byte[] desc = constructFsverityDescriptorNative(file.length());
- output.put(desc);
- md.update(desc);
-
- // 2. Generate authenticated extensions.
- final byte[] authExt =
- constructFsverityExtensionNative(kRootHashExtensionId, rootHash.length);
- output.put(authExt);
- output.put(rootHash);
- md.update(authExt);
- md.update(rootHash);
-
- // 3. Generate unauthenticated extensions.
- ByteBuffer header = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN);
- output.putShort((short) 1); // number of unauthenticated extensions below
- output.position(output.position() + 6);
-
- // Generate PKCS#7 extension. NB: We do not verify agaist trusted certificate (should be
- // done by the caller if needed).
- Path path = Paths.get(pkcs7SignaturePath);
- if (Files.size(path) > MAX_SIGNATURE_FILE_SIZE_BYTES) {
- throw new IllegalArgumentException("Signature size is unexpectedly large: "
- + pkcs7SignaturePath);
- }
- final byte[] pkcs7Signature = Files.readAllBytes(path);
- output.put(constructFsverityExtensionNative(kPkcs7SignatureExtensionId,
- pkcs7Signature.length));
- output.put(pkcs7Signature);
-
- // 4. Generate the footer.
- output.put(constructFsverityFooterNative(output.position() - origPosition));
-
- return md.digest();
- }
-
- private static native int enableFsverityNative(@NonNull String filePath);
- private static native int measureFsverityNative(@NonNull String filePath);
- private static native byte[] constructFsveritySignedDataNative(@NonNull byte[] measurement);
- private static native byte[] constructFsverityDescriptorNative(long fileSize);
- private static native byte[] constructFsverityExtensionNative(short extensionId,
- int extensionDataSize);
- private static native byte[] constructFsverityFooterNative(int offsetToDescriptorHead);
-
- /**
* Returns a pair of {@code SharedMemory} and {@code Integer}. The {@code SharedMemory} contains
* Merkle tree and fsverity headers for the given apk, in the form that can immediately be used
* for fsverity setup. The data is aligned to the beginning of {@code SharedMemory}, and has
@@ -313,6 +198,11 @@
return HexEncoding.encodeToString(bytes);
}
+ /**
+ * @deprecated This is only used for previous fs-verity implementation, and should never be used
+ * on new devices.
+ */
+ @Deprecated
public static class SetupResult {
/** Result code if verity is set up correctly. */
private static final int RESULT_OK = 1;
@@ -401,30 +291,4 @@
return mBuffer == null ? -1 : mBuffer.limit();
}
}
-
- /** A {@code ByteBufferFactory} that tracks the {@code ByteBuffer} it creates. */
- private static class TrackedBufferFactory implements ByteBufferFactory {
- private ByteBuffer mBuffer;
-
- @Override
- public ByteBuffer create(int capacity) {
- if (mBuffer != null) {
- throw new IllegalStateException("Multiple instantiation from this factory");
- }
- mBuffer = ByteBuffer.allocate(capacity);
- return mBuffer;
- }
-
- public ByteBuffer getBuffer() {
- return mBuffer;
- }
- }
-
- /** Round up the number to the next multiple of the divisor. */
- private static long roundUpToNextMultiple(long number, long divisor) {
- if (number > (Long.MAX_VALUE - divisor)) {
- throw new IllegalArgumentException("arithmetic overflow");
- }
- return ((number + (divisor - 1)) / divisor) * divisor;
- }
}
diff --git a/services/core/java/com/android/server/timedetector/SimpleTimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/SimpleTimeDetectorStrategy.java
deleted file mode 100644
index 340fe3d..0000000
--- a/services/core/java/com/android/server/timedetector/SimpleTimeDetectorStrategy.java
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.timedetector;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.AlarmManager;
-import android.app.timedetector.ManualTimeSuggestion;
-import android.app.timedetector.PhoneTimeSuggestion;
-import android.content.Intent;
-import android.util.LocalLog;
-import android.util.Slog;
-import android.util.TimestampedValue;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.util.IndentingPrintWriter;
-
-import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * An implementation of TimeDetectorStrategy that passes only NITZ suggestions to
- * {@link AlarmManager}.
- *
- * <p>Most public methods are marked synchronized to ensure thread safety around internal state.
- */
-public final class SimpleTimeDetectorStrategy implements TimeDetectorStrategy {
-
- private static final boolean DBG = false;
- private static final String LOG_TAG = "SimpleTimeDetectorStrategy";
-
- @IntDef({ ORIGIN_PHONE, ORIGIN_MANUAL })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Origin {}
-
- /** Used when a time value originated from a telephony signal. */
- @Origin
- private static final int ORIGIN_PHONE = 1;
-
- /** Used when a time value originated from a user / manual settings. */
- @Origin
- private static final int ORIGIN_MANUAL = 2;
-
- /**
- * CLOCK_PARANOIA: The maximum difference allowed between the expected system clock time and the
- * actual system clock time before a warning is logged. Used to help identify situations where
- * there is something other than this class setting the system clock automatically.
- */
- private static final long SYSTEM_CLOCK_PARANOIA_THRESHOLD_MILLIS = 2 * 1000;
-
- // A log for changes made to the system clock and why.
- @NonNull private final LocalLog mTimeChangesLog = new LocalLog(30);
-
- // @NonNull after initialize()
- private Callback mCallback;
-
- // Last phone suggestion.
- @Nullable private PhoneTimeSuggestion mLastPhoneSuggestion;
-
- // Information about the last time signal received: Used when toggling auto-time.
- @Nullable private TimestampedValue<Long> mLastAutoSystemClockTime;
- private boolean mLastAutoSystemClockTimeSendNetworkBroadcast;
-
- // System clock state.
- @Nullable private TimestampedValue<Long> mLastAutoSystemClockTimeSet;
-
- @Override
- public void initialize(@NonNull Callback callback) {
- mCallback = callback;
- }
-
- @Override
- public synchronized void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion) {
- // NITZ logic
-
- // Empty suggestions are just ignored as we don't currently keep track of suggestion origin.
- if (timeSuggestion.getUtcTime() == null) {
- return;
- }
-
- boolean timeSuggestionIsValid =
- validateNewPhoneSuggestion(timeSuggestion, mLastPhoneSuggestion);
- if (!timeSuggestionIsValid) {
- return;
- }
- // Always store the last NITZ value received, regardless of whether we go on to use it to
- // update the system clock. This is so that we can validate future phone suggestions.
- mLastPhoneSuggestion = timeSuggestion;
-
- // System clock update logic.
- final TimestampedValue<Long> newUtcTime = timeSuggestion.getUtcTime();
- setSystemClockIfRequired(ORIGIN_PHONE, newUtcTime, timeSuggestion);
- }
-
- @Override
- public synchronized void suggestManualTime(ManualTimeSuggestion timeSuggestion) {
- final TimestampedValue<Long> newUtcTime = timeSuggestion.getUtcTime();
- setSystemClockIfRequired(ORIGIN_MANUAL, newUtcTime, timeSuggestion);
- }
-
- private static boolean validateNewPhoneSuggestion(@NonNull PhoneTimeSuggestion newSuggestion,
- @Nullable PhoneTimeSuggestion lastSuggestion) {
-
- if (lastSuggestion != null) {
- long referenceTimeDifference = TimestampedValue.referenceTimeDifference(
- newSuggestion.getUtcTime(), lastSuggestion.getUtcTime());
- if (referenceTimeDifference < 0 || referenceTimeDifference > Integer.MAX_VALUE) {
- // Out of order or bogus.
- Slog.w(LOG_TAG, "Bad NITZ signal received."
- + " referenceTimeDifference=" + referenceTimeDifference
- + " lastSuggestion=" + lastSuggestion
- + " newSuggestion=" + newSuggestion);
- return false;
- }
- }
- return true;
- }
-
- @GuardedBy("this")
- private void setSystemClockIfRequired(
- @Origin int origin, TimestampedValue<Long> time, Object cause) {
- // Historically, Android has sent a TelephonyIntents.ACTION_NETWORK_SET_TIME broadcast only
- // when setting the time using NITZ.
- boolean sendNetworkBroadcast = origin == ORIGIN_PHONE;
-
- boolean isOriginAutomatic = isOriginAutomatic(origin);
- if (isOriginAutomatic) {
- // Store the last auto time candidate we've seen in all cases so we can set the system
- // clock when/if time detection is off but later enabled.
- mLastAutoSystemClockTime = time;
- mLastAutoSystemClockTimeSendNetworkBroadcast = sendNetworkBroadcast;
-
- if (!mCallback.isAutoTimeDetectionEnabled()) {
- if (DBG) {
- Slog.d(LOG_TAG, "Auto time detection is not enabled."
- + " origin=" + origin
- + ", time=" + time
- + ", cause=" + cause);
- }
- return;
- }
- } else {
- if (mCallback.isAutoTimeDetectionEnabled()) {
- if (DBG) {
- Slog.d(LOG_TAG, "Auto time detection is enabled."
- + " origin=" + origin
- + ", time=" + time
- + ", cause=" + cause);
- }
- return;
- }
- }
-
- mCallback.acquireWakeLock();
- try {
- long elapsedRealtimeMillis = mCallback.elapsedRealtimeMillis();
- long actualTimeMillis = mCallback.systemClockMillis();
-
- if (isOriginAutomatic) {
- // CLOCK_PARANOIA : Check to see if this class owns the clock or if something else
- // may be setting the clock.
- if (mLastAutoSystemClockTimeSet != null) {
- long expectedTimeMillis = TimeDetectorStrategy.getTimeAt(
- mLastAutoSystemClockTimeSet, elapsedRealtimeMillis);
- long absSystemClockDifference = Math.abs(expectedTimeMillis - actualTimeMillis);
- if (absSystemClockDifference > SYSTEM_CLOCK_PARANOIA_THRESHOLD_MILLIS) {
- Slog.w(LOG_TAG,
- "System clock has not tracked elapsed real time clock. A clock may"
- + " be inaccurate or something unexpectedly set the system"
- + " clock."
- + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
- + " expectedTimeMillis=" + expectedTimeMillis
- + " actualTimeMillis=" + actualTimeMillis);
- }
- }
- }
-
- adjustAndSetDeviceSystemClock(
- time, sendNetworkBroadcast, elapsedRealtimeMillis, actualTimeMillis, cause);
- } finally {
- mCallback.releaseWakeLock();
- }
- }
-
- private static boolean isOriginAutomatic(@Origin int origin) {
- return origin == ORIGIN_PHONE;
- }
-
- @Override
- public synchronized void handleAutoTimeDetectionChanged() {
- // If automatic time detection is enabled we update the system clock instantly if we can.
- // Conversely, if automatic time detection is disabled we leave the clock as it is.
- boolean enabled = mCallback.isAutoTimeDetectionEnabled();
- if (enabled) {
- if (mLastAutoSystemClockTime != null) {
- // Only send the network broadcast if the last candidate would have caused one.
- final boolean sendNetworkBroadcast = mLastAutoSystemClockTimeSendNetworkBroadcast;
-
- mCallback.acquireWakeLock();
- try {
- long elapsedRealtimeMillis = mCallback.elapsedRealtimeMillis();
- long actualTimeMillis = mCallback.systemClockMillis();
-
- final String reason = "Automatic time detection enabled.";
- adjustAndSetDeviceSystemClock(mLastAutoSystemClockTime, sendNetworkBroadcast,
- elapsedRealtimeMillis, actualTimeMillis, reason);
- } finally {
- mCallback.releaseWakeLock();
- }
- }
- } else {
- // CLOCK_PARANOIA: We are losing "control" of the system clock so we cannot predict what
- // it should be in future.
- mLastAutoSystemClockTimeSet = null;
- }
- }
-
- @Override
- public synchronized void dump(@NonNull PrintWriter pw, @Nullable String[] args) {
- IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
- ipw.println("TimeDetectorStrategy:");
- ipw.increaseIndent(); // level 1
-
- ipw.println("mLastPhoneSuggestion=" + mLastPhoneSuggestion);
- ipw.println("mLastAutoSystemClockTimeSet=" + mLastAutoSystemClockTimeSet);
- ipw.println("mLastAutoSystemClockTime=" + mLastAutoSystemClockTime);
- ipw.println("mLastAutoSystemClockTimeSendNetworkBroadcast="
- + mLastAutoSystemClockTimeSendNetworkBroadcast);
-
-
- ipw.println("Time change log:");
- ipw.increaseIndent(); // level 2
- mTimeChangesLog.dump(ipw);
- ipw.decreaseIndent(); // level 2
-
- ipw.decreaseIndent(); // level 1
- ipw.flush();
- }
-
- @GuardedBy("this")
- private void adjustAndSetDeviceSystemClock(
- TimestampedValue<Long> newTime, boolean sendNetworkBroadcast,
- long elapsedRealtimeMillis, long actualSystemClockMillis, Object cause) {
-
- // Adjust for the time that has elapsed since the signal was received.
- long newSystemClockMillis = TimeDetectorStrategy.getTimeAt(newTime, elapsedRealtimeMillis);
-
- // Check if the new signal would make sufficient difference to the system clock. If it's
- // below the threshold then ignore it.
- long absTimeDifference = Math.abs(newSystemClockMillis - actualSystemClockMillis);
- long systemClockUpdateThreshold = mCallback.systemClockUpdateThresholdMillis();
- if (absTimeDifference < systemClockUpdateThreshold) {
- if (DBG) {
- Slog.d(LOG_TAG, "Not setting system clock. New time and"
- + " system clock are close enough."
- + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
- + " newTime=" + newTime
- + " cause=" + cause
- + " systemClockUpdateThreshold=" + systemClockUpdateThreshold
- + " absTimeDifference=" + absTimeDifference);
- }
- return;
- }
-
- mCallback.setSystemClock(newSystemClockMillis);
- String logMsg = "Set system clock using time=" + newTime
- + " cause=" + cause
- + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
- + " newSystemClockMillis=" + newSystemClockMillis;
- if (DBG) {
- Slog.d(LOG_TAG, logMsg);
- }
- mTimeChangesLog.log(logMsg);
-
- // CLOCK_PARANOIA : Record the last time this class set the system clock.
- mLastAutoSystemClockTimeSet = newTime;
-
- if (sendNetworkBroadcast) {
- // Send a broadcast that telephony code used to send after setting the clock.
- // TODO Remove this broadcast as soon as there are no remaining listeners.
- Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- intent.putExtra("time", newSystemClockMillis);
- mCallback.sendStickyBroadcast(intent);
- }
- }
-}
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
index 34400ff..172367a 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
@@ -31,7 +31,6 @@
import com.android.internal.util.DumpUtils;
import com.android.server.FgThread;
import com.android.server.SystemService;
-import com.android.server.timedetector.TimeDetectorStrategy.Callback;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -58,17 +57,16 @@
@NonNull private final Handler mHandler;
@NonNull private final Context mContext;
- @NonNull private final Callback mCallback;
@NonNull private final TimeDetectorStrategy mTimeDetectorStrategy;
private static TimeDetectorService create(@NonNull Context context) {
- TimeDetectorStrategy timeDetector = new SimpleTimeDetectorStrategy();
+ TimeDetectorStrategy timeDetectorStrategy = new TimeDetectorStrategyImpl();
TimeDetectorStrategyCallbackImpl callback = new TimeDetectorStrategyCallbackImpl(context);
- timeDetector.initialize(callback);
+ timeDetectorStrategy.initialize(callback);
Handler handler = FgThread.getHandler();
TimeDetectorService timeDetectorService =
- new TimeDetectorService(context, handler, callback, timeDetector);
+ new TimeDetectorService(context, handler, timeDetectorStrategy);
// Wire up event listening.
ContentResolver contentResolver = context.getContentResolver();
@@ -85,10 +83,9 @@
@VisibleForTesting
public TimeDetectorService(@NonNull Context context, @NonNull Handler handler,
- @NonNull Callback callback, @NonNull TimeDetectorStrategy timeDetectorStrategy) {
+ @NonNull TimeDetectorStrategy timeDetectorStrategy) {
mContext = Objects.requireNonNull(context);
mHandler = Objects.requireNonNull(handler);
- mCallback = Objects.requireNonNull(callback);
mTimeDetectorStrategy = Objects.requireNonNull(timeDetectorStrategy);
}
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
new file mode 100644
index 0000000..1b1ac6d
--- /dev/null
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -0,0 +1,549 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.timedetector;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.AlarmManager;
+import android.app.timedetector.ManualTimeSuggestion;
+import android.app.timedetector.PhoneTimeSuggestion;
+import android.content.Intent;
+import android.util.ArrayMap;
+import android.util.LocalLog;
+import android.util.Slog;
+import android.util.TimestampedValue;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.LinkedList;
+import java.util.Map;
+
+/**
+ * An implementation of TimeDetectorStrategy that passes phone and manual suggestions to
+ * {@link AlarmManager}. When there are multiple phone sources, the one with the lowest ID is used
+ * unless the data becomes too stale.
+ *
+ * <p>Most public methods are marked synchronized to ensure thread safety around internal state.
+ */
+public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
+
+ private static final boolean DBG = false;
+ private static final String LOG_TAG = "SimpleTimeDetectorStrategy";
+
+ /** A score value used to indicate "no score", either due to validation failure or age. */
+ private static final int PHONE_INVALID_SCORE = -1;
+ /** The number of buckets phone suggestions can be put in by age. */
+ private static final int PHONE_BUCKET_COUNT = 24;
+ /** Each bucket is this size. All buckets are equally sized. */
+ @VisibleForTesting
+ static final int PHONE_BUCKET_SIZE_MILLIS = 60 * 60 * 1000;
+ /** Phone suggestions older than this value are considered too old. */
+ @VisibleForTesting
+ static final long PHONE_MAX_AGE_MILLIS = PHONE_BUCKET_COUNT * PHONE_BUCKET_SIZE_MILLIS;
+
+ @IntDef({ ORIGIN_PHONE, ORIGIN_MANUAL })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Origin {}
+
+ /** Used when a time value originated from a telephony signal. */
+ @Origin
+ private static final int ORIGIN_PHONE = 1;
+
+ /** Used when a time value originated from a user / manual settings. */
+ @Origin
+ private static final int ORIGIN_MANUAL = 2;
+
+ /**
+ * CLOCK_PARANOIA: The maximum difference allowed between the expected system clock time and the
+ * actual system clock time before a warning is logged. Used to help identify situations where
+ * there is something other than this class setting the system clock.
+ */
+ private static final long SYSTEM_CLOCK_PARANOIA_THRESHOLD_MILLIS = 2 * 1000;
+
+ /** The number of previous phone suggestions to keep for each ID (for use during debugging). */
+ private static final int KEEP_SUGGESTION_HISTORY_SIZE = 30;
+
+ // A log for changes made to the system clock and why.
+ @NonNull
+ private final LocalLog mTimeChangesLog = new LocalLog(30, false /* useLocalTimestamps */);
+
+ // @NonNull after initialize()
+ private Callback mCallback;
+
+ // Used to store the last time the system clock state was set automatically. It is used to
+ // detect (and log) issues with the realtime clock or whether the clock is being set without
+ // going through this strategy code.
+ @GuardedBy("this")
+ @Nullable
+ private TimestampedValue<Long> mLastAutoSystemClockTimeSet;
+
+ /**
+ * A mapping from phoneId to a linked list of time suggestions (the "first" being the latest).
+ * We typically expect one or two entries in this Map: devices will have a small number
+ * of telephony devices and phoneIds are assumed to be stable. The LinkedList associated with
+ * the ID will not exceed {@link #KEEP_SUGGESTION_HISTORY_SIZE} in size.
+ */
+ @GuardedBy("this")
+ private ArrayMap<Integer, LinkedList<PhoneTimeSuggestion>> mSuggestionByPhoneId =
+ new ArrayMap<>();
+
+ @Override
+ public void initialize(@NonNull Callback callback) {
+ mCallback = callback;
+ }
+
+ @Override
+ public synchronized void suggestManualTime(@NonNull ManualTimeSuggestion suggestion) {
+ final TimestampedValue<Long> newUtcTime = suggestion.getUtcTime();
+
+ if (!validateSuggestionTime(newUtcTime, suggestion)) {
+ return;
+ }
+
+ String cause = "Manual time suggestion received: suggestion=" + suggestion;
+ setSystemClockIfRequired(ORIGIN_MANUAL, newUtcTime, cause);
+ }
+
+ @Override
+ public synchronized void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion) {
+ // Empty time suggestion means that telephony network connectivity has been lost.
+ // The passage of time is relentless, and we don't expect our users to use a time machine,
+ // so we can continue relying on previous suggestions when we lose connectivity. This is
+ // unlike time zone, where a user may lose connectivity when boarding a flight and where we
+ // do want to "forget" old signals. Suggestions that are too old are discarded later in the
+ // detection algorithm.
+ if (timeSuggestion.getUtcTime() == null) {
+ return;
+ }
+
+ // Perform validation / input filtering and record the validated suggestion against the
+ // phoneId.
+ if (!validateAndStorePhoneSuggestion(timeSuggestion)) {
+ return;
+ }
+
+ // Now perform auto time detection. The new suggestion may be used to modify the system
+ // clock.
+ String reason = "New phone time suggested. timeSuggestion=" + timeSuggestion;
+ doAutoTimeDetection(reason);
+ }
+
+ @Override
+ public synchronized void handleAutoTimeDetectionChanged() {
+ boolean enabled = mCallback.isAutoTimeDetectionEnabled();
+ // When automatic time detection is enabled we update the system clock instantly if we can.
+ // Conversely, when automatic time detection is disabled we leave the clock as it is.
+ if (enabled) {
+ String reason = "Auto time zone detection setting enabled.";
+ doAutoTimeDetection(reason);
+ } else {
+ // CLOCK_PARANOIA: We are losing "control" of the system clock so we cannot predict what
+ // it should be in future.
+ mLastAutoSystemClockTimeSet = null;
+ }
+ }
+
+ @Override
+ public synchronized void dump(@NonNull PrintWriter pw, @Nullable String[] args) {
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ ipw.println("TimeDetectorStrategy:");
+ ipw.increaseIndent(); // level 1
+
+ ipw.println("mLastAutoSystemClockTimeSet=" + mLastAutoSystemClockTimeSet);
+
+ ipw.println("Time change log:");
+ ipw.increaseIndent(); // level 2
+ mTimeChangesLog.dump(ipw);
+ ipw.decreaseIndent(); // level 2
+
+ ipw.println("Phone suggestion history:");
+ ipw.increaseIndent(); // level 2
+ for (Map.Entry<Integer, LinkedList<PhoneTimeSuggestion>> entry
+ : mSuggestionByPhoneId.entrySet()) {
+ ipw.println("Phone " + entry.getKey());
+
+ ipw.increaseIndent(); // level 3
+ for (PhoneTimeSuggestion suggestion : entry.getValue()) {
+ ipw.println(suggestion);
+ }
+ ipw.decreaseIndent(); // level 3
+ }
+ ipw.decreaseIndent(); // level 2
+
+ ipw.decreaseIndent(); // level 1
+ ipw.flush();
+ }
+
+ @GuardedBy("this")
+ private boolean validateAndStorePhoneSuggestion(@NonNull PhoneTimeSuggestion suggestion) {
+ TimestampedValue<Long> newUtcTime = suggestion.getUtcTime();
+ if (!validateSuggestionTime(newUtcTime, suggestion)) {
+ // There's probably nothing useful we can do: elsewhere we assume that reference
+ // times are in the past so just stop here.
+ return false;
+ }
+
+ int phoneId = suggestion.getPhoneId();
+ LinkedList<PhoneTimeSuggestion> phoneSuggestions = mSuggestionByPhoneId.get(phoneId);
+ if (phoneSuggestions == null) {
+ // The first time we've seen this phoneId.
+ phoneSuggestions = new LinkedList<>();
+ mSuggestionByPhoneId.put(phoneId, phoneSuggestions);
+ } else if (phoneSuggestions.isEmpty()) {
+ Slog.w(LOG_TAG, "Suggestions unexpectedly empty when adding suggestion=" + suggestion);
+ }
+
+ if (!phoneSuggestions.isEmpty()) {
+ // We can log / discard suggestions with obvious issues with the reference time clock.
+ PhoneTimeSuggestion previousSuggestion = phoneSuggestions.getFirst();
+ if (previousSuggestion == null
+ || previousSuggestion.getUtcTime() == null
+ || previousSuggestion.getUtcTime().getValue() == null) {
+ // This should be impossible given we only store validated suggestions.
+ Slog.w(LOG_TAG, "Previous suggestion is null or has a null time."
+ + " previousSuggestion=" + previousSuggestion
+ + ", suggestion=" + suggestion);
+ return false;
+ }
+
+ long referenceTimeDifference = TimestampedValue.referenceTimeDifference(
+ newUtcTime, previousSuggestion.getUtcTime());
+ if (referenceTimeDifference < 0) {
+ // The reference time is before the previously received suggestion. Ignore it.
+ Slog.w(LOG_TAG, "Out of order phone suggestion received."
+ + " referenceTimeDifference=" + referenceTimeDifference
+ + " previousSuggestion=" + previousSuggestion
+ + " suggestion=" + suggestion);
+ return false;
+ }
+ }
+
+ // Store the latest suggestion.
+ phoneSuggestions.addFirst(suggestion);
+ if (phoneSuggestions.size() > KEEP_SUGGESTION_HISTORY_SIZE) {
+ phoneSuggestions.removeLast();
+ }
+ return true;
+ }
+
+ private boolean validateSuggestionTime(
+ @NonNull TimestampedValue<Long> newUtcTime, @NonNull Object suggestion) {
+ if (newUtcTime.getValue() == null) {
+ Slog.w(LOG_TAG, "Suggested time value is null. suggestion=" + suggestion);
+ return false;
+ }
+
+ // We can validate the suggestion against the reference time clock.
+ long elapsedRealtimeMillis = mCallback.elapsedRealtimeMillis();
+ if (elapsedRealtimeMillis < newUtcTime.getReferenceTimeMillis()) {
+ // elapsedRealtime clock went backwards?
+ Slog.w(LOG_TAG, "New reference time is in the future? Ignoring."
+ + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+ + ", suggestion=" + suggestion);
+ return false;
+ }
+ return true;
+ }
+
+ @GuardedBy("this")
+ private void doAutoTimeDetection(@NonNull String detectionReason) {
+ if (!mCallback.isAutoTimeDetectionEnabled()) {
+ // Avoid doing unnecessary work with this (race-prone) check.
+ return;
+ }
+
+ PhoneTimeSuggestion bestPhoneSuggestion = findBestPhoneSuggestion();
+
+ // Work out what to do with the best suggestion.
+ if (bestPhoneSuggestion == null) {
+ // There is no good phone suggestion.
+ if (DBG) {
+ Slog.d(LOG_TAG, "Could not determine time: No best phone suggestion."
+ + " detectionReason=" + detectionReason);
+ }
+ return;
+ }
+
+ final TimestampedValue<Long> newUtcTime = bestPhoneSuggestion.getUtcTime();
+ String cause = "Found good suggestion."
+ + ", bestPhoneSuggestion=" + bestPhoneSuggestion
+ + ", detectionReason=" + detectionReason;
+ setSystemClockIfRequired(ORIGIN_PHONE, newUtcTime, cause);
+ }
+
+ @GuardedBy("this")
+ @Nullable
+ private PhoneTimeSuggestion findBestPhoneSuggestion() {
+ long elapsedRealtimeMillis = mCallback.elapsedRealtimeMillis();
+
+ // Phone time suggestions are assumed to be derived from NITZ or NITZ-like signals. These
+ // have a number of limitations:
+ // 1) No guarantee of accuracy ("accuracy of the time information is in the order of
+ // minutes") [1]
+ // 2) No guarantee of regular signals ("dependent on the handset crossing radio network
+ // boundaries") [1]
+ //
+ // [1] https://en.wikipedia.org/wiki/NITZ
+ //
+ // Generally, when there are suggestions from multiple phoneIds they should usually
+ // approximately agree. In cases where signals *are* inaccurate we don't want to vacillate
+ // between signals from two phoneIds. However, it is known for NITZ signals to be incorrect
+ // occasionally, which means we also don't want to stick forever with one phoneId. Without
+ // cross-referencing across sources (e.g. the current device time, NTP), or doing some kind
+ // of statistical analysis of consistency within and across phoneIds, we can't know which
+ // suggestions are more correct.
+ //
+ // For simplicity, we try to value recency, then consistency of phoneId.
+ //
+ // The heuristic works as follows:
+ // Recency: The most recent suggestion from each phone is scored. The score is based on a
+ // discrete age bucket, i.e. so signals received around the same time will be in the same
+ // bucket, thus applying a loose reference time ordering. The suggestion with the highest
+ // score is used.
+ // Consistency: If there a multiple suggestions with the same score, the suggestion with the
+ // lowest phoneId is always taken.
+ //
+ // In the trivial case with a single ID this will just mean that the latest received
+ // suggestion is used.
+
+ PhoneTimeSuggestion bestSuggestion = null;
+ int bestScore = PHONE_INVALID_SCORE;
+ for (int i = 0; i < mSuggestionByPhoneId.size(); i++) {
+ Integer phoneId = mSuggestionByPhoneId.keyAt(i);
+ LinkedList<PhoneTimeSuggestion> phoneSuggestions = mSuggestionByPhoneId.valueAt(i);
+ if (phoneSuggestions == null) {
+ // Unexpected - map is missing a value.
+ Slog.w(LOG_TAG, "Suggestions unexpectedly missing for phoneId."
+ + " phoneId=" + phoneId);
+ continue;
+ }
+
+ PhoneTimeSuggestion candidateSuggestion = phoneSuggestions.getFirst();
+ if (candidateSuggestion == null) {
+ // Unexpected - null suggestions should never be stored.
+ Slog.w(LOG_TAG, "Latest suggestion unexpectedly null for phoneId."
+ + " phoneId=" + phoneId);
+ continue;
+ } else if (candidateSuggestion.getUtcTime() == null) {
+ // Unexpected - we do not store empty suggestions.
+ Slog.w(LOG_TAG, "Latest suggestion unexpectedly empty. "
+ + " candidateSuggestion=" + candidateSuggestion);
+ continue;
+ }
+
+ int candidateScore = scorePhoneSuggestion(elapsedRealtimeMillis, candidateSuggestion);
+ if (candidateScore == PHONE_INVALID_SCORE) {
+ // Expected: This means the suggestion is obviously invalid or just too old.
+ continue;
+ }
+
+ // Higher scores are better.
+ if (bestSuggestion == null || bestScore < candidateScore) {
+ bestSuggestion = candidateSuggestion;
+ bestScore = candidateScore;
+ } else if (bestScore == candidateScore) {
+ // Tie! Use the suggestion with the lowest phoneId.
+ int candidatePhoneId = candidateSuggestion.getPhoneId();
+ int bestPhoneId = bestSuggestion.getPhoneId();
+ if (candidatePhoneId < bestPhoneId) {
+ bestSuggestion = candidateSuggestion;
+ }
+ }
+ }
+ return bestSuggestion;
+ }
+
+ private static int scorePhoneSuggestion(
+ long elapsedRealtimeMillis, @NonNull PhoneTimeSuggestion timeSuggestion) {
+ // The score is based on the age since receipt. Suggestions are bucketed so two
+ // suggestions in the same bucket from different phoneIds are scored the same.
+ TimestampedValue<Long> utcTime = timeSuggestion.getUtcTime();
+ long referenceTimeMillis = utcTime.getReferenceTimeMillis();
+ if (referenceTimeMillis > elapsedRealtimeMillis) {
+ // Future times are ignored. They imply the reference time was wrong, or the elapsed
+ // realtime clock has gone backwards, neither of which are supportable situations.
+ Slog.w(LOG_TAG, "Existing suggestion found to be in the future. "
+ + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+ + ", timeSuggestion=" + timeSuggestion);
+ return PHONE_INVALID_SCORE;
+ }
+
+ long ageMillis = elapsedRealtimeMillis - referenceTimeMillis;
+
+ // Any suggestion > MAX_AGE_MILLIS is treated as too old. Although time is relentless and
+ // predictable, the accuracy of the reference time clock may be poor over long periods which
+ // would lead to errors creeping in. Also, in edge cases where a bad suggestion has been
+ // made and never replaced, it could also mean that the time detection code remains
+ // opinionated using a bad invalid suggestion. This caps that edge case at MAX_AGE_MILLIS.
+ if (ageMillis > PHONE_MAX_AGE_MILLIS) {
+ return PHONE_INVALID_SCORE;
+ }
+
+ // Turn the age into a discrete value: 0 <= bucketIndex < MAX_AGE_HOURS.
+ int bucketIndex = (int) (ageMillis / PHONE_BUCKET_SIZE_MILLIS);
+
+ // We want the lowest bucket index to have the highest score. 0 > score >= BUCKET_COUNT.
+ return PHONE_BUCKET_COUNT - bucketIndex;
+ }
+
+ @GuardedBy("this")
+ private void setSystemClockIfRequired(
+ @Origin int origin, @NonNull TimestampedValue<Long> time, @NonNull String cause) {
+
+ boolean isOriginAutomatic = isOriginAutomatic(origin);
+ if (isOriginAutomatic) {
+ if (!mCallback.isAutoTimeDetectionEnabled()) {
+ if (DBG) {
+ Slog.d(LOG_TAG, "Auto time detection is not enabled."
+ + " origin=" + origin
+ + ", time=" + time
+ + ", cause=" + cause);
+ }
+ return;
+ }
+ } else {
+ if (mCallback.isAutoTimeDetectionEnabled()) {
+ if (DBG) {
+ Slog.d(LOG_TAG, "Auto time detection is enabled."
+ + " origin=" + origin
+ + ", time=" + time
+ + ", cause=" + cause);
+ }
+ return;
+ }
+ }
+
+ mCallback.acquireWakeLock();
+ try {
+ setSystemClockUnderWakeLock(origin, time, cause);
+ } finally {
+ mCallback.releaseWakeLock();
+ }
+ }
+
+ private static boolean isOriginAutomatic(@Origin int origin) {
+ return origin == ORIGIN_PHONE;
+ }
+
+ @GuardedBy("this")
+ private void setSystemClockUnderWakeLock(
+ int origin, @NonNull TimestampedValue<Long> newTime, @NonNull Object cause) {
+
+ long elapsedRealtimeMillis = mCallback.elapsedRealtimeMillis();
+ boolean isOriginAutomatic = isOriginAutomatic(origin);
+ long actualSystemClockMillis = mCallback.systemClockMillis();
+ if (isOriginAutomatic) {
+ // CLOCK_PARANOIA : Check to see if this class owns the clock or if something else
+ // may be setting the clock.
+ if (mLastAutoSystemClockTimeSet != null) {
+ long expectedTimeMillis = TimeDetectorStrategy.getTimeAt(
+ mLastAutoSystemClockTimeSet, elapsedRealtimeMillis);
+ long absSystemClockDifference =
+ Math.abs(expectedTimeMillis - actualSystemClockMillis);
+ if (absSystemClockDifference > SYSTEM_CLOCK_PARANOIA_THRESHOLD_MILLIS) {
+ Slog.w(LOG_TAG,
+ "System clock has not tracked elapsed real time clock. A clock may"
+ + " be inaccurate or something unexpectedly set the system"
+ + " clock."
+ + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+ + " expectedTimeMillis=" + expectedTimeMillis
+ + " actualTimeMillis=" + actualSystemClockMillis
+ + " cause=" + cause);
+ }
+ }
+ }
+
+ // Adjust for the time that has elapsed since the signal was received.
+ long newSystemClockMillis = TimeDetectorStrategy.getTimeAt(newTime, elapsedRealtimeMillis);
+
+ // Check if the new signal would make sufficient difference to the system clock. If it's
+ // below the threshold then ignore it.
+ long absTimeDifference = Math.abs(newSystemClockMillis - actualSystemClockMillis);
+ long systemClockUpdateThreshold = mCallback.systemClockUpdateThresholdMillis();
+ if (absTimeDifference < systemClockUpdateThreshold) {
+ if (DBG) {
+ Slog.d(LOG_TAG, "Not setting system clock. New time and"
+ + " system clock are close enough."
+ + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+ + " newTime=" + newTime
+ + " cause=" + cause
+ + " systemClockUpdateThreshold=" + systemClockUpdateThreshold
+ + " absTimeDifference=" + absTimeDifference);
+ }
+ return;
+ }
+
+ mCallback.setSystemClock(newSystemClockMillis);
+ String logMsg = "Set system clock using time=" + newTime
+ + " cause=" + cause
+ + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+ + " newSystemClockMillis=" + newSystemClockMillis;
+ if (DBG) {
+ Slog.d(LOG_TAG, logMsg);
+ }
+ mTimeChangesLog.log(logMsg);
+
+ // CLOCK_PARANOIA : Record the last time this class set the system clock due to an auto-time
+ // signal, or clear the record it is being done manually.
+ if (isOriginAutomatic(origin)) {
+ mLastAutoSystemClockTimeSet = newTime;
+ } else {
+ mLastAutoSystemClockTimeSet = null;
+ }
+
+ // Historically, Android has sent a TelephonyIntents.ACTION_NETWORK_SET_TIME broadcast only
+ // when setting the time using NITZ.
+ if (origin == ORIGIN_PHONE) {
+ // Send a broadcast that telephony code used to send after setting the clock.
+ // TODO Remove this broadcast as soon as there are no remaining listeners.
+ Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ intent.putExtra("time", newSystemClockMillis);
+ mCallback.sendStickyBroadcast(intent);
+ }
+ }
+
+ /**
+ * Returns the current best phone suggestion. Not intended for general use: it is used during
+ * tests to check strategy behavior.
+ */
+ @VisibleForTesting
+ @Nullable
+ public synchronized PhoneTimeSuggestion findBestPhoneSuggestionForTests() {
+ return findBestPhoneSuggestion();
+ }
+
+ /**
+ * A method used to inspect state during tests. Not intended for general use.
+ */
+ @VisibleForTesting
+ @Nullable
+ public synchronized PhoneTimeSuggestion getLatestPhoneSuggestion(int phoneId) {
+ LinkedList<PhoneTimeSuggestion> suggestions = mSuggestionByPhoneId.get(phoneId);
+ if (suggestions == null) {
+ return null;
+ }
+ return suggestions.getFirst();
+ }
+}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java
index e034ad4..adf6d7e 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java
@@ -20,13 +20,9 @@
import android.app.AlarmManager;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.Intent;
import android.os.SystemProperties;
-import android.os.UserHandle;
import android.provider.Settings;
-import com.android.internal.telephony.TelephonyIntents;
-
/**
* The real implementation of {@link TimeZoneDetectorStrategy.Callback}.
*/
@@ -66,16 +62,8 @@
}
@Override
- public void setDeviceTimeZone(String zoneId, boolean sendNetworkBroadcast) {
+ public void setDeviceTimeZone(String zoneId) {
AlarmManager alarmManager = mContext.getSystemService(AlarmManager.class);
alarmManager.setTimeZone(zoneId);
-
- if (sendNetworkBroadcast) {
- // TODO Nothing in the platform appears to listen for this. Remove it.
- Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- intent.putExtra("time-zone", zoneId);
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
}
}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
index 5db12c7..b4d8053 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
@@ -86,7 +86,7 @@
/**
* Sets the device's time zone.
*/
- void setDeviceTimeZone(@NonNull String zoneId, boolean sendNetworkBroadcast);
+ void setDeviceTimeZone(@NonNull String zoneId);
}
private static final String LOG_TAG = "TimeZoneDetectorStrategy";
@@ -172,7 +172,7 @@
* (for use during debugging).
*/
@NonNull
- private final LocalLog mTimeZoneChangesLog = new LocalLog(30);
+ private final LocalLog mTimeZoneChangesLog = new LocalLog(30, false /* useLocalTimestamps */);
/**
* A mapping from phoneId to a linked list of phone time zone suggestions (the head being the
@@ -333,7 +333,6 @@
Objects.requireNonNull(newZoneId);
Objects.requireNonNull(cause);
- boolean sendNetworkBroadcast = (origin == ORIGIN_PHONE);
boolean isOriginAutomatic = isOriginAutomatic(origin);
if (isOriginAutomatic) {
if (!mCallback.isAutoTimeZoneDetectionEnabled()) {
@@ -373,12 +372,11 @@
return;
}
- mCallback.setDeviceTimeZone(newZoneId, sendNetworkBroadcast);
+ mCallback.setDeviceTimeZone(newZoneId);
String msg = "Set device time zone."
+ " origin=" + origin
+ ", currentZoneId=" + currentZoneId
+ ", newZoneId=" + newZoneId
- + ", sendNetworkBroadcast" + sendNetworkBroadcast
+ ", cause=" + cause;
if (DBG) {
Slog.d(LOG_TAG, msg);
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
old mode 100644
new mode 100755
index 8e66b14..18ed51a
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -2943,6 +2943,16 @@
if (state != null) {
setStateLocked(inputId, state, mCurrentUserId);
}
+ UserState userState = getOrCreateUserStateLocked(mCurrentUserId);
+ // Broadcast the event to all hardware inputs.
+ for (ServiceState serviceState : userState.serviceStateMap.values()) {
+ if (!serviceState.isHardware || serviceState.service == null) continue;
+ try {
+ serviceState.service.notifyHdmiDeviceUpdated(deviceInfo);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in notifyHdmiDeviceUpdated", e);
+ }
+ }
}
}
}
diff --git a/services/core/jni/com_android_server_security_VerityUtils.cpp b/services/core/jni/com_android_server_security_VerityUtils.cpp
index 6cd9f2c..9ceb770 100644
--- a/services/core/jni/com_android_server_security_VerityUtils.cpp
+++ b/services/core/jni/com_android_server_security_VerityUtils.cpp
@@ -36,61 +36,33 @@
#include <linux/fsverity.h>
#else
-// Before fs-verity is upstreamed, use the current snapshot for development.
-// https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/tree/include/uapi/linux/fsverity.h?h=fsverity
-
#include <linux/limits.h>
#include <linux/ioctl.h>
#include <linux/types.h>
+#define FS_VERITY_HASH_ALG_SHA256 1
+
+struct fsverity_enable_arg {
+ __u32 version;
+ __u32 hash_algorithm;
+ __u32 block_size;
+ __u32 salt_size;
+ __u64 salt_ptr;
+ __u32 sig_size;
+ __u32 __reserved1;
+ __u64 sig_ptr;
+ __u64 __reserved2[11];
+};
+
struct fsverity_digest {
__u16 digest_algorithm;
__u16 digest_size; /* input/output */
__u8 digest[];
};
-#define FS_IOC_ENABLE_VERITY _IO('f', 133)
+#define FS_IOC_ENABLE_VERITY _IOW('f', 133, struct fsverity_enable_arg)
#define FS_IOC_MEASURE_VERITY _IOWR('f', 134, struct fsverity_digest)
-#define FS_VERITY_MAGIC "FSVerity"
-
-#define FS_VERITY_ALG_SHA256 1
-
-struct fsverity_descriptor {
- __u8 magic[8]; /* must be FS_VERITY_MAGIC */
- __u8 major_version; /* must be 1 */
- __u8 minor_version; /* must be 0 */
- __u8 log_data_blocksize;/* log2(data-bytes-per-hash), e.g. 12 for 4KB */
- __u8 log_tree_blocksize;/* log2(tree-bytes-per-hash), e.g. 12 for 4KB */
- __le16 data_algorithm; /* hash algorithm for data blocks */
- __le16 tree_algorithm; /* hash algorithm for tree blocks */
- __le32 flags; /* flags */
- __le32 __reserved1; /* must be 0 */
- __le64 orig_file_size; /* size of the original file data */
- __le16 auth_ext_count; /* number of authenticated extensions */
- __u8 __reserved2[30]; /* must be 0 */
-};
-
-#define FS_VERITY_EXT_ROOT_HASH 1
-#define FS_VERITY_EXT_PKCS7_SIGNATURE 3
-
-struct fsverity_extension {
- __le32 length;
- __le16 type; /* Type of this extension (see codes above) */
- __le16 __reserved; /* Reserved, must be 0 */
-};
-
-struct fsverity_digest_disk {
- __le16 digest_algorithm;
- __le16 digest_size;
- __u8 digest[];
-};
-
-struct fsverity_footer {
- __le32 desc_reverse_offset; /* distance to fsverity_descriptor */
- __u8 magic[8]; /* FS_VERITY_MAGIC */
-} __packed;
-
#endif
const int kSha256Bytes = 32;
@@ -99,52 +71,24 @@
namespace {
-class JavaByteArrayHolder {
- public:
- JavaByteArrayHolder(const JavaByteArrayHolder &other) = delete;
- JavaByteArrayHolder(JavaByteArrayHolder &&other)
- : mEnv(other.mEnv), mBytes(other.mBytes), mElements(other.mElements) {
- other.mElements = nullptr;
- }
-
- static JavaByteArrayHolder newArray(JNIEnv* env, jsize size) {
- return JavaByteArrayHolder(env, size);
- }
-
- jbyte* getRaw() {
- return mElements;
- }
-
- jbyteArray release() {
- mEnv->ReleaseByteArrayElements(mBytes, mElements, 0);
- mElements = nullptr;
- return mBytes;
- }
-
- ~JavaByteArrayHolder() {
- LOG_ALWAYS_FATAL_IF(mElements != nullptr, "Elements are not released");
- }
-
- private:
- JavaByteArrayHolder(JNIEnv* env, jsize size) {
- mEnv = env;
- mBytes = mEnv->NewByteArray(size);
- mElements = mEnv->GetByteArrayElements(mBytes, nullptr);
- memset(mElements, 0, size);
- }
-
- JNIEnv* mEnv;
- jbyteArray mBytes;
- jbyte* mElements;
-};
-
-int enableFsverity(JNIEnv* env, jobject /* clazz */, jstring filePath) {
+int enableFsverity(JNIEnv* env, jobject /* clazz */, jstring filePath, jbyteArray signature) {
const char* path = env->GetStringUTFChars(filePath, nullptr);
::android::base::unique_fd rfd(open(path, O_RDONLY | O_CLOEXEC));
+ env->ReleaseStringUTFChars(filePath, path);
if (rfd.get() < 0) {
return errno;
}
- if (ioctl(rfd.get(), FS_IOC_ENABLE_VERITY, nullptr) < 0) {
+
+ fsverity_enable_arg arg = {};
+ arg.version = 1;
+ arg.hash_algorithm = FS_VERITY_HASH_ALG_SHA256;
+ arg.block_size = 4096;
+ arg.salt_size = 0;
+ arg.salt_ptr = reinterpret_cast<uintptr_t>(nullptr);
+ arg.sig_size = env->GetArrayLength(signature);
+ arg.sig_ptr = reinterpret_cast<uintptr_t>(signature);
+
+ if (ioctl(rfd.get(), FS_IOC_ENABLE_VERITY, &arg) < 0) {
return errno;
}
return 0;
@@ -159,6 +103,7 @@
const char* path = env->GetStringUTFChars(filePath, nullptr);
::android::base::unique_fd rfd(open(path, O_RDONLY | O_CLOEXEC));
+ env->ReleaseStringUTFChars(filePath, path);
if (rfd.get() < 0) {
return errno;
}
@@ -168,71 +113,9 @@
return 0;
}
-jbyteArray constructFsveritySignedData(JNIEnv* env, jobject /* clazz */, jbyteArray digest) {
- auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_digest_disk) + kSha256Bytes);
- fsverity_digest_disk* data = reinterpret_cast<fsverity_digest_disk*>(raii.getRaw());
-
- data->digest_algorithm = FS_VERITY_ALG_SHA256;
- data->digest_size = kSha256Bytes;
- if (env->GetArrayLength(digest) != kSha256Bytes) {
- jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "Invalid hash size of %d",
- env->GetArrayLength(digest));
- return 0;
- }
- const jbyte* src = env->GetByteArrayElements(digest, nullptr);
- memcpy(data->digest, src, kSha256Bytes);
-
- return raii.release();
-}
-
-
-jbyteArray constructFsverityDescriptor(JNIEnv* env, jobject /* clazz */, jlong fileSize) {
- auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_descriptor));
- fsverity_descriptor* desc = reinterpret_cast<fsverity_descriptor*>(raii.getRaw());
-
- memcpy(desc->magic, FS_VERITY_MAGIC, sizeof(desc->magic));
- desc->major_version = 1;
- desc->minor_version = 0;
- desc->log_data_blocksize = 12;
- desc->log_tree_blocksize = 12;
- desc->data_algorithm = FS_VERITY_ALG_SHA256;
- desc->tree_algorithm = FS_VERITY_ALG_SHA256;
- desc->flags = 0;
- desc->orig_file_size = fileSize;
- desc->auth_ext_count = 1;
-
- return raii.release();
-}
-
-jbyteArray constructFsverityExtension(JNIEnv* env, jobject /* clazz */, jshort extensionId,
- jint extensionDataSize) {
- auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_extension));
- fsverity_extension* ext = reinterpret_cast<fsverity_extension*>(raii.getRaw());
-
- ext->length = sizeof(fsverity_extension) + extensionDataSize;
- ext->type = extensionId;
-
- return raii.release();
-}
-
-jbyteArray constructFsverityFooter(JNIEnv* env, jobject /* clazz */,
- jint offsetToDescriptorHead) {
- auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_footer));
- fsverity_footer* footer = reinterpret_cast<fsverity_footer*>(raii.getRaw());
-
- footer->desc_reverse_offset = offsetToDescriptorHead + sizeof(fsverity_footer);
- memcpy(footer->magic, FS_VERITY_MAGIC, sizeof(footer->magic));
-
- return raii.release();
-}
-
const JNINativeMethod sMethods[] = {
- { "enableFsverityNative", "(Ljava/lang/String;)I", (void *)enableFsverity },
+ { "enableFsverityNative", "(Ljava/lang/String;[B)I", (void *)enableFsverity },
{ "measureFsverityNative", "(Ljava/lang/String;)I", (void *)measureFsverity },
- { "constructFsveritySignedDataNative", "([B)[B", (void *)constructFsveritySignedData },
- { "constructFsverityDescriptorNative", "(J)[B", (void *)constructFsverityDescriptor },
- { "constructFsverityExtensionNative", "(SI)[B", (void *)constructFsverityExtension },
- { "constructFsverityFooterNative", "(I)[B", (void *)constructFsverityFooter },
};
} // namespace
diff --git a/services/coverage/Android.bp b/services/coverage/Android.bp
index 16c9c1b..e4f5464 100644
--- a/services/coverage/Android.bp
+++ b/services/coverage/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.coverage-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.coverage",
- srcs: ["java/**/*.java"],
+ srcs: [":services.coverage-sources"],
libs: ["jacocoagent"],
}
diff --git a/services/devicepolicy/Android.bp b/services/devicepolicy/Android.bp
index dbe0d81..2f6592b 100644
--- a/services/devicepolicy/Android.bp
+++ b/services/devicepolicy/Android.bp
@@ -1,6 +1,13 @@
+filegroup {
+ name: "services.devicepolicy-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.devicepolicy",
- srcs: ["java/**/*.java"],
+ srcs: [":services.devicepolicy-sources"],
libs: [
"services.core",
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index e09e88f..2528063 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -40,12 +40,12 @@
import android.database.sqlite.SQLiteGlobal;
import android.hardware.display.DisplayManagerInternal;
import android.net.ConnectivityModuleConnector;
-import android.net.Network;
import android.net.NetworkStackClient;
import android.net.TetheringManager;
import android.os.BaseBundle;
import android.os.Binder;
import android.os.Build;
+import android.os.Debug;
import android.os.Environment;
import android.os.FactoryTest;
import android.os.FileUtils;
@@ -446,10 +446,6 @@
// Mmmmmm... more memory!
VMRuntime.getRuntime().clearGrowthLimit();
- // The system server has to run all of the time, so it needs to be
- // as efficient as possible with its memory usage.
- VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
-
// Some devices rely on runtime fingerprint generation, so make sure
// we've defined it before booting further.
Build.ensureFingerprintProperty();
@@ -501,6 +497,24 @@
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.get();
+ // Attach JVMTI agent if this is a debuggable build and the system property is set.
+ if (Build.IS_DEBUGGABLE) {
+ // Property is of the form "library_path=parameters".
+ String jvmtiAgent = SystemProperties.get("persist.sys.dalvik.jvmtiagent");
+ if (!jvmtiAgent.isEmpty()) {
+ int equalIndex = jvmtiAgent.indexOf('=');
+ String libraryPath = jvmtiAgent.substring(0, equalIndex);
+ String parameterList =
+ jvmtiAgent.substring(equalIndex + 1, jvmtiAgent.length());
+ // Attach the agent.
+ try {
+ Debug.attachJvmtiAgent(libraryPath, parameterList, null);
+ } catch (Exception e) {
+ Slog.e("System", "*************************************************");
+ Slog.e("System", "********** Failed to load jvmti plugin: " + jvmtiAgent);
+ }
+ }
+ }
} finally {
traceEnd(); // InitBeforeStartServices
}
diff --git a/services/midi/Android.bp b/services/midi/Android.bp
index 3745e89..20e0083 100644
--- a/services/midi/Android.bp
+++ b/services/midi/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.midi-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.midi",
- srcs: ["java/**/*.java"],
+ srcs: [":services.midi-sources"],
libs: ["services.core"],
}
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 2dabdb7..3babb0b 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -1,8 +1,15 @@
+filegroup {
+ name: "services.net-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.net",
srcs: [
":net-module-utils-srcs",
- "java/**/*.java",
+ ":services.net-sources",
":tethering-manager",
],
static_libs: [
@@ -23,4 +30,5 @@
"java/android/net/util/NetdService.java",
"java/android/net/util/NetworkConstants.java",
],
+ visibility: ["//frameworks/base/packages/Tethering"],
}
diff --git a/services/print/Android.bp b/services/print/Android.bp
index 80a8c75..aad24d7 100644
--- a/services/print/Android.bp
+++ b/services/print/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.print-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.print",
- srcs: ["java/**/*.java"],
+ srcs: [":services.print-sources"],
libs: ["services.core"],
}
diff --git a/services/restrictions/Android.bp b/services/restrictions/Android.bp
index 979e891..805858f 100644
--- a/services/restrictions/Android.bp
+++ b/services/restrictions/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.restrictions-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.restrictions",
- srcs: ["java/**/*.java"],
+ srcs: [":services.restrictions-sources"],
libs: ["services.core"],
}
diff --git a/services/systemcaptions/Android.bp b/services/systemcaptions/Android.bp
index 4e190b6..1ce3e66 100644
--- a/services/systemcaptions/Android.bp
+++ b/services/systemcaptions/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.systemcaptions-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.systemcaptions",
- srcs: ["java/**/*.java"],
+ srcs: [":services.systemcaptions-sources"],
libs: ["services.core"],
}
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 32aa6e1..61fe01f 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -40,6 +40,7 @@
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<uses-permission android:name="android.permission.MANAGE_DEVICE_ADMINS" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
+ <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD" />
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 49c22a3..7e08d95 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -137,7 +137,6 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.BroadcastInterceptingContext.FutureIntent;
import com.android.server.DeviceIdleController;
@@ -1408,7 +1407,7 @@
// smoke test to make sure no errors are raised
mServiceContext.sendBroadcast(
new Intent(ACTION_CARRIER_CONFIG_CHANGED)
- .putExtra(PhoneConstants.SUBSCRIPTION_KEY, FAKE_SUB_ID)
+ .putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, FAKE_SUB_ID)
);
assertNetworkPolicyEquals(DEFAULT_CYCLE_DAY, mDefaultWarningBytes, mDefaultLimitBytes,
true);
@@ -1423,7 +1422,7 @@
bundle.putLong(CarrierConfigManager.KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG, -100);
mServiceContext.sendBroadcast(
new Intent(ACTION_CARRIER_CONFIG_CHANGED)
- .putExtra(PhoneConstants.SUBSCRIPTION_KEY, FAKE_SUB_ID)
+ .putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, FAKE_SUB_ID)
);
assertNetworkPolicyEquals(DEFAULT_CYCLE_DAY, mDefaultWarningBytes, mDefaultLimitBytes,
@@ -1442,7 +1441,7 @@
DATA_CYCLE_USE_PLATFORM_DEFAULT);
mServiceContext.sendBroadcast(
new Intent(ACTION_CARRIER_CONFIG_CHANGED)
- .putExtra(PhoneConstants.SUBSCRIPTION_KEY, FAKE_SUB_ID)
+ .putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, FAKE_SUB_ID)
);
assertNetworkPolicyEquals(DEFAULT_CYCLE_DAY, mDefaultWarningBytes, mDefaultLimitBytes,
@@ -1464,7 +1463,7 @@
DATA_CYCLE_THRESHOLD_DISABLED);
mServiceContext.sendBroadcast(
new Intent(ACTION_CARRIER_CONFIG_CHANGED)
- .putExtra(PhoneConstants.SUBSCRIPTION_KEY, FAKE_SUB_ID)
+ .putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, FAKE_SUB_ID)
);
// The policy still shouldn't change, because we don't want to overwrite user settings.
@@ -1481,7 +1480,7 @@
bundle.putLong(CarrierConfigManager.KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG, 9999);
mServiceContext.sendBroadcast(
new Intent(ACTION_CARRIER_CONFIG_CHANGED)
- .putExtra(PhoneConstants.SUBSCRIPTION_KEY, FAKE_SUB_ID)
+ .putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, FAKE_SUB_ID)
);
assertNetworkPolicyEquals(31, 9999, 9999, true);
@@ -1498,7 +1497,7 @@
DATA_CYCLE_THRESHOLD_DISABLED);
mServiceContext.sendBroadcast(
new Intent(ACTION_CARRIER_CONFIG_CHANGED)
- .putExtra(PhoneConstants.SUBSCRIPTION_KEY, FAKE_SUB_ID)
+ .putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, FAKE_SUB_ID)
);
assertNetworkPolicyEquals(31, WARNING_DISABLED, LIMIT_DISABLED, true);
@@ -1515,7 +1514,7 @@
DATA_CYCLE_THRESHOLD_DISABLED);
mServiceContext.sendBroadcast(
new Intent(ACTION_CARRIER_CONFIG_CHANGED)
- .putExtra(PhoneConstants.SUBSCRIPTION_KEY, FAKE_SUB_ID)
+ .putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, FAKE_SUB_ID)
);
assertNetworkPolicyEquals(31, WARNING_DISABLED, LIMIT_DISABLED, true);
@@ -1530,7 +1529,7 @@
DATA_CYCLE_USE_PLATFORM_DEFAULT);
mServiceContext.sendBroadcast(
new Intent(ACTION_CARRIER_CONFIG_CHANGED)
- .putExtra(PhoneConstants.SUBSCRIPTION_KEY, FAKE_SUB_ID)
+ .putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, FAKE_SUB_ID)
);
assertNetworkPolicyEquals(31, mDefaultWarningBytes, mDefaultLimitBytes,
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/SimpleTimeDetectorStrategyTest.java b/services/tests/servicestests/src/com/android/server/timedetector/SimpleTimeDetectorStrategyTest.java
deleted file mode 100644
index 7a0a28d..0000000
--- a/services/tests/servicestests/src/com/android/server/timedetector/SimpleTimeDetectorStrategyTest.java
+++ /dev/null
@@ -1,661 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.timedetector;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import android.app.timedetector.ManualTimeSuggestion;
-import android.app.timedetector.PhoneTimeSuggestion;
-import android.content.Intent;
-import android.icu.util.Calendar;
-import android.icu.util.GregorianCalendar;
-import android.icu.util.TimeZone;
-import android.util.TimestampedValue;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.time.Duration;
-
-@RunWith(AndroidJUnit4.class)
-public class SimpleTimeDetectorStrategyTest {
-
- private static final Scenario SCENARIO_1 = new Scenario.Builder()
- .setInitialDeviceSystemClockUtc(1977, 1, 1, 12, 0, 0)
- .setInitialDeviceRealtimeMillis(123456789L)
- .setActualTimeUtc(2018, 1, 1, 12, 0, 0)
- .build();
-
- private static final int ARBITRARY_PHONE_ID = 123456;
-
- private static final long ONE_DAY_MILLIS = Duration.ofDays(1).toMillis();
-
- private Script mScript;
-
- @Before
- public void setUp() {
- mScript = new Script();
- }
-
- @Test
- public void testSuggestPhoneTime_autoTimeEnabled() {
- Scenario scenario = SCENARIO_1;
- mScript.pokeFakeClocks(scenario)
- .pokeTimeDetectionEnabled(true);
-
- PhoneTimeSuggestion timeSuggestion =
- scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
- final int clockIncrement = 1000;
- long expectSystemClockMillis = scenario.getActualTimeMillis() + clockIncrement;
-
- mScript.simulateTimePassing(clockIncrement)
- .simulatePhoneTimeSuggestion(timeSuggestion)
- .verifySystemClockWasSetAndResetCallTracking(
- expectSystemClockMillis, true /* expectNetworkBroadcast */);
- }
-
- @Test
- public void testSuggestPhoneTime_emptySuggestionIgnored() {
- Scenario scenario = SCENARIO_1;
- mScript.pokeFakeClocks(scenario)
- .pokeTimeDetectionEnabled(true);
-
- PhoneTimeSuggestion timeSuggestion = createPhoneTimeSuggestion(ARBITRARY_PHONE_ID, null);
-
- mScript.simulatePhoneTimeSuggestion(timeSuggestion)
- .verifySystemClockWasNotSetAndResetCallTracking();
- }
-
- @Test
- public void testSuggestPhoneTime_systemClockThreshold() {
- Scenario scenario = SCENARIO_1;
- final int systemClockUpdateThresholdMillis = 1000;
- mScript.pokeFakeClocks(scenario)
- .pokeThresholds(systemClockUpdateThresholdMillis)
- .pokeTimeDetectionEnabled(true);
-
- PhoneTimeSuggestion timeSuggestion1 =
- scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
- TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
-
- final int clockIncrement = 100;
- // Increment the the device clocks to simulate the passage of time.
- mScript.simulateTimePassing(clockIncrement);
-
- long expectSystemClockMillis1 =
- TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
-
- // Send the first time signal. It should be used.
- mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
- .verifySystemClockWasSetAndResetCallTracking(
- expectSystemClockMillis1, true /* expectNetworkBroadcast */);
-
- // Now send another time signal, but one that is too similar to the last one and should be
- // ignored.
- int underThresholdMillis = systemClockUpdateThresholdMillis - 1;
- TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
- mScript.peekElapsedRealtimeMillis(),
- mScript.peekSystemClockMillis() + underThresholdMillis);
- PhoneTimeSuggestion timeSuggestion2 =
- createPhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime2);
- mScript.simulateTimePassing(clockIncrement)
- .simulatePhoneTimeSuggestion(timeSuggestion2)
- .verifySystemClockWasNotSetAndResetCallTracking();
-
- // Now send another time signal, but one that is on the threshold and so should be used.
- TimestampedValue<Long> utcTime3 = new TimestampedValue<>(
- mScript.peekElapsedRealtimeMillis(),
- mScript.peekSystemClockMillis() + systemClockUpdateThresholdMillis);
-
- PhoneTimeSuggestion timeSuggestion3 =
- createPhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime3);
- mScript.simulateTimePassing(clockIncrement);
-
- long expectSystemClockMillis3 =
- TimeDetectorStrategy.getTimeAt(utcTime3, mScript.peekElapsedRealtimeMillis());
-
- mScript.simulatePhoneTimeSuggestion(timeSuggestion3)
- .verifySystemClockWasSetAndResetCallTracking(
- expectSystemClockMillis3, true /* expectNetworkBroadcast */);
- }
-
- @Test
- public void testSuggestPhoneTime_autoTimeDisabled() {
- Scenario scenario = SCENARIO_1;
- mScript.pokeFakeClocks(scenario)
- .pokeTimeDetectionEnabled(false);
-
- PhoneTimeSuggestion timeSuggestion =
- scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
- mScript.simulatePhoneTimeSuggestion(timeSuggestion)
- .verifySystemClockWasNotSetAndResetCallTracking();
- }
-
- @Test
- public void testSuggestPhoneTime_invalidNitzReferenceTimesIgnored() {
- Scenario scenario = SCENARIO_1;
- final int systemClockUpdateThreshold = 2000;
- mScript.pokeFakeClocks(scenario)
- .pokeThresholds(systemClockUpdateThreshold)
- .pokeTimeDetectionEnabled(true);
- PhoneTimeSuggestion timeSuggestion1 =
- scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
- TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
-
- // Initialize the strategy / device with a time set from NITZ.
- mScript.simulateTimePassing(100);
- long expectedSystemClockMillis1 =
- TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
- mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
- .verifySystemClockWasSetAndResetCallTracking(
- expectedSystemClockMillis1, true /* expectNetworkBroadcast */);
-
- // The UTC time increment should be larger than the system clock update threshold so we
- // know it shouldn't be ignored for other reasons.
- long validUtcTimeMillis = utcTime1.getValue() + (2 * systemClockUpdateThreshold);
-
- // Now supply a new signal that has an obviously bogus reference time : older than the last
- // one.
- long referenceTimeBeforeLastSignalMillis = utcTime1.getReferenceTimeMillis() - 1;
- TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
- referenceTimeBeforeLastSignalMillis, validUtcTimeMillis);
- PhoneTimeSuggestion timeSuggestion2 =
- createPhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime2);
- mScript.simulatePhoneTimeSuggestion(timeSuggestion2)
- .verifySystemClockWasNotSetAndResetCallTracking();
-
- // Now supply a new signal that has an obviously bogus reference time : substantially in the
- // future.
- long referenceTimeInFutureMillis =
- utcTime1.getReferenceTimeMillis() + Integer.MAX_VALUE + 1;
- TimestampedValue<Long> utcTime3 = new TimestampedValue<>(
- referenceTimeInFutureMillis, validUtcTimeMillis);
- PhoneTimeSuggestion timeSuggestion3 =
- createPhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime3);
- mScript.simulatePhoneTimeSuggestion(timeSuggestion3)
- .verifySystemClockWasNotSetAndResetCallTracking();
-
- // Just to prove validUtcTimeMillis is valid.
- long validReferenceTimeMillis = utcTime1.getReferenceTimeMillis() + 100;
- TimestampedValue<Long> utcTime4 = new TimestampedValue<>(
- validReferenceTimeMillis, validUtcTimeMillis);
- long expectedSystemClockMillis4 =
- TimeDetectorStrategy.getTimeAt(utcTime4, mScript.peekElapsedRealtimeMillis());
- PhoneTimeSuggestion timeSuggestion4 =
- createPhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime4);
- mScript.simulatePhoneTimeSuggestion(timeSuggestion4)
- .verifySystemClockWasSetAndResetCallTracking(
- expectedSystemClockMillis4, true /* expectNetworkBroadcast */);
- }
-
- @Test
- public void testSuggestPhoneTime_timeDetectionToggled() {
- Scenario scenario = SCENARIO_1;
- final int clockIncrementMillis = 100;
- final int systemClockUpdateThreshold = 2000;
- mScript.pokeFakeClocks(scenario)
- .pokeThresholds(systemClockUpdateThreshold)
- .pokeTimeDetectionEnabled(false);
-
- PhoneTimeSuggestion timeSuggestion1 =
- scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
- TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
-
- // Simulate time passing.
- mScript.simulateTimePassing(clockIncrementMillis);
-
- // Simulate the time signal being received. It should not be used because auto time
- // detection is off but it should be recorded.
- mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
- .verifySystemClockWasNotSetAndResetCallTracking();
-
- // Simulate more time passing.
- mScript.simulateTimePassing(clockIncrementMillis);
-
- long expectedSystemClockMillis1 =
- TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
-
- // Turn on auto time detection.
- mScript.simulateAutoTimeDetectionToggle()
- .verifySystemClockWasSetAndResetCallTracking(
- expectedSystemClockMillis1, true /* expectNetworkBroadcast */);
-
- // Turn off auto time detection.
- mScript.simulateAutoTimeDetectionToggle()
- .verifySystemClockWasNotSetAndResetCallTracking();
-
- // Receive another valid time signal.
- // It should be on the threshold and accounting for the clock increments.
- TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
- mScript.peekElapsedRealtimeMillis(),
- mScript.peekSystemClockMillis() + systemClockUpdateThreshold);
- PhoneTimeSuggestion timeSuggestion2 =
- createPhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime2);
-
- // Simulate more time passing.
- mScript.simulateTimePassing(clockIncrementMillis);
-
- long expectedSystemClockMillis2 =
- TimeDetectorStrategy.getTimeAt(utcTime2, mScript.peekElapsedRealtimeMillis());
-
- // The new time, though valid, should not be set in the system clock because auto time is
- // disabled.
- mScript.simulatePhoneTimeSuggestion(timeSuggestion2)
- .verifySystemClockWasNotSetAndResetCallTracking();
-
- // Turn on auto time detection.
- mScript.simulateAutoTimeDetectionToggle()
- .verifySystemClockWasSetAndResetCallTracking(
- expectedSystemClockMillis2, true /* expectNetworkBroadcast */);
- }
-
- @Test
- public void testSuggestManualTime_autoTimeDisabled() {
- Scenario scenario = SCENARIO_1;
- mScript.pokeFakeClocks(scenario)
- .pokeTimeDetectionEnabled(false);
-
- ManualTimeSuggestion timeSuggestion = scenario.createManualTimeSuggestionForActual();
- final int clockIncrement = 1000;
- long expectSystemClockMillis = scenario.getActualTimeMillis() + clockIncrement;
-
- mScript.simulateTimePassing(clockIncrement)
- .simulateManualTimeSuggestion(timeSuggestion)
- .verifySystemClockWasSetAndResetCallTracking(
- expectSystemClockMillis, false /* expectNetworkBroadcast */);
- }
-
- @Test
- public void testSuggestManualTime_retainsAutoSignal() {
- Scenario scenario = SCENARIO_1;
-
- // Configure the start state.
- mScript.pokeFakeClocks(scenario)
- .pokeTimeDetectionEnabled(true);
-
- // Simulate a phone suggestion.
- PhoneTimeSuggestion phoneTimeSuggestion =
- scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
- long expectedAutoClockMillis = phoneTimeSuggestion.getUtcTime().getValue();
- final int clockIncrement = 1000;
-
- // Simulate the passage of time.
- mScript.simulateTimePassing(clockIncrement);
- expectedAutoClockMillis += clockIncrement;
-
- mScript.simulatePhoneTimeSuggestion(phoneTimeSuggestion)
- .verifySystemClockWasSetAndResetCallTracking(
- expectedAutoClockMillis, true /* expectNetworkBroadcast */);
-
- // Simulate the passage of time.
- mScript.simulateTimePassing(clockIncrement);
- expectedAutoClockMillis += clockIncrement;
-
- // Switch to manual.
- mScript.simulateAutoTimeDetectionToggle()
- .verifySystemClockWasNotSetAndResetCallTracking();
-
- // Simulate the passage of time.
- mScript.simulateTimePassing(clockIncrement);
- expectedAutoClockMillis += clockIncrement;
-
-
- // Simulate a manual suggestion 1 day different from the auto suggestion.
- long manualTimeMillis = SCENARIO_1.getActualTimeMillis() + ONE_DAY_MILLIS;
- long expectedManualClockMillis = manualTimeMillis;
- ManualTimeSuggestion manualTimeSuggestion = createManualTimeSuggestion(manualTimeMillis);
- mScript.simulateManualTimeSuggestion(manualTimeSuggestion)
- .verifySystemClockWasSetAndResetCallTracking(
- expectedManualClockMillis, false /* expectNetworkBroadcast */);
-
- // Simulate the passage of time.
- mScript.simulateTimePassing(clockIncrement);
- expectedAutoClockMillis += clockIncrement;
-
- // Switch back to auto.
- mScript.simulateAutoTimeDetectionToggle();
-
- mScript.verifySystemClockWasSetAndResetCallTracking(
- expectedAutoClockMillis, true /* expectNetworkBroadcast */);
-
- // Switch back to manual - nothing should happen to the clock.
- mScript.simulateAutoTimeDetectionToggle()
- .verifySystemClockWasNotSetAndResetCallTracking();
- }
-
- /**
- * Manual suggestions should be ignored if auto time is enabled.
- */
- @Test
- public void testSuggestManualTime_autoTimeEnabled() {
- Scenario scenario = SCENARIO_1;
- mScript.pokeFakeClocks(scenario)
- .pokeTimeDetectionEnabled(true);
-
- ManualTimeSuggestion timeSuggestion = scenario.createManualTimeSuggestionForActual();
- final int clockIncrement = 1000;
-
- mScript.simulateTimePassing(clockIncrement)
- .simulateManualTimeSuggestion(timeSuggestion)
- .verifySystemClockWasNotSetAndResetCallTracking();
- }
-
- /**
- * A fake implementation of TimeDetectorStrategy.Callback. Besides tracking changes and behaving
- * like the real thing should, it also asserts preconditions.
- */
- private static class FakeCallback implements TimeDetectorStrategy.Callback {
- private boolean mTimeDetectionEnabled;
- private boolean mWakeLockAcquired;
- private long mElapsedRealtimeMillis;
- private long mSystemClockMillis;
- private int mSystemClockUpdateThresholdMillis = 2000;
-
- // Tracking operations.
- private boolean mSystemClockWasSet;
- private Intent mBroadcastSent;
-
- @Override
- public int systemClockUpdateThresholdMillis() {
- return mSystemClockUpdateThresholdMillis;
- }
-
- @Override
- public boolean isAutoTimeDetectionEnabled() {
- return mTimeDetectionEnabled;
- }
-
- @Override
- public void acquireWakeLock() {
- if (mWakeLockAcquired) {
- fail("Wake lock already acquired");
- }
- mWakeLockAcquired = true;
- }
-
- @Override
- public long elapsedRealtimeMillis() {
- assertWakeLockAcquired();
- return mElapsedRealtimeMillis;
- }
-
- @Override
- public long systemClockMillis() {
- assertWakeLockAcquired();
- return mSystemClockMillis;
- }
-
- @Override
- public void setSystemClock(long newTimeMillis) {
- assertWakeLockAcquired();
- mSystemClockWasSet = true;
- mSystemClockMillis = newTimeMillis;
- }
-
- @Override
- public void releaseWakeLock() {
- assertWakeLockAcquired();
- mWakeLockAcquired = false;
- }
-
- @Override
- public void sendStickyBroadcast(Intent intent) {
- assertNotNull(intent);
- mBroadcastSent = intent;
- }
-
- // Methods below are for managing the fake's behavior.
-
- public void pokeSystemClockUpdateThreshold(int thresholdMillis) {
- mSystemClockUpdateThresholdMillis = thresholdMillis;
- }
-
- public void pokeElapsedRealtimeMillis(long elapsedRealtimeMillis) {
- mElapsedRealtimeMillis = elapsedRealtimeMillis;
- }
-
- public void pokeSystemClockMillis(long systemClockMillis) {
- mSystemClockMillis = systemClockMillis;
- }
-
- public void pokeAutoTimeDetectionEnabled(boolean enabled) {
- mTimeDetectionEnabled = enabled;
- }
-
- public long peekElapsedRealtimeMillis() {
- return mElapsedRealtimeMillis;
- }
-
- public long peekSystemClockMillis() {
- return mSystemClockMillis;
- }
-
- public void simulateTimePassing(int incrementMillis) {
- mElapsedRealtimeMillis += incrementMillis;
- mSystemClockMillis += incrementMillis;
- }
-
- public void simulateAutoTimeZoneDetectionToggle() {
- mTimeDetectionEnabled = !mTimeDetectionEnabled;
- }
-
- public void verifySystemClockNotSet() {
- assertFalse(mSystemClockWasSet);
- }
-
- public void verifySystemClockWasSet(long expectSystemClockMillis) {
- assertTrue(mSystemClockWasSet);
- assertEquals(expectSystemClockMillis, mSystemClockMillis);
- }
-
- public void verifyIntentWasBroadcast() {
- assertTrue(mBroadcastSent != null);
- }
-
- public void verifyIntentWasNotBroadcast() {
- assertNull(mBroadcastSent);
- }
-
- public void resetCallTracking() {
- mSystemClockWasSet = false;
- mBroadcastSent = null;
- }
-
- private void assertWakeLockAcquired() {
- assertTrue("The operation must be performed only after acquiring the wakelock",
- mWakeLockAcquired);
- }
- }
-
- /**
- * A fluent helper class for tests.
- */
- private class Script {
-
- private final FakeCallback mFakeCallback;
- private final SimpleTimeDetectorStrategy mSimpleTimeDetectorStrategy;
-
- Script() {
- mFakeCallback = new FakeCallback();
- mSimpleTimeDetectorStrategy = new SimpleTimeDetectorStrategy();
- mSimpleTimeDetectorStrategy.initialize(mFakeCallback);
-
- }
-
- Script pokeTimeDetectionEnabled(boolean enabled) {
- mFakeCallback.pokeAutoTimeDetectionEnabled(enabled);
- return this;
- }
-
- Script pokeFakeClocks(Scenario scenario) {
- mFakeCallback.pokeElapsedRealtimeMillis(scenario.getInitialRealTimeMillis());
- mFakeCallback.pokeSystemClockMillis(scenario.getInitialSystemClockMillis());
- return this;
- }
-
- Script pokeThresholds(int systemClockUpdateThreshold) {
- mFakeCallback.pokeSystemClockUpdateThreshold(systemClockUpdateThreshold);
- return this;
- }
-
- long peekElapsedRealtimeMillis() {
- return mFakeCallback.peekElapsedRealtimeMillis();
- }
-
- long peekSystemClockMillis() {
- return mFakeCallback.peekSystemClockMillis();
- }
-
- Script simulatePhoneTimeSuggestion(PhoneTimeSuggestion timeSuggestion) {
- mSimpleTimeDetectorStrategy.suggestPhoneTime(timeSuggestion);
- return this;
- }
-
- Script simulateManualTimeSuggestion(ManualTimeSuggestion timeSuggestion) {
- mSimpleTimeDetectorStrategy.suggestManualTime(timeSuggestion);
- return this;
- }
-
- Script simulateAutoTimeDetectionToggle() {
- mFakeCallback.simulateAutoTimeZoneDetectionToggle();
- mSimpleTimeDetectorStrategy.handleAutoTimeDetectionChanged();
- return this;
- }
-
- Script simulateTimePassing(int clockIncrement) {
- mFakeCallback.simulateTimePassing(clockIncrement);
- return this;
- }
-
- Script verifySystemClockWasNotSetAndResetCallTracking() {
- mFakeCallback.verifySystemClockNotSet();
- mFakeCallback.verifyIntentWasNotBroadcast();
- mFakeCallback.resetCallTracking();
- return this;
- }
-
- Script verifySystemClockWasSetAndResetCallTracking(
- long expectSystemClockMillis, boolean expectNetworkBroadcast) {
- mFakeCallback.verifySystemClockWasSet(expectSystemClockMillis);
- if (expectNetworkBroadcast) {
- mFakeCallback.verifyIntentWasBroadcast();
- }
- mFakeCallback.resetCallTracking();
- return this;
- }
- }
-
- /**
- * A starting scenario used during tests. Describes a fictional "physical" reality.
- */
- private static class Scenario {
-
- private final long mInitialDeviceSystemClockMillis;
- private final long mInitialDeviceRealtimeMillis;
- private final long mActualTimeMillis;
-
- Scenario(long initialDeviceSystemClock, long elapsedRealtime, long timeMillis) {
- mInitialDeviceSystemClockMillis = initialDeviceSystemClock;
- mActualTimeMillis = timeMillis;
- mInitialDeviceRealtimeMillis = elapsedRealtime;
- }
-
- long getInitialRealTimeMillis() {
- return mInitialDeviceRealtimeMillis;
- }
-
- long getInitialSystemClockMillis() {
- return mInitialDeviceSystemClockMillis;
- }
-
- long getActualTimeMillis() {
- return mActualTimeMillis;
- }
-
- PhoneTimeSuggestion createPhoneTimeSuggestionForActual(int phoneId) {
- TimestampedValue<Long> time = new TimestampedValue<>(
- mInitialDeviceRealtimeMillis, mActualTimeMillis);
- return createPhoneTimeSuggestion(phoneId, time);
- }
-
- ManualTimeSuggestion createManualTimeSuggestionForActual() {
- TimestampedValue<Long> time = new TimestampedValue<>(
- mInitialDeviceRealtimeMillis, mActualTimeMillis);
- return new ManualTimeSuggestion(time);
- }
-
- static class Builder {
-
- private long mInitialDeviceSystemClockMillis;
- private long mInitialDeviceRealtimeMillis;
- private long mActualTimeMillis;
-
- Builder setInitialDeviceSystemClockUtc(int year, int monthInYear, int day,
- int hourOfDay, int minute, int second) {
- mInitialDeviceSystemClockMillis = createUtcTime(year, monthInYear, day, hourOfDay,
- minute, second);
- return this;
- }
-
- Builder setInitialDeviceRealtimeMillis(long realtimeMillis) {
- mInitialDeviceRealtimeMillis = realtimeMillis;
- return this;
- }
-
- Builder setActualTimeUtc(int year, int monthInYear, int day, int hourOfDay,
- int minute, int second) {
- mActualTimeMillis =
- createUtcTime(year, monthInYear, day, hourOfDay, minute, second);
- return this;
- }
-
- Scenario build() {
- return new Scenario(mInitialDeviceSystemClockMillis, mInitialDeviceRealtimeMillis,
- mActualTimeMillis);
- }
- }
- }
-
- private static PhoneTimeSuggestion createPhoneTimeSuggestion(int phoneId,
- TimestampedValue<Long> utcTime) {
- return new PhoneTimeSuggestion.Builder(phoneId)
- .setUtcTime(utcTime)
- .build();
- }
-
- private ManualTimeSuggestion createManualTimeSuggestion(long timeMillis) {
- TimestampedValue<Long> utcTime =
- new TimestampedValue<>(mScript.peekElapsedRealtimeMillis(), timeMillis);
- return new ManualTimeSuggestion(utcTime);
- }
-
- private static long createUtcTime(int year, int monthInYear, int day, int hourOfDay, int minute,
- int second) {
- Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("Etc/UTC"));
- cal.clear();
- cal.set(year, monthInYear - 1, day, hourOfDay, minute, second);
- return cal.getTimeInMillis();
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index 84b495f..72a7f50 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -38,8 +38,6 @@
import androidx.test.runner.AndroidJUnit4;
-import com.android.server.timedetector.TimeDetectorStrategy.Callback;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -52,7 +50,6 @@
private Context mMockContext;
private StubbedTimeDetectorStrategy mStubbedTimeDetectorStrategy;
- private Callback mMockCallback;
private TimeDetectorService mTimeDetectorService;
private HandlerThread mHandlerThread;
@@ -68,12 +65,10 @@
mHandlerThread.start();
mTestHandler = new TestHandler(mHandlerThread.getLooper());
- mMockCallback = mock(Callback.class);
mStubbedTimeDetectorStrategy = new StubbedTimeDetectorStrategy();
mTimeDetectorService = new TimeDetectorService(
- mMockContext, mTestHandler, mMockCallback,
- mStubbedTimeDetectorStrategy);
+ mMockContext, mTestHandler, mStubbedTimeDetectorStrategy);
}
@After
@@ -100,13 +95,13 @@
@Test
public void testSuggestManualTime() throws Exception {
- doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
+ doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
ManualTimeSuggestion manualTimeSuggestion = createManualTimeSuggestion();
mTimeDetectorService.suggestManualTime(manualTimeSuggestion);
mTestHandler.assertTotalMessagesEnqueued(1);
- verify(mMockContext).enforceCallingPermission(
+ verify(mMockContext).enforceCallingOrSelfPermission(
eq(android.Manifest.permission.SET_TIME),
anyString());
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
new file mode 100644
index 0000000..1aa3d8f
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -0,0 +1,758 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.timedetector;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.app.timedetector.ManualTimeSuggestion;
+import android.app.timedetector.PhoneTimeSuggestion;
+import android.content.Intent;
+import android.icu.util.Calendar;
+import android.icu.util.GregorianCalendar;
+import android.icu.util.TimeZone;
+import android.util.TimestampedValue;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.time.Duration;
+
+@RunWith(AndroidJUnit4.class)
+public class TimeDetectorStrategyImplTest {
+
+ private static final TimestampedValue<Long> ARBITRARY_CLOCK_INITIALIZATION_INFO =
+ new TimestampedValue<>(
+ 123456789L /* realtimeClockMillis */,
+ createUtcTime(1977, 1, 1, 12, 0, 0));
+
+ private static final long ARBITRARY_TEST_TIME_MILLIS = createUtcTime(2018, 1, 1, 12, 0, 0);
+
+ private static final int ARBITRARY_PHONE_ID = 123456;
+
+ private static final long ONE_DAY_MILLIS = Duration.ofDays(1).toMillis();
+
+ private Script mScript;
+
+ @Before
+ public void setUp() {
+ mScript = new Script();
+ }
+
+ @Test
+ public void testSuggestPhoneTime_autoTimeEnabled() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ int phoneId = ARBITRARY_PHONE_ID;
+ long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+ PhoneTimeSuggestion timeSuggestion =
+ mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
+ int clockIncrement = 1000;
+ long expectedSystemClockMillis = testTimeMillis + clockIncrement;
+
+ mScript.simulateTimePassing(clockIncrement)
+ .simulatePhoneTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(
+ expectedSystemClockMillis, true /* expectNetworkBroadcast */)
+ .assertLatestPhoneSuggestion(phoneId, timeSuggestion);
+ }
+
+ @Test
+ public void testSuggestPhoneTime_emptySuggestionIgnored() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ int phoneId = ARBITRARY_PHONE_ID;
+ PhoneTimeSuggestion timeSuggestion =
+ mScript.generatePhoneTimeSuggestion(phoneId, null);
+ mScript.simulatePhoneTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking()
+ .assertLatestPhoneSuggestion(phoneId, null);
+ }
+
+ @Test
+ public void testSuggestPhoneTime_systemClockThreshold() {
+ int systemClockUpdateThresholdMillis = 1000;
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeThresholds(systemClockUpdateThresholdMillis)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ final int clockIncrement = 100;
+ int phoneId = ARBITRARY_PHONE_ID;
+
+ // Send the first time signal. It should be used.
+ {
+ long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+ PhoneTimeSuggestion timeSuggestion1 =
+ mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
+ TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
+
+ // Increment the the device clocks to simulate the passage of time.
+ mScript.simulateTimePassing(clockIncrement);
+
+ long expectedSystemClockMillis1 =
+ TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
+
+ mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
+ .verifySystemClockWasSetAndResetCallTracking(
+ expectedSystemClockMillis1, true /* expectNetworkBroadcast */)
+ .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+ }
+
+ // Now send another time signal, but one that is too similar to the last one and should be
+ // stored, but not used to set the system clock.
+ {
+ int underThresholdMillis = systemClockUpdateThresholdMillis - 1;
+ PhoneTimeSuggestion timeSuggestion2 = mScript.generatePhoneTimeSuggestion(
+ phoneId, mScript.peekSystemClockMillis() + underThresholdMillis);
+ mScript.simulateTimePassing(clockIncrement)
+ .simulatePhoneTimeSuggestion(timeSuggestion2)
+ .verifySystemClockWasNotSetAndResetCallTracking()
+ .assertLatestPhoneSuggestion(phoneId, timeSuggestion2);
+ }
+
+ // Now send another time signal, but one that is on the threshold and so should be used.
+ {
+ PhoneTimeSuggestion timeSuggestion3 = mScript.generatePhoneTimeSuggestion(
+ phoneId,
+ mScript.peekSystemClockMillis() + systemClockUpdateThresholdMillis);
+ mScript.simulateTimePassing(clockIncrement);
+
+ long expectedSystemClockMillis3 =
+ TimeDetectorStrategy.getTimeAt(timeSuggestion3.getUtcTime(),
+ mScript.peekElapsedRealtimeMillis());
+
+ mScript.simulatePhoneTimeSuggestion(timeSuggestion3)
+ .verifySystemClockWasSetAndResetCallTracking(
+ expectedSystemClockMillis3, true /* expectNetworkBroadcast */)
+ .assertLatestPhoneSuggestion(phoneId, timeSuggestion3);
+ }
+ }
+
+ @Test
+ public void testSuggestPhoneTime_multiplePhoneIdsAndBucketing() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ // There are 2 phones in this test. Phone 2 has a different idea of the current time.
+ // phone1Id < phone2Id (which is important because the strategy uses the lowest ID when
+ // multiple phone suggestions are available.
+ int phone1Id = ARBITRARY_PHONE_ID;
+ int phone2Id = ARBITRARY_PHONE_ID + 1;
+ long phone1TimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+ long phone2TimeMillis = phone1TimeMillis + 60000;
+
+ final int clockIncrement = 999;
+
+ // Make a suggestion with phone2Id.
+ {
+ PhoneTimeSuggestion phone2TimeSuggestion =
+ mScript.generatePhoneTimeSuggestion(phone2Id, phone2TimeMillis);
+ mScript.simulateTimePassing(clockIncrement);
+
+ long expectedSystemClockMillis = phone2TimeMillis + clockIncrement;
+
+ mScript.simulatePhoneTimeSuggestion(phone2TimeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(
+ expectedSystemClockMillis, true /* expectNetworkBroadcast */)
+ .assertLatestPhoneSuggestion(phone1Id, null)
+ .assertLatestPhoneSuggestion(phone2Id, phone2TimeSuggestion);
+ }
+
+ mScript.simulateTimePassing(clockIncrement);
+
+ // Now make a different suggestion with phone1Id.
+ {
+ PhoneTimeSuggestion phone1TimeSuggestion =
+ mScript.generatePhoneTimeSuggestion(phone1Id, phone1TimeMillis);
+ mScript.simulateTimePassing(clockIncrement);
+
+ long expectedSystemClockMillis = phone1TimeMillis + clockIncrement;
+
+ mScript.simulatePhoneTimeSuggestion(phone1TimeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(
+ expectedSystemClockMillis, true /* expectNetworkBroadcast */)
+ .assertLatestPhoneSuggestion(phone1Id, phone1TimeSuggestion);
+
+ }
+
+ mScript.simulateTimePassing(clockIncrement);
+
+ // Make another suggestion with phone2Id. It should be stored but not used because the
+ // phone1Id suggestion will still "win".
+ {
+ PhoneTimeSuggestion phone2TimeSuggestion =
+ mScript.generatePhoneTimeSuggestion(phone2Id, phone2TimeMillis);
+ mScript.simulateTimePassing(clockIncrement);
+
+ mScript.simulatePhoneTimeSuggestion(phone2TimeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking()
+ .assertLatestPhoneSuggestion(phone2Id, phone2TimeSuggestion);
+ }
+
+ // Let enough time pass that phone1Id's suggestion should now be too old.
+ mScript.simulateTimePassing(TimeDetectorStrategyImpl.PHONE_BUCKET_SIZE_MILLIS);
+
+ // Make another suggestion with phone2Id. It should be used because the phoneId1
+ // is in an older "bucket".
+ {
+ PhoneTimeSuggestion phone2TimeSuggestion =
+ mScript.generatePhoneTimeSuggestion(phone2Id, phone2TimeMillis);
+ mScript.simulateTimePassing(clockIncrement);
+
+ long expectedSystemClockMillis = phone2TimeMillis + clockIncrement;
+
+ mScript.simulatePhoneTimeSuggestion(phone2TimeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(
+ expectedSystemClockMillis, true /* expectNetworkBroadcast */)
+ .assertLatestPhoneSuggestion(phone2Id, phone2TimeSuggestion);
+ }
+ }
+
+ @Test
+ public void testSuggestPhoneTime_autoTimeDisabled() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(false);
+
+ int phoneId = ARBITRARY_PHONE_ID;
+ PhoneTimeSuggestion timeSuggestion =
+ mScript.generatePhoneTimeSuggestion(phoneId, ARBITRARY_TEST_TIME_MILLIS);
+ mScript.simulateTimePassing(1000)
+ .simulatePhoneTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking()
+ .assertLatestPhoneSuggestion(phoneId, timeSuggestion);
+ }
+
+ @Test
+ public void testSuggestPhoneTime_invalidNitzReferenceTimesIgnored() {
+ final int systemClockUpdateThreshold = 2000;
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeThresholds(systemClockUpdateThreshold)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+ int phoneId = ARBITRARY_PHONE_ID;
+
+ PhoneTimeSuggestion timeSuggestion1 =
+ mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
+ TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
+
+ // Initialize the strategy / device with a time set from a phone suggestion.
+ mScript.simulateTimePassing(100);
+ long expectedSystemClockMillis1 =
+ TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
+ mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
+ .verifySystemClockWasSetAndResetCallTracking(
+ expectedSystemClockMillis1, true /* expectNetworkBroadcast */)
+ .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+
+ // The UTC time increment should be larger than the system clock update threshold so we
+ // know it shouldn't be ignored for other reasons.
+ long validUtcTimeMillis = utcTime1.getValue() + (2 * systemClockUpdateThreshold);
+
+ // Now supply a new signal that has an obviously bogus reference time : older than the last
+ // one.
+ long referenceTimeBeforeLastSignalMillis = utcTime1.getReferenceTimeMillis() - 1;
+ TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
+ referenceTimeBeforeLastSignalMillis, validUtcTimeMillis);
+ PhoneTimeSuggestion timeSuggestion2 =
+ createPhoneTimeSuggestion(phoneId, utcTime2);
+ mScript.simulatePhoneTimeSuggestion(timeSuggestion2)
+ .verifySystemClockWasNotSetAndResetCallTracking()
+ .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+
+ // Now supply a new signal that has an obviously bogus reference time : substantially in the
+ // future.
+ long referenceTimeInFutureMillis =
+ utcTime1.getReferenceTimeMillis() + Integer.MAX_VALUE + 1;
+ TimestampedValue<Long> utcTime3 = new TimestampedValue<>(
+ referenceTimeInFutureMillis, validUtcTimeMillis);
+ PhoneTimeSuggestion timeSuggestion3 =
+ createPhoneTimeSuggestion(phoneId, utcTime3);
+ mScript.simulatePhoneTimeSuggestion(timeSuggestion3)
+ .verifySystemClockWasNotSetAndResetCallTracking()
+ .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+
+ // Just to prove validUtcTimeMillis is valid.
+ long validReferenceTimeMillis = utcTime1.getReferenceTimeMillis() + 100;
+ TimestampedValue<Long> utcTime4 = new TimestampedValue<>(
+ validReferenceTimeMillis, validUtcTimeMillis);
+ long expectedSystemClockMillis4 =
+ TimeDetectorStrategy.getTimeAt(utcTime4, mScript.peekElapsedRealtimeMillis());
+ PhoneTimeSuggestion timeSuggestion4 =
+ createPhoneTimeSuggestion(phoneId, utcTime4);
+ mScript.simulatePhoneTimeSuggestion(timeSuggestion4)
+ .verifySystemClockWasSetAndResetCallTracking(
+ expectedSystemClockMillis4, true /* expectNetworkBroadcast */)
+ .assertLatestPhoneSuggestion(phoneId, timeSuggestion4);
+ }
+
+ @Test
+ public void testSuggestPhoneTime_timeDetectionToggled() {
+ final int clockIncrementMillis = 100;
+ final int systemClockUpdateThreshold = 2000;
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeThresholds(systemClockUpdateThreshold)
+ .pokeAutoTimeDetectionEnabled(false);
+
+ int phoneId = ARBITRARY_PHONE_ID;
+ long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+ PhoneTimeSuggestion timeSuggestion1 =
+ mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
+ TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
+
+ // Simulate time passing.
+ mScript.simulateTimePassing(clockIncrementMillis);
+
+ // Simulate the time signal being received. It should not be used because auto time
+ // detection is off but it should be recorded.
+ mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
+ .verifySystemClockWasNotSetAndResetCallTracking()
+ .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+
+ // Simulate more time passing.
+ mScript.simulateTimePassing(clockIncrementMillis);
+
+ long expectedSystemClockMillis1 =
+ TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
+
+ // Turn on auto time detection.
+ mScript.simulateAutoTimeDetectionToggle()
+ .verifySystemClockWasSetAndResetCallTracking(
+ expectedSystemClockMillis1, true /* expectNetworkBroadcast */)
+ .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+
+ // Turn off auto time detection.
+ mScript.simulateAutoTimeDetectionToggle()
+ .verifySystemClockWasNotSetAndResetCallTracking()
+ .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+
+ // Receive another valid time signal.
+ // It should be on the threshold and accounting for the clock increments.
+ PhoneTimeSuggestion timeSuggestion2 = mScript.generatePhoneTimeSuggestion(
+ phoneId, mScript.peekSystemClockMillis() + systemClockUpdateThreshold);
+
+ // Simulate more time passing.
+ mScript.simulateTimePassing(clockIncrementMillis);
+
+ long expectedSystemClockMillis2 = TimeDetectorStrategy.getTimeAt(
+ timeSuggestion2.getUtcTime(), mScript.peekElapsedRealtimeMillis());
+
+ // The new time, though valid, should not be set in the system clock because auto time is
+ // disabled.
+ mScript.simulatePhoneTimeSuggestion(timeSuggestion2)
+ .verifySystemClockWasNotSetAndResetCallTracking()
+ .assertLatestPhoneSuggestion(phoneId, timeSuggestion2);
+
+ // Turn on auto time detection.
+ mScript.simulateAutoTimeDetectionToggle()
+ .verifySystemClockWasSetAndResetCallTracking(
+ expectedSystemClockMillis2, true /* expectNetworkBroadcast */)
+ .assertLatestPhoneSuggestion(phoneId, timeSuggestion2);
+ }
+
+ @Test
+ public void testSuggestPhoneTime_maxSuggestionAge() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ int phoneId = ARBITRARY_PHONE_ID;
+ long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+ PhoneTimeSuggestion phoneSuggestion =
+ mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
+ int clockIncrementMillis = 1000;
+
+ mScript.simulateTimePassing(clockIncrementMillis)
+ .simulatePhoneTimeSuggestion(phoneSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(
+ testTimeMillis + clockIncrementMillis, true /* expectedNetworkBroadcast */)
+ .assertLatestPhoneSuggestion(phoneId, phoneSuggestion);
+
+ // Look inside and check what the strategy considers the current best phone suggestion.
+ assertEquals(phoneSuggestion, mScript.peekBestPhoneSuggestion());
+
+ // Simulate time passing, long enough that phoneSuggestion is now too old.
+ mScript.simulateTimePassing(TimeDetectorStrategyImpl.PHONE_MAX_AGE_MILLIS);
+
+ // Look inside and check what the strategy considers the current best phone suggestion. It
+ // should still be the, it's just no longer used.
+ assertNull(mScript.peekBestPhoneSuggestion());
+ mScript.assertLatestPhoneSuggestion(phoneId, phoneSuggestion);
+ }
+
+ @Test
+ public void testSuggestManualTime_autoTimeDisabled() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(false);
+
+ long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+ ManualTimeSuggestion timeSuggestion = mScript.generateManualTimeSuggestion(testTimeMillis);
+ final int clockIncrement = 1000;
+ long expectedSystemClockMillis = testTimeMillis + clockIncrement;
+
+ mScript.simulateTimePassing(clockIncrement)
+ .simulateManualTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(
+ expectedSystemClockMillis, false /* expectNetworkBroadcast */);
+ }
+
+ @Test
+ public void testSuggestManualTime_retainsAutoSignal() {
+ // Configure the start state.
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ int phoneId = ARBITRARY_PHONE_ID;
+
+ // Simulate a phone suggestion.
+ long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+ PhoneTimeSuggestion phoneTimeSuggestion =
+ mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
+ long expectedAutoClockMillis = phoneTimeSuggestion.getUtcTime().getValue();
+ final int clockIncrement = 1000;
+
+ // Simulate the passage of time.
+ mScript.simulateTimePassing(clockIncrement);
+ expectedAutoClockMillis += clockIncrement;
+
+ mScript.simulatePhoneTimeSuggestion(phoneTimeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(
+ expectedAutoClockMillis, true /* expectNetworkBroadcast */)
+ .assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
+
+ // Simulate the passage of time.
+ mScript.simulateTimePassing(clockIncrement);
+ expectedAutoClockMillis += clockIncrement;
+
+ // Switch to manual.
+ mScript.simulateAutoTimeDetectionToggle()
+ .verifySystemClockWasNotSetAndResetCallTracking()
+ .assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
+
+ // Simulate the passage of time.
+ mScript.simulateTimePassing(clockIncrement);
+ expectedAutoClockMillis += clockIncrement;
+
+ // Simulate a manual suggestion 1 day different from the auto suggestion.
+ long manualTimeMillis = testTimeMillis + ONE_DAY_MILLIS;
+ long expectedManualClockMillis = manualTimeMillis;
+ ManualTimeSuggestion manualTimeSuggestion =
+ mScript.generateManualTimeSuggestion(manualTimeMillis);
+ mScript.simulateManualTimeSuggestion(manualTimeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(
+ expectedManualClockMillis, false /* expectNetworkBroadcast */)
+ .assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
+
+ // Simulate the passage of time.
+ mScript.simulateTimePassing(clockIncrement);
+ expectedAutoClockMillis += clockIncrement;
+
+ // Switch back to auto.
+ mScript.simulateAutoTimeDetectionToggle();
+
+ mScript.verifySystemClockWasSetAndResetCallTracking(
+ expectedAutoClockMillis, true /* expectNetworkBroadcast */)
+ .assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
+
+ // Switch back to manual - nothing should happen to the clock.
+ mScript.simulateAutoTimeDetectionToggle()
+ .verifySystemClockWasNotSetAndResetCallTracking()
+ .assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
+ }
+
+ /**
+ * Manual suggestions should be ignored if auto time is enabled.
+ */
+ @Test
+ public void testSuggestManualTime_autoTimeEnabled() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ ManualTimeSuggestion timeSuggestion =
+ mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS);
+ final int clockIncrement = 1000;
+
+ mScript.simulateTimePassing(clockIncrement)
+ .simulateManualTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ /**
+ * A fake implementation of TimeDetectorStrategy.Callback. Besides tracking changes and behaving
+ * like the real thing should, it also asserts preconditions.
+ */
+ private static class FakeCallback implements TimeDetectorStrategy.Callback {
+ private boolean mAutoTimeDetectionEnabled;
+ private boolean mWakeLockAcquired;
+ private long mElapsedRealtimeMillis;
+ private long mSystemClockMillis;
+ private int mSystemClockUpdateThresholdMillis = 2000;
+
+ // Tracking operations.
+ private boolean mSystemClockWasSet;
+ private Intent mBroadcastSent;
+
+ @Override
+ public int systemClockUpdateThresholdMillis() {
+ return mSystemClockUpdateThresholdMillis;
+ }
+
+ @Override
+ public boolean isAutoTimeDetectionEnabled() {
+ return mAutoTimeDetectionEnabled;
+ }
+
+ @Override
+ public void acquireWakeLock() {
+ if (mWakeLockAcquired) {
+ fail("Wake lock already acquired");
+ }
+ mWakeLockAcquired = true;
+ }
+
+ @Override
+ public long elapsedRealtimeMillis() {
+ return mElapsedRealtimeMillis;
+ }
+
+ @Override
+ public long systemClockMillis() {
+ assertWakeLockAcquired();
+ return mSystemClockMillis;
+ }
+
+ @Override
+ public void setSystemClock(long newTimeMillis) {
+ assertWakeLockAcquired();
+ mSystemClockWasSet = true;
+ mSystemClockMillis = newTimeMillis;
+ }
+
+ @Override
+ public void releaseWakeLock() {
+ assertWakeLockAcquired();
+ mWakeLockAcquired = false;
+ }
+
+ @Override
+ public void sendStickyBroadcast(Intent intent) {
+ assertNotNull(intent);
+ mBroadcastSent = intent;
+ }
+
+ // Methods below are for managing the fake's behavior.
+
+ void pokeSystemClockUpdateThreshold(int thresholdMillis) {
+ mSystemClockUpdateThresholdMillis = thresholdMillis;
+ }
+
+ void pokeElapsedRealtimeMillis(long elapsedRealtimeMillis) {
+ mElapsedRealtimeMillis = elapsedRealtimeMillis;
+ }
+
+ void pokeSystemClockMillis(long systemClockMillis) {
+ mSystemClockMillis = systemClockMillis;
+ }
+
+ void pokeAutoTimeDetectionEnabled(boolean enabled) {
+ mAutoTimeDetectionEnabled = enabled;
+ }
+
+ long peekElapsedRealtimeMillis() {
+ return mElapsedRealtimeMillis;
+ }
+
+ long peekSystemClockMillis() {
+ return mSystemClockMillis;
+ }
+
+ void simulateTimePassing(long incrementMillis) {
+ mElapsedRealtimeMillis += incrementMillis;
+ mSystemClockMillis += incrementMillis;
+ }
+
+ void simulateAutoTimeZoneDetectionToggle() {
+ mAutoTimeDetectionEnabled = !mAutoTimeDetectionEnabled;
+ }
+
+ void verifySystemClockNotSet() {
+ assertFalse(mSystemClockWasSet);
+ }
+
+ void verifySystemClockWasSet(long expectedSystemClockMillis) {
+ assertTrue(mSystemClockWasSet);
+ assertEquals(expectedSystemClockMillis, mSystemClockMillis);
+ }
+
+ void verifyIntentWasBroadcast() {
+ assertTrue(mBroadcastSent != null);
+ }
+
+ void verifyIntentWasNotBroadcast() {
+ assertNull(mBroadcastSent);
+ }
+
+ void resetCallTracking() {
+ mSystemClockWasSet = false;
+ mBroadcastSent = null;
+ }
+
+ private void assertWakeLockAcquired() {
+ assertTrue("The operation must be performed only after acquiring the wakelock",
+ mWakeLockAcquired);
+ }
+ }
+
+ /**
+ * A fluent helper class for tests.
+ */
+ private class Script {
+
+ private final FakeCallback mFakeCallback;
+ private final TimeDetectorStrategyImpl mTimeDetectorStrategy;
+
+ Script() {
+ mFakeCallback = new FakeCallback();
+ mTimeDetectorStrategy = new TimeDetectorStrategyImpl();
+ mTimeDetectorStrategy.initialize(mFakeCallback);
+
+ }
+
+ Script pokeAutoTimeDetectionEnabled(boolean enabled) {
+ mFakeCallback.pokeAutoTimeDetectionEnabled(enabled);
+ return this;
+ }
+
+ Script pokeFakeClocks(TimestampedValue<Long> timeInfo) {
+ mFakeCallback.pokeElapsedRealtimeMillis(timeInfo.getReferenceTimeMillis());
+ mFakeCallback.pokeSystemClockMillis(timeInfo.getValue());
+ return this;
+ }
+
+ Script pokeThresholds(int systemClockUpdateThreshold) {
+ mFakeCallback.pokeSystemClockUpdateThreshold(systemClockUpdateThreshold);
+ return this;
+ }
+
+ long peekElapsedRealtimeMillis() {
+ return mFakeCallback.peekElapsedRealtimeMillis();
+ }
+
+ long peekSystemClockMillis() {
+ return mFakeCallback.peekSystemClockMillis();
+ }
+
+ Script simulatePhoneTimeSuggestion(PhoneTimeSuggestion timeSuggestion) {
+ mTimeDetectorStrategy.suggestPhoneTime(timeSuggestion);
+ return this;
+ }
+
+ Script simulateManualTimeSuggestion(ManualTimeSuggestion timeSuggestion) {
+ mTimeDetectorStrategy.suggestManualTime(timeSuggestion);
+ return this;
+ }
+
+ Script simulateAutoTimeDetectionToggle() {
+ mFakeCallback.simulateAutoTimeZoneDetectionToggle();
+ mTimeDetectorStrategy.handleAutoTimeDetectionChanged();
+ return this;
+ }
+
+ Script simulateTimePassing(long clockIncrementMillis) {
+ mFakeCallback.simulateTimePassing(clockIncrementMillis);
+ return this;
+ }
+
+ Script verifySystemClockWasNotSetAndResetCallTracking() {
+ mFakeCallback.verifySystemClockNotSet();
+ mFakeCallback.verifyIntentWasNotBroadcast();
+ mFakeCallback.resetCallTracking();
+ return this;
+ }
+
+ Script verifySystemClockWasSetAndResetCallTracking(
+ long expectedSystemClockMillis, boolean expectNetworkBroadcast) {
+ mFakeCallback.verifySystemClockWasSet(expectedSystemClockMillis);
+ if (expectNetworkBroadcast) {
+ mFakeCallback.verifyIntentWasBroadcast();
+ }
+ mFakeCallback.resetCallTracking();
+ return this;
+ }
+
+ /**
+ * White box test info: Asserts the latest suggestion for the phone ID is as expected.
+ */
+ Script assertLatestPhoneSuggestion(int phoneId, PhoneTimeSuggestion expected) {
+ assertEquals(expected, mTimeDetectorStrategy.getLatestPhoneSuggestion(phoneId));
+ return this;
+ }
+
+ /**
+ * White box test info: Returns the phone suggestion that would be used, if any, given the
+ * current elapsed real time clock.
+ */
+ PhoneTimeSuggestion peekBestPhoneSuggestion() {
+ return mTimeDetectorStrategy.findBestPhoneSuggestionForTests();
+ }
+
+ /**
+ * Generates a ManualTimeSuggestion using the current elapsed realtime clock for the
+ * reference time.
+ */
+ ManualTimeSuggestion generateManualTimeSuggestion(long timeMillis) {
+ TimestampedValue<Long> utcTime =
+ new TimestampedValue<>(mFakeCallback.peekElapsedRealtimeMillis(), timeMillis);
+ return new ManualTimeSuggestion(utcTime);
+ }
+
+ /**
+ * Generates a PhoneTimeSuggestion using the current elapsed realtime clock for the
+ * reference time.
+ */
+ PhoneTimeSuggestion generatePhoneTimeSuggestion(int phoneId, Long timeMillis) {
+ TimestampedValue<Long> time = null;
+ if (timeMillis != null) {
+ time = new TimestampedValue<>(peekElapsedRealtimeMillis(), timeMillis);
+ }
+ return createPhoneTimeSuggestion(phoneId, time);
+ }
+ }
+
+ private static PhoneTimeSuggestion createPhoneTimeSuggestion(int phoneId,
+ TimestampedValue<Long> utcTime) {
+ return new PhoneTimeSuggestion.Builder(phoneId)
+ .setUtcTime(utcTime)
+ .build();
+ }
+
+ private static long createUtcTime(int year, int monthInYear, int day, int hourOfDay, int minute,
+ int second) {
+ Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("Etc/UTC"));
+ cal.clear();
+ cal.set(year, monthInYear - 1, day, hourOfDay, minute, second);
+ return cal.getTimeInMillis();
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyTest.java
index 270436d..2429cfc 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyTest.java
@@ -50,7 +50,6 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
-import java.util.Objects;
/**
* White-box unit tests for {@link TimeZoneDetectorStrategy}.
@@ -445,8 +444,7 @@
static class FakeTimeZoneDetectorStrategyCallback implements TimeZoneDetectorStrategy.Callback {
private boolean mAutoTimeZoneDetectionEnabled;
- private TestState<TimeZoneChange> mTimeZoneChanges = new TestState<>();
- private String mTimeZoneId;
+ private TestState<String> mTimeZoneId = new TestState<>();
@Override
public boolean isAutoTimeZoneDetectionEnabled() {
@@ -455,18 +453,17 @@
@Override
public boolean isDeviceTimeZoneInitialized() {
- return mTimeZoneId != null;
+ return mTimeZoneId.getLatest() != null;
}
@Override
public String getDeviceTimeZone() {
- return mTimeZoneId;
+ return mTimeZoneId.getLatest();
}
@Override
- public void setDeviceTimeZone(String zoneId, boolean withNetworkBroadcast) {
- mTimeZoneId = zoneId;
- mTimeZoneChanges.set(new TimeZoneChange(zoneId, withNetworkBroadcast));
+ public void setDeviceTimeZone(String zoneId) {
+ mTimeZoneId.set(zoneId);
}
void initializeAutoTimeZoneDetection(boolean enabled) {
@@ -474,7 +471,7 @@
}
void initializeTimeZone(String zoneId) {
- mTimeZoneId = zoneId;
+ mTimeZoneId.init(zoneId);
}
void setAutoTimeZoneDetectionEnabled(boolean enabled) {
@@ -482,46 +479,17 @@
}
void assertTimeZoneNotSet() {
- mTimeZoneChanges.assertHasNotBeenSet();
+ mTimeZoneId.assertHasNotBeenSet();
}
- void assertTimeZoneSet(String timeZoneId, boolean withNetworkBroadcast) {
- mTimeZoneChanges.assertHasBeenSet();
- mTimeZoneChanges.assertChangeCount(1);
- TimeZoneChange expectedChange = new TimeZoneChange(timeZoneId, withNetworkBroadcast);
- mTimeZoneChanges.assertLatestEquals(expectedChange);
+ void assertTimeZoneSet(String timeZoneId) {
+ mTimeZoneId.assertHasBeenSet();
+ mTimeZoneId.assertChangeCount(1);
+ mTimeZoneId.assertLatestEquals(timeZoneId);
}
void commitAllChanges() {
- mTimeZoneChanges.commitLatest();
- }
- }
-
- private static class TimeZoneChange {
- private final String mTimeZoneId;
- private final boolean mWithNetworkBroadcast;
-
- private TimeZoneChange(String timeZoneId, boolean withNetworkBroadcast) {
- mTimeZoneId = timeZoneId;
- mWithNetworkBroadcast = withNetworkBroadcast;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- TimeZoneChange that = (TimeZoneChange) o;
- return mWithNetworkBroadcast == that.mWithNetworkBroadcast
- && mTimeZoneId.equals(that.mTimeZoneId);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mTimeZoneId, mWithNetworkBroadcast);
+ mTimeZoneId.commitLatest();
}
}
@@ -614,21 +582,13 @@
}
Script verifyTimeZoneSetAndReset(PhoneTimeZoneSuggestion suggestion) {
- // Phone suggestions should cause a TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE
- // broadcast.
- boolean withNetworkBroadcast = true;
- mFakeTimeZoneDetectorStrategyCallback.assertTimeZoneSet(
- suggestion.getZoneId(), withNetworkBroadcast);
+ mFakeTimeZoneDetectorStrategyCallback.assertTimeZoneSet(suggestion.getZoneId());
mFakeTimeZoneDetectorStrategyCallback.commitAllChanges();
return this;
}
Script verifyTimeZoneSetAndReset(ManualTimeZoneSuggestion suggestion) {
- // Manual suggestions should not cause a TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE
- // broadcast.
- boolean withNetworkBroadcast = false;
- mFakeTimeZoneDetectorStrategyCallback.assertTimeZoneSet(
- suggestion.getZoneId(), withNetworkBroadcast);
+ mFakeTimeZoneDetectorStrategyCallback.assertTimeZoneSet(suggestion.getZoneId());
mFakeTimeZoneDetectorStrategyCallback.commitAllChanges();
return this;
}
diff --git a/services/usage/Android.bp b/services/usage/Android.bp
index 1064b6e..156bf33 100644
--- a/services/usage/Android.bp
+++ b/services/usage/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.usage-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.usage",
- srcs: ["java/**/*.java"],
+ srcs: [":services.usage-sources"],
libs: ["services.core"],
}
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 75e8fb5..cb120fc 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -1356,7 +1356,8 @@
private void fetchCarrierPrivilegedAppsLocked() {
TelephonyManager telephonyManager =
mContext.getSystemService(TelephonyManager.class);
- mCarrierPrivilegedApps = telephonyManager.getPackagesWithCarrierPrivilegesForAllPhones();
+ mCarrierPrivilegedApps =
+ telephonyManager.getCarrierPrivilegedPackagesForAllActiveSubscriptions();
mHaveCarrierPrivilegedApps = true;
if (DEBUG) {
Slog.d(TAG, "apps with carrier privilege " + mCarrierPrivilegedApps);
diff --git a/services/usb/Android.bp b/services/usb/Android.bp
index 20855b7..d2c973a 100644
--- a/services/usb/Android.bp
+++ b/services/usb/Android.bp
@@ -1,6 +1,13 @@
+filegroup {
+ name: "services.usb-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.usb",
- srcs: ["java/**/*.java"],
+ srcs: [":services.usb-sources"],
libs: [
"services.core",
diff --git a/services/voiceinteraction/Android.bp b/services/voiceinteraction/Android.bp
index 390406f..85b96f34 100644
--- a/services/voiceinteraction/Android.bp
+++ b/services/voiceinteraction/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+ name: "services.voiceinteraction-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
java_library_static {
name: "services.voiceinteraction",
- srcs: ["java/**/*.java"],
+ srcs: [":services.voiceinteraction-sources"],
libs: ["services.core"],
}
diff --git a/startop/iorap/Android.bp b/startop/iorap/Android.bp
index 59a80fb..993d1e1 100644
--- a/startop/iorap/Android.bp
+++ b/startop/iorap/Android.bp
@@ -12,19 +12,24 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+filegroup {
+ name: "services.startop.iorap-javasources",
+ srcs: ["src/**/*.java"],
+ path: "src",
+ visibility: ["//visibility:private"],
+}
+
+filegroup {
+ name: "services.startop.iorap-sources",
+ srcs: [
+ ":services.startop.iorap-javasources",
+ ":iorap-aidl",
+ ],
+ visibility: ["//frameworks/base/services:__subpackages__"],
+}
+
java_library_static {
name: "services.startop.iorap",
-
- aidl: {
- include_dirs: [
- "system/iorap/binder",
- ],
- },
-
+ srcs: [":services.startop.iorap-sources"],
libs: ["services.core"],
-
- srcs: [
- ":iorap-aidl",
- "**/*.java",
- ],
}
diff --git a/telephony/java/com/android/internal/telephony/EncodeException.java b/telephony/common/com/android/internal/telephony/EncodeException.java
similarity index 100%
rename from telephony/java/com/android/internal/telephony/EncodeException.java
rename to telephony/common/com/android/internal/telephony/EncodeException.java
diff --git a/telephony/common/com/android/internal/telephony/PackageChangeReceiver.java b/telephony/common/com/android/internal/telephony/PackageChangeReceiver.java
new file mode 100644
index 0000000..922af12
--- /dev/null
+++ b/telephony/common/com/android/internal/telephony/PackageChangeReceiver.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+
+import com.android.internal.os.BackgroundThread;
+
+/**
+ * Helper class for monitoring the state of packages: adding, removing,
+ * updating, and disappearing and reappearing on the SD card.
+ */
+public abstract class PackageChangeReceiver extends BroadcastReceiver {
+ static final IntentFilter sPackageIntentFilter = new IntentFilter();
+ static {
+ sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ sPackageIntentFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
+ sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
+ sPackageIntentFilter.addDataScheme("package");
+ }
+ Context mRegisteredContext;
+
+ /**
+ * To register the intents that needed for monitoring the state of packages
+ */
+ public void register(@NonNull Context context, @Nullable Looper thread,
+ @Nullable UserHandle user) {
+ if (mRegisteredContext != null) {
+ throw new IllegalStateException("Already registered");
+ }
+ Handler handler = (thread == null) ? BackgroundThread.getHandler() : new Handler(thread);
+ mRegisteredContext = context;
+ if (handler != null) {
+ if (user != null) {
+ context.registerReceiverAsUser(this, user, sPackageIntentFilter, null, handler);
+ } else {
+ context.registerReceiver(this, sPackageIntentFilter,
+ null, handler);
+ }
+ } else {
+ throw new NullPointerException();
+ }
+ }
+
+ /**
+ * To unregister the intents for monitoring the state of packages
+ */
+ public void unregister() {
+ if (mRegisteredContext == null) {
+ throw new IllegalStateException("Not registered");
+ }
+ mRegisteredContext.unregisterReceiver(this);
+ mRegisteredContext = null;
+ }
+
+ /**
+ * This method is invoked when receive the Intent.ACTION_PACKAGE_ADDED
+ */
+ public void onPackageAdded(@Nullable String packageName) {
+ }
+
+ /**
+ * This method is invoked when receive the Intent.ACTION_PACKAGE_REMOVED
+ */
+ public void onPackageRemoved(@Nullable String packageName) {
+ }
+
+ /**
+ * This method is invoked when Intent.EXTRA_REPLACING as extra field is true
+ */
+ public void onPackageUpdateFinished(@Nullable String packageName) {
+ }
+
+ /**
+ * This method is invoked when receive the Intent.ACTION_PACKAGE_CHANGED or
+ * Intent.EXTRA_REPLACING as extra field is true
+ */
+ public void onPackageModified(@Nullable String packageName) {
+ }
+
+ /**
+ * This method is invoked when receive the Intent.ACTION_QUERY_PACKAGE_RESTART and
+ * Intent.ACTION_PACKAGE_RESTARTED
+ */
+ public void onHandleForceStop(@Nullable String[] packages, boolean doit) {
+ }
+
+ /**
+ * This method is invoked when receive the Intent.ACTION_PACKAGE_REMOVED
+ */
+ public void onPackageDisappeared() {
+ }
+
+ /**
+ * This method is invoked when receive the Intent.ACTION_PACKAGE_ADDED
+ */
+ public void onPackageAppeared() {
+ }
+
+ @Override
+ public void onReceive(@Nullable Context context, @Nullable Intent intent) {
+ String action = intent.getAction();
+
+ if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+ String pkg = getPackageName(intent);
+ if (pkg != null) {
+ if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+ onPackageUpdateFinished(pkg);
+ onPackageModified(pkg);
+ } else {
+ onPackageAdded(pkg);
+ }
+ onPackageAppeared();
+ }
+ } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+ String pkg = getPackageName(intent);
+ if (pkg != null) {
+ if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+ onPackageRemoved(pkg);
+ }
+ onPackageDisappeared();
+ }
+ } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
+ String pkg = getPackageName(intent);
+ if (pkg != null) {
+ onPackageModified(pkg);
+ }
+ } else if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
+ String[] disappearingPackages = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
+ onHandleForceStop(disappearingPackages, false);
+ } else if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) {
+ String[] disappearingPackages = new String[] {getPackageName(intent)};
+ onHandleForceStop(disappearingPackages, true);
+ }
+ }
+
+ String getPackageName(Intent intent) {
+ Uri uri = intent.getData();
+ String pkg = uri != null ? uri.getSchemeSpecificPart() : null;
+ return pkg;
+ }
+}
diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java
index 9da45da..df668ea 100644
--- a/telephony/common/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/common/com/android/internal/telephony/SmsApplication.java
@@ -39,11 +39,11 @@
import android.os.UserHandle;
import android.provider.Telephony;
import android.provider.Telephony.Sms.Intents;
+import android.telephony.PackageChangeReceiver;
import android.telephony.Rlog;
import android.telephony.TelephonyManager;
import android.util.Log;
-import com.android.internal.content.PackageMonitor;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -305,7 +305,7 @@
Uri.fromParts(SCHEME_SMSTO, "", null));
List<ResolveInfo> respondServices = packageManager.queryIntentServicesAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- UserHandle.getUserHandleForUid(userId));
+ UserHandle.of(userId));
for (ResolveInfo resolveInfo : respondServices) {
final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
if (serviceInfo == null) {
@@ -782,7 +782,7 @@
* Tracks package changes and ensures that the default SMS app is always configured to be the
* preferred activity for SENDTO sms/mms intents.
*/
- private static final class SmsPackageMonitor extends PackageMonitor {
+ private static final class SmsPackageMonitor extends PackageChangeReceiver {
final Context mContext;
public SmsPackageMonitor(Context context) {
@@ -791,12 +791,12 @@
}
@Override
- public void onPackageDisappeared(String packageName, int reason) {
+ public void onPackageDisappeared() {
onPackageChanged();
}
@Override
- public void onPackageAppeared(String packageName, int reason) {
+ public void onPackageAppeared() {
onPackageChanged();
}
@@ -829,7 +829,7 @@
public static void initSmsPackageMonitor(Context context) {
sSmsPackageMonitor = new SmsPackageMonitor(context);
- sSmsPackageMonitor.register(context, context.getMainLooper(), UserHandle.ALL, false);
+ sSmsPackageMonitor.register(context, context.getMainLooper(), UserHandle.ALL);
}
@UnsupportedAppUsage
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index f89bbc7..3940a3b 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -116,7 +116,8 @@
ApnSetting.TYPE_CBS,
ApnSetting.TYPE_IA,
ApnSetting.TYPE_EMERGENCY,
- ApnSetting.TYPE_MCX
+ ApnSetting.TYPE_MCX,
+ ApnSetting.TYPE_XCAP,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ApnType {
@@ -463,9 +464,7 @@
DataFailCause.UNKNOWN,
DataFailCause.RADIO_NOT_AVAILABLE,
DataFailCause.UNACCEPTABLE_NETWORK_PARAMETER,
- DataFailCause.CONNECTION_TO_DATACONNECTIONAC_BROKEN,
DataFailCause.LOST_CONNECTION,
- DataFailCause.RESET_BY_FRAMEWORK
})
@Retention(RetentionPolicy.SOURCE)
public @interface DataFailureCause {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 92c6e93..c04105b 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -100,6 +100,16 @@
KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
/**
+ * Boolean indicating the Supplementary Services(SS) is disable when airplane mode on in the
+ * Call Settings menu.
+ * {@code true}: SS is disable when airplane mode on.
+ * {@code false}: SS is enable when airplane mode on.
+ * The default value for this key is {@code false}
+ */
+ public static final String KEY_DISABLE_SUPPLEMENTARY_SERVICES_IN_AIRPLANE_MODE_BOOL =
+ "disable_supplementary_services_in_airplane_mode_bool";
+
+ /**
* Boolean indicating if the "Call forwarding" item is visible in the Call Settings menu.
* true means visible. false means gone.
* @hide
@@ -2323,7 +2333,7 @@
* Reference: 3GPP TS 38.215
*
* 4 threshold integers must be within the boundaries [-20 dB, -3 dB], and the levels are:
- * "NONE: [-23, threshold1]"
+ * "NONE: [-20, threshold1]"
* "POOR: (threshold1, threshold2]"
* "MODERATE: (threshold2, threshold3]"
* "GOOD: (threshold3, threshold4]"
@@ -2357,15 +2367,26 @@
/**
* Bit-field integer to determine whether to use SS reference signal received power (SSRSRP),
* SS reference signal received quality (SSRSRQ), or/and SS signal-to-noise and interference
- * ratio (SSSINR) for the number of 5G NR signal bars. If multiple measures are set bit, the
- * parameter whose value is smallest is used to indicate the signal bar.
+ * ratio (SSSINR) for the number of 5G NR signal bars and signal criteria reporting enabling.
+ *
+ * <p> If a measure is not set, signal criteria reporting from modem will not be triggered and
+ * not be used for calculating signal level. If multiple measures are set bit, the parameter
+ * whose value is smallest is used to indicate the signal level.
*
* SSRSRP = 1 << 0,
* SSRSRQ = 1 << 1,
* SSSINR = 1 << 2,
*
+ * The value of this key must be bitwise OR of {@link CellSignalStrengthNr#USE_SSRSRP},
+ * {@link CellSignalStrengthNr#USE_SSRSRQ}, {@link CellSignalStrengthNr#USE_SSSINR}.
+ *
+ * For example, if both SSRSRP and SSSINR are used, the value of key is 5 (1 << 0 | 1 << 2).
+ * If the key is invalid or not configured, a default value (SSRSRP = 1 << 0) will apply.
+ *
* Reference: 3GPP TS 38.215,
* 3GPP TS 38.133 10.1.16.1
+ *
+ * @hide
*/
public static final String KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT =
"parameters_use_for_5g_nr_signal_bar_int";
@@ -2978,7 +2999,6 @@
/**
* Location information during (and after) an emergency call is only provided over control
* plane signaling from the network.
- * @hide
*/
public static final int SUPL_EMERGENCY_MODE_TYPE_CP_ONLY = 0;
@@ -2986,7 +3006,6 @@
* Location information during (and after) an emergency call is provided over the data
* plane and serviced by the framework GNSS service, but if it fails, the carrier also
* supports control plane backup signaling.
- * @hide
*/
public static final int SUPL_EMERGENCY_MODE_TYPE_CP_FALLBACK = 1;
@@ -2994,7 +3013,6 @@
* Location information during (and after) an emergency call is provided over the data plane
* and serviced by the framework GNSS service only. There is no backup signalling over the
* control plane if it fails.
- * @hide
*/
public static final int SUPL_EMERGENCY_MODE_TYPE_DP_ONLY = 2;
@@ -3102,11 +3120,21 @@
* {@link #SUPL_EMERGENCY_MODE_TYPE_CP_ONLY}.
* <p>
* The default value for this configuration is {@link #SUPL_EMERGENCY_MODE_TYPE_CP_ONLY}.
- * @hide
*/
public static final String KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT = KEY_PREFIX
+ "es_supl_control_plane_support_int";
+ /**
+ * A list of roaming PLMNs where SUPL ES mode does not support a control-plane mechanism to
+ * get a user's location in the event that data plane SUPL fails or is otherwise
+ * unavailable.
+ * <p>
+ * A string array of PLMNs that do not support a control-plane mechanism for getting a
+ * user's location for SUPL ES.
+ */
+ public static final String KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY =
+ KEY_PREFIX + "es_supl_data_plane_only_roaming_plmn_string_array";
+
private static PersistableBundle getDefaults() {
PersistableBundle defaults = new PersistableBundle();
defaults.putBoolean(KEY_PERSIST_LPP_MODE_BOOL, true);
@@ -3123,6 +3151,7 @@
defaults.putString(KEY_NFW_PROXY_APPS_STRING, "");
defaults.putInt(KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
SUPL_EMERGENCY_MODE_TYPE_CP_ONLY);
+ defaults.putStringArray(KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY, null);
return defaults;
}
}
@@ -3393,6 +3422,7 @@
sDefaults.putBoolean(KEY_CALL_FORWARDING_WHEN_UNREACHABLE_SUPPORTED_BOOL, true);
sDefaults.putBoolean(KEY_ADDITIONAL_SETTINGS_CALLER_ID_VISIBILITY_BOOL, true);
sDefaults.putBoolean(KEY_ADDITIONAL_SETTINGS_CALL_WAITING_VISIBILITY_BOOL, true);
+ sDefaults.putBoolean(KEY_DISABLE_SUPPLEMENTARY_SERVICES_IN_AIRPLANE_MODE_BOOL, false);
sDefaults.putBoolean(KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL, false);
sDefaults.putBoolean(KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL, false);
sDefaults.putBoolean(KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
@@ -3692,6 +3722,32 @@
-95, /* SIGNAL_STRENGTH_GOOD */
-85 /* SIGNAL_STRENGTH_GREAT */
});
+ sDefaults.putIntArray(KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY,
+ // Boundaries: [-140 dB, -44 dB]
+ new int[] {
+ -125, /* SIGNAL_STRENGTH_POOR */
+ -115, /* SIGNAL_STRENGTH_MODERATE */
+ -105, /* SIGNAL_STRENGTH_GOOD */
+ -95, /* SIGNAL_STRENGTH_GREAT */
+ });
+ sDefaults.putIntArray(KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY,
+ // Boundaries: [-20 dB, -3 dB]
+ new int[] {
+ -14, /* SIGNAL_STRENGTH_POOR */
+ -12, /* SIGNAL_STRENGTH_MODERATE */
+ -10, /* SIGNAL_STRENGTH_GOOD */
+ -8 /* SIGNAL_STRENGTH_GREAT */
+ });
+ sDefaults.putIntArray(KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY,
+ // Boundaries: [-23 dB, 40 dB]
+ new int[] {
+ -8, /* SIGNAL_STRENGTH_POOR */
+ 0, /* SIGNAL_STRENGTH_MODERATE */
+ 8, /* SIGNAL_STRENGTH_GOOD */
+ 16 /* SIGNAL_STRENGTH_GREAT */
+ });
+ sDefaults.putInt(KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT,
+ CellSignalStrengthNr.USE_SSRSRP);
sDefaults.putString(KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING, "rssi");
sDefaults.putBoolean(KEY_CONFIG_SHOW_ORIG_DIAL_STRING_FOR_CDMA_BOOL, false);
sDefaults.putBoolean(KEY_SHOW_CALL_BLOCKING_DISABLED_NOTIFICATION_ALWAYS_BOOL, false);
@@ -3810,6 +3866,34 @@
@SystemApi
@TestApi
public void overrideConfig(int subscriptionId, @Nullable PersistableBundle overrideValues) {
+ overrideConfig(subscriptionId, overrideValues, false);
+ }
+
+ /**
+ * Overrides the carrier config of the provided subscription ID with the provided values.
+ *
+ * Any further queries to carrier config from any process will return the overridden values
+ * after this method returns. The overrides are effective until the user passes in {@code null}
+ * for {@code overrideValues}. This removes all previous overrides and sets the carrier config
+ * back to production values.
+ *
+ * The overrides is stored persistently and will survive a reboot if {@code persistent} is true.
+ *
+ * May throw an {@link IllegalArgumentException} if {@code overrideValues} contains invalid
+ * values for the specified config keys.
+ *
+ * NOTE: This API is meant for testing purposes only.
+ *
+ * @param subscriptionId The subscription ID for which the override should be done.
+ * @param overrideValues Key-value pairs of the values that are to be overridden. If set to
+ * {@code null}, this will remove all previous overrides and set the
+ * carrier configuration back to production values.
+ * @param persistent Determines whether the override should be persistent.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ public void overrideConfig(int subscriptionId, @Nullable PersistableBundle overrideValues,
+ boolean persistent) {
try {
ICarrierConfigLoader loader = getICarrierConfigLoader();
if (loader == null) {
@@ -3817,7 +3901,7 @@
+ " ICarrierConfigLoader is null");
return;
}
- loader.overrideConfig(subscriptionId, overrideValues);
+ loader.overrideConfig(subscriptionId, overrideValues, persistent);
} catch (RemoteException ex) {
Rlog.e(TAG, "Error setting config for subId " + subscriptionId + ": "
+ ex.toString());
diff --git a/telephony/java/android/telephony/CbGeoUtils.java b/telephony/java/android/telephony/CbGeoUtils.java
index f4ce6e7..ce5e3f3 100644
--- a/telephony/java/android/telephony/CbGeoUtils.java
+++ b/telephony/java/android/telephony/CbGeoUtils.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.os.Build;
import android.text.TextUtils;
import java.util.ArrayList;
@@ -257,6 +258,15 @@
return new Point(x - p.x, y - p.y);
}
}
+
+ @Override
+ public String toString() {
+ String str = "Polygon: ";
+ if (Build.IS_DEBUGGABLE) {
+ str += mVertices;
+ }
+ return str;
+ }
}
/**
@@ -284,6 +294,16 @@
public boolean contains(LatLng p) {
return mCenter.distance(p) <= mRadiusMeter;
}
+
+ @Override
+ public String toString() {
+ String str = "Circle: ";
+ if (Build.IS_DEBUGGABLE) {
+ str += mCenter + ", radius = " + mRadiusMeter;
+ }
+
+ return str;
+ }
}
/**
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index f9b7f6d..f31fafe 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -16,11 +16,15 @@
package android.telephony;
+import android.annotation.IntDef;
import android.annotation.IntRange;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
import java.util.Objects;
/**
@@ -36,13 +40,67 @@
private static final String TAG = "CellSignalStrengthNr";
+ // Lifted from Default carrier configs and max range of SSRSRP
+ // Boundaries: [-140 dB, -44 dB]
+ private int[] mSsRsrpThresholds = new int[] {
+ -125, /* SIGNAL_STRENGTH_POOR */
+ -115, /* SIGNAL_STRENGTH_MODERATE */
+ -105, /* SIGNAL_STRENGTH_GOOD */
+ -95, /* SIGNAL_STRENGTH_GREAT */
+ };
+
+ // Lifted from Default carrier configs and max range of SSRSRQ
+ // Boundaries: [-20 dB, -3 dB]
+ private int[] mSsRsrqThresholds = new int[] {
+ -14, /* SIGNAL_STRENGTH_POOR */
+ -12, /* SIGNAL_STRENGTH_MODERATE */
+ -10, /* SIGNAL_STRENGTH_GOOD */
+ -8 /* SIGNAL_STRENGTH_GREAT */
+ };
+
+ // Lifted from Default carrier configs and max range of SSSINR
+ // Boundaries: [-23 dB, 40 dB]
+ private int[] mSsSinrThresholds = new int[] {
+ -8, /* SIGNAL_STRENGTH_POOR */
+ 0, /* SIGNAL_STRENGTH_MODERATE */
+ 8, /* SIGNAL_STRENGTH_GOOD */
+ 16 /* SIGNAL_STRENGTH_GREAT */
+ };
+
/**
- * These threshold values are copied from LTE.
- * TODO: make it configurable via CarrierConfig.
+ * Indicates SSRSRP is considered for {@link #getLevel()} and reporting from modem.
+ *
+ * @hide
*/
- private static final int SIGNAL_GREAT_THRESHOLD = -95;
- private static final int SIGNAL_GOOD_THRESHOLD = -105;
- private static final int SIGNAL_MODERATE_THRESHOLD = -115;
+ public static final int USE_SSRSRP = 1 << 0;
+ /**
+ * Indicates SSRSRQ is considered for {@link #getLevel()} and reporting from modem.
+ *
+ * @hide
+ */
+ public static final int USE_SSRSRQ = 1 << 1;
+ /**
+ * Indicates SSSINR is considered for {@link #getLevel()} and reporting from modem.
+ *
+ * @hide
+ */
+ public static final int USE_SSSINR = 1 << 2;
+
+ /**
+ * Bit-field integer to determine whether to use SS reference signal received power (SSRSRP),
+ * SS reference signal received quality (SSRSRQ), or/and SS signal-to-noise and interference
+ * ratio (SSSINR) for the number of 5G NR signal bars. If multiple measures are set bit, the
+ * parameter whose value is smallest is used to indicate the signal bar.
+ *
+ * @hide
+ */
+ @IntDef(flag = true, prefix = { "USE_" }, value = {
+ USE_SSRSRP,
+ USE_SSRSRQ,
+ USE_SSSINR
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SignalLevelAndReportCriteriaSource {}
private int mCsiRsrp;
private int mCsiRsrq;
@@ -52,6 +110,21 @@
private int mSsSinr;
private int mLevel;
+ /**
+ * Bit-field integer to determine whether to use SS reference signal received power (SSRSRP),
+ * SS reference signal received quality (SSRSRQ), or/and SS signal-to-noise and interference
+ * ratio (SSSINR) for the number of 5G NR signal bars. If multiple measures are set bit, the
+ * parameter whose value is smallest is used to indicate the signal bar.
+ *
+ * SSRSRP = 1 << 0,
+ * SSRSRQ = 1 << 1,
+ * SSSINR = 1 << 2,
+ *
+ * For example, if both SSRSRP and SSSINR are used, the value of key is 5 (1 << 0 | 1 << 2).
+ * If the key is invalid or not configured, a default value (SSRSRP = 1 << 0) will apply.
+ */
+ private int mParametersUseForLevel;
+
/** @hide */
public CellSignalStrengthNr() {
setDefaultValues();
@@ -182,6 +255,7 @@
mSsRsrq = CellInfo.UNAVAILABLE;
mSsSinr = CellInfo.UNAVAILABLE;
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ mParametersUseForLevel = USE_SSRSRP;
}
/** {@inheritDoc} */
@@ -191,20 +265,83 @@
return mLevel;
}
+ /**
+ * Checks if the given parameter type is considered to use for {@link #getLevel()}.
+ *
+ * Note: if multiple parameter types are considered, the smaller level for one of the
+ * parameters would be returned by {@link #getLevel()}
+ *
+ * @param parameterType bitwise OR of {@link #USE_SSRSRP}, {@link #USE_SSRSRQ},
+ * {@link #USE_SSSINR}
+ * @return {@code true} if the level is calculated based on the given parameter type;
+ * {@code false} otherwise.
+ *
+ */
+ private boolean isLevelForParameter(@SignalLevelAndReportCriteriaSource int parameterType) {
+ return (parameterType & mParametersUseForLevel) == parameterType;
+ }
+
/** @hide */
@Override
public void updateLevel(PersistableBundle cc, ServiceState ss) {
- if (mSsRsrp == CellInfo.UNAVAILABLE) {
- mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
- } else if (mSsRsrp >= SIGNAL_GREAT_THRESHOLD) {
- mLevel = SIGNAL_STRENGTH_GREAT;
- } else if (mSsRsrp >= SIGNAL_GOOD_THRESHOLD) {
- mLevel = SIGNAL_STRENGTH_GOOD;
- } else if (mSsRsrp >= SIGNAL_MODERATE_THRESHOLD) {
- mLevel = SIGNAL_STRENGTH_MODERATE;
+ if (cc == null) {
+ mParametersUseForLevel = USE_SSRSRP;
} else {
- mLevel = SIGNAL_STRENGTH_POOR;
+ mParametersUseForLevel = cc.getInt(
+ CarrierConfigManager.KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT, USE_SSRSRP);
+ Rlog.i(TAG, "Using SSRSRP for Level.");
+ mSsRsrpThresholds = cc.getIntArray(
+ CarrierConfigManager.KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY);
+ Rlog.i(TAG, "Applying 5G NR SSRSRP Thresholds: " + Arrays.toString(mSsRsrpThresholds));
+ mSsRsrqThresholds = cc.getIntArray(
+ CarrierConfigManager.KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY);
+ Rlog.i(TAG, "Applying 5G NR SSRSRQ Thresholds: " + Arrays.toString(mSsRsrqThresholds));
+ mSsSinrThresholds = cc.getIntArray(
+ CarrierConfigManager.KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY);
+ Rlog.i(TAG, "Applying 5G NR SSSINR Thresholds: " + Arrays.toString(mSsSinrThresholds));
}
+ int ssRsrpLevel = SignalStrength.INVALID;
+ int ssRsrqLevel = SignalStrength.INVALID;
+ int ssSinrLevel = SignalStrength.INVALID;
+ if (isLevelForParameter(USE_SSRSRP)) {
+ ssRsrpLevel = updateLevelWithMeasure(mSsRsrp, mSsRsrpThresholds);
+ Rlog.i(TAG, "Updated 5G NR SSRSRP Level: " + ssRsrpLevel);
+ }
+ if (isLevelForParameter(USE_SSRSRQ)) {
+ ssRsrqLevel = updateLevelWithMeasure(mSsRsrq, mSsRsrqThresholds);
+ Rlog.i(TAG, "Updated 5G NR SSRSRQ Level: " + ssRsrqLevel);
+ }
+ if (isLevelForParameter(USE_SSSINR)) {
+ ssSinrLevel = updateLevelWithMeasure(mSsSinr, mSsSinrThresholds);
+ Rlog.i(TAG, "Updated 5G NR SSSINR Level: " + ssSinrLevel);
+ }
+ // Apply the smaller value among three levels of three measures.
+ mLevel = Math.min(Math.min(ssRsrpLevel, ssRsrqLevel), ssSinrLevel);
+ }
+
+ /**
+ * Update level with corresponding measure and thresholds.
+ *
+ * @param measure corresponding signal measure
+ * @param thresholds corresponding signal thresholds
+ * @return level of the signal strength
+ */
+ private int updateLevelWithMeasure(int measure, int[] thresholds) {
+ int level;
+ if (measure == CellInfo.UNAVAILABLE) {
+ level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ } else if (measure > thresholds[3]) {
+ level = SIGNAL_STRENGTH_GREAT;
+ } else if (measure > thresholds[2]) {
+ level = SIGNAL_STRENGTH_GOOD;
+ } else if (measure > thresholds[1]) {
+ level = SIGNAL_STRENGTH_MODERATE;
+ } else if (measure > thresholds[0]) {
+ level = SIGNAL_STRENGTH_POOR;
+ } else {
+ level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ }
+ return level;
}
/**
@@ -247,6 +384,7 @@
mSsRsrq = s.mSsRsrq;
mSsSinr = s.mSsSinr;
mLevel = s.mLevel;
+ mParametersUseForLevel = s.mParametersUseForLevel;
}
/** @hide */
@@ -290,6 +428,7 @@
.append(" ssRsrq = " + mSsRsrq)
.append(" ssSinr = " + mSsSinr)
.append(" level = " + mLevel)
+ .append(" parametersUseForLevel = " + mParametersUseForLevel)
.append(" }")
.toString();
}
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index 246bec7..e1c4bef 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -15,17 +15,14 @@
*/
package android.telephony;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.content.Context;
import android.os.PersistableBundle;
-
import android.telephony.Annotation.DataFailureCause;
-import com.android.internal.util.ArrayUtils;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
+import com.android.internal.telephony.util.ArrayUtils;
+
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
@@ -953,14 +950,10 @@
public static final int UNKNOWN = 0x10000;
/** Data fail due to radio not unavailable. */
public static final int RADIO_NOT_AVAILABLE = 0x10001; /* no retry */
- /** @hide */
+ /** Data fail due to unacceptable network parameter. */
public static final int UNACCEPTABLE_NETWORK_PARAMETER = 0x10002; /* no retry */
- /** @hide */
- public static final int CONNECTION_TO_DATACONNECTIONAC_BROKEN = 0x10003;
/** Data connection was lost. */
public static final int LOST_CONNECTION = 0x10004;
- /** @hide */
- public static final int RESET_BY_FRAMEWORK = 0x10005;
/**
* Data handover failed.
@@ -1364,10 +1357,7 @@
sFailCauseMap.put(RADIO_NOT_AVAILABLE, "RADIO_NOT_AVAILABLE");
sFailCauseMap.put(UNACCEPTABLE_NETWORK_PARAMETER,
"UNACCEPTABLE_NETWORK_PARAMETER");
- sFailCauseMap.put(CONNECTION_TO_DATACONNECTIONAC_BROKEN,
- "CONNECTION_TO_DATACONNECTIONAC_BROKEN");
sFailCauseMap.put(LOST_CONNECTION, "LOST_CONNECTION");
- sFailCauseMap.put(RESET_BY_FRAMEWORK, "RESET_BY_FRAMEWORK");
}
private DataFailCause() {
diff --git a/telephony/java/android/telephony/IFinancialSmsCallback.aidl b/telephony/java/android/telephony/IFinancialSmsCallback.aidl
deleted file mode 100644
index aa88615..0000000
--- a/telephony/java/android/telephony/IFinancialSmsCallback.aidl
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-** Copyright 2019, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-package android.telephony;
-
-import android.app.PendingIntent;
-import android.database.CursorWindow;
-import android.net.Uri;
-import android.os.Bundle;
-import com.android.internal.telephony.SmsRawData;
-
-/** Interface for returning back the financial sms messages asynchrously.
- * @hide
- */
-interface IFinancialSmsCallback {
- /**
- * Return sms messages back to calling financial app.
- *
- * @param messages the sms messages returned for cinancial app.
- */
- oneway void onGetSmsMessagesForFinancialApp(in CursorWindow messages);
-}
diff --git a/telephony/java/android/telephony/LocationAccessPolicy.java b/telephony/java/android/telephony/LocationAccessPolicy.java
index eb744f6..d4526a4 100644
--- a/telephony/java/android/telephony/LocationAccessPolicy.java
+++ b/telephony/java/android/telephony/LocationAccessPolicy.java
@@ -33,6 +33,8 @@
import android.util.Log;
import android.widget.Toast;
+import com.android.internal.telephony.util.TelephonyUtils;
+
import java.util.List;
/**
@@ -162,7 +164,7 @@
}
Log.e(TAG, errorMsg);
try {
- if (Build.IS_DEBUGGABLE) {
+ if (TelephonyUtils.IS_DEBUGGABLE) {
Toast.makeText(context, errorMsg, Toast.LENGTH_SHORT).show();
}
} catch (Throwable t) {
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index bbf746fc..fc717e7 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -24,8 +24,8 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.AccessNetworkConstants.TransportType;
-
import android.telephony.Annotation.NetworkType;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -90,7 +90,7 @@
* Dual Connectivity(EN-DC).
* @hide
*/
- public static final int NR_STATE_NONE = -1;
+ public static final int NR_STATE_NONE = 0;
/**
* The device is camped on an LTE cell that supports E-UTRA-NR Dual Connectivity(EN-DC) but
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 1e601cf..d7d85c2 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -102,7 +102,7 @@
* Indicates frequency range is unknown.
* @hide
*/
- public static final int FREQUENCY_RANGE_UNKNOWN = -1;
+ public static final int FREQUENCY_RANGE_UNKNOWN = 0;
/**
* Indicates the frequency range is below 1GHz.
@@ -278,12 +278,9 @@
*/
public static final int UNKNOWN_ID = -1;
- private String mVoiceOperatorAlphaLong;
- private String mVoiceOperatorAlphaShort;
- private String mVoiceOperatorNumeric;
- private String mDataOperatorAlphaLong;
- private String mDataOperatorAlphaShort;
- private String mDataOperatorNumeric;
+ private String mOperatorAlphaLong;
+ private String mOperatorAlphaShort;
+ private String mOperatorNumeric;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
private boolean mIsManualNetworkSelection;
@@ -379,12 +376,9 @@
protected void copyFrom(ServiceState s) {
mVoiceRegState = s.mVoiceRegState;
mDataRegState = s.mDataRegState;
- mVoiceOperatorAlphaLong = s.mVoiceOperatorAlphaLong;
- mVoiceOperatorAlphaShort = s.mVoiceOperatorAlphaShort;
- mVoiceOperatorNumeric = s.mVoiceOperatorNumeric;
- mDataOperatorAlphaLong = s.mDataOperatorAlphaLong;
- mDataOperatorAlphaShort = s.mDataOperatorAlphaShort;
- mDataOperatorNumeric = s.mDataOperatorNumeric;
+ mOperatorAlphaLong = s.mOperatorAlphaLong;
+ mOperatorAlphaShort = s.mOperatorAlphaShort;
+ mOperatorNumeric = s.mOperatorNumeric;
mIsManualNetworkSelection = s.mIsManualNetworkSelection;
mCssIndicator = s.mCssIndicator;
mNetworkId = s.mNetworkId;
@@ -418,12 +412,9 @@
public ServiceState(Parcel in) {
mVoiceRegState = in.readInt();
mDataRegState = in.readInt();
- mVoiceOperatorAlphaLong = in.readString();
- mVoiceOperatorAlphaShort = in.readString();
- mVoiceOperatorNumeric = in.readString();
- mDataOperatorAlphaLong = in.readString();
- mDataOperatorAlphaShort = in.readString();
- mDataOperatorNumeric = in.readString();
+ mOperatorAlphaLong = in.readString();
+ mOperatorAlphaShort = in.readString();
+ mOperatorNumeric = in.readString();
mIsManualNetworkSelection = in.readInt() != 0;
mCssIndicator = (in.readInt() != 0);
mNetworkId = in.readInt();
@@ -448,12 +439,9 @@
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mVoiceRegState);
out.writeInt(mDataRegState);
- out.writeString(mVoiceOperatorAlphaLong);
- out.writeString(mVoiceOperatorAlphaShort);
- out.writeString(mVoiceOperatorNumeric);
- out.writeString(mDataOperatorAlphaLong);
- out.writeString(mDataOperatorAlphaShort);
- out.writeString(mDataOperatorNumeric);
+ out.writeString(mOperatorAlphaLong);
+ out.writeString(mOperatorAlphaShort);
+ out.writeString(mOperatorNumeric);
out.writeInt(mIsManualNetworkSelection ? 1 : 0);
out.writeInt(mCssIndicator ? 1 : 0);
out.writeInt(mNetworkId);
@@ -691,7 +679,7 @@
* @return long name of operator, null if unregistered or unknown
*/
public String getOperatorAlphaLong() {
- return mVoiceOperatorAlphaLong;
+ return mOperatorAlphaLong;
}
/**
@@ -699,18 +687,10 @@
* @return long name of operator
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@link #getOperatorAlphaLong} instead.")
public String getVoiceOperatorAlphaLong() {
- return mVoiceOperatorAlphaLong;
- }
-
- /**
- * Get current registered data network operator name in long alphanumeric format.
- * @return long name of voice operator
- * @hide
- */
- public String getDataOperatorAlphaLong() {
- return mDataOperatorAlphaLong;
+ return mOperatorAlphaLong;
}
/**
@@ -721,7 +701,7 @@
* @return short name of operator, null if unregistered or unknown
*/
public String getOperatorAlphaShort() {
- return mVoiceOperatorAlphaShort;
+ return mOperatorAlphaShort;
}
/**
@@ -729,9 +709,10 @@
* @return short name of operator, null if unregistered or unknown
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@link #getOperatorAlphaShort} instead.")
public String getVoiceOperatorAlphaShort() {
- return mVoiceOperatorAlphaShort;
+ return mOperatorAlphaShort;
}
/**
@@ -739,9 +720,10 @@
* @return short name of operator, null if unregistered or unknown
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@link #getOperatorAlphaShort} instead.")
public String getDataOperatorAlphaShort() {
- return mDataOperatorAlphaShort;
+ return mOperatorAlphaShort;
}
/**
@@ -755,11 +737,11 @@
* @hide
*/
public String getOperatorAlpha() {
- if (TextUtils.isEmpty(mVoiceOperatorAlphaLong)) {
- return mVoiceOperatorAlphaShort;
+ if (TextUtils.isEmpty(mOperatorAlphaLong)) {
+ return mOperatorAlphaShort;
}
- return mVoiceOperatorAlphaLong;
+ return mOperatorAlphaLong;
}
/**
@@ -775,7 +757,7 @@
* {@link com.android.internal.telephony.MccTable#countryCodeForMcc(int)}.
*/
public String getOperatorNumeric() {
- return mVoiceOperatorNumeric;
+ return mOperatorNumeric;
}
/**
@@ -785,7 +767,7 @@
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public String getVoiceOperatorNumeric() {
- return mVoiceOperatorNumeric;
+ return mOperatorNumeric;
}
/**
@@ -793,9 +775,10 @@
* @return numeric format of operator, null if unregistered or unknown
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
+ publicAlternatives = "Use {@link #getOperatorNumeric} instead.")
public String getDataOperatorNumeric() {
- return mDataOperatorNumeric;
+ return mOperatorNumeric;
}
/**
@@ -815,12 +798,9 @@
mDataRegState,
mChannelNumber,
Arrays.hashCode(mCellBandwidths),
- mVoiceOperatorAlphaLong,
- mVoiceOperatorAlphaShort,
- mVoiceOperatorNumeric,
- mDataOperatorAlphaLong,
- mDataOperatorAlphaShort,
- mDataOperatorNumeric,
+ mOperatorAlphaLong,
+ mOperatorAlphaShort,
+ mOperatorNumeric,
mIsManualNetworkSelection,
mCssIndicator,
mNetworkId,
@@ -850,12 +830,9 @@
&& mIsManualNetworkSelection == s.mIsManualNetworkSelection
&& mChannelNumber == s.mChannelNumber
&& Arrays.equals(mCellBandwidths, s.mCellBandwidths)
- && equalsHandlesNulls(mVoiceOperatorAlphaLong, s.mVoiceOperatorAlphaLong)
- && equalsHandlesNulls(mVoiceOperatorAlphaShort, s.mVoiceOperatorAlphaShort)
- && equalsHandlesNulls(mVoiceOperatorNumeric, s.mVoiceOperatorNumeric)
- && equalsHandlesNulls(mDataOperatorAlphaLong, s.mDataOperatorAlphaLong)
- && equalsHandlesNulls(mDataOperatorAlphaShort, s.mDataOperatorAlphaShort)
- && equalsHandlesNulls(mDataOperatorNumeric, s.mDataOperatorNumeric)
+ && equalsHandlesNulls(mOperatorAlphaLong, s.mOperatorAlphaLong)
+ && equalsHandlesNulls(mOperatorAlphaShort, s.mOperatorAlphaShort)
+ && equalsHandlesNulls(mOperatorNumeric, s.mOperatorNumeric)
&& equalsHandlesNulls(mCssIndicator, s.mCssIndicator)
&& equalsHandlesNulls(mNetworkId, s.mNetworkId)
&& equalsHandlesNulls(mSystemId, s.mSystemId)
@@ -964,7 +941,7 @@
rtString = "LTE_CA";
break;
case RIL_RADIO_TECHNOLOGY_NR:
- rtString = "LTE_NR";
+ rtString = "NR_SA";
break;
default:
rtString = "Unexpected";
@@ -1007,10 +984,8 @@
.append(", mChannelNumber=").append(mChannelNumber)
.append(", duplexMode()=").append(getDuplexMode())
.append(", mCellBandwidths=").append(Arrays.toString(mCellBandwidths))
- .append(", mVoiceOperatorAlphaLong=").append(mVoiceOperatorAlphaLong)
- .append(", mVoiceOperatorAlphaShort=").append(mVoiceOperatorAlphaShort)
- .append(", mDataOperatorAlphaLong=").append(mDataOperatorAlphaLong)
- .append(", mDataOperatorAlphaShort=").append(mDataOperatorAlphaShort)
+ .append(", mOperatorAlphaLong=").append(mOperatorAlphaLong)
+ .append(", mOperatorAlphaShort=").append(mOperatorAlphaShort)
.append(", isManualNetworkSelection=").append(mIsManualNetworkSelection)
.append(mIsManualNetworkSelection ? "(manual)" : "(automatic)")
.append(", getRilVoiceRadioTechnology=").append(getRilVoiceRadioTechnology())
@@ -1040,12 +1015,9 @@
mDataRegState = STATE_OUT_OF_SERVICE;
mChannelNumber = -1;
mCellBandwidths = new int[0];
- mVoiceOperatorAlphaLong = null;
- mVoiceOperatorAlphaShort = null;
- mVoiceOperatorNumeric = null;
- mDataOperatorAlphaLong = null;
- mDataOperatorAlphaShort = null;
- mDataOperatorNumeric = null;
+ mOperatorAlphaLong = null;
+ mOperatorAlphaShort = null;
+ mOperatorNumeric = null;
mIsManualNetworkSelection = false;
mCssIndicator = false;
mNetworkId = -1;
@@ -1204,26 +1176,9 @@
}
public void setOperatorName(String longName, String shortName, String numeric) {
- mVoiceOperatorAlphaLong = longName;
- mVoiceOperatorAlphaShort = shortName;
- mVoiceOperatorNumeric = numeric;
- mDataOperatorAlphaLong = longName;
- mDataOperatorAlphaShort = shortName;
- mDataOperatorNumeric = numeric;
- }
-
- /** @hide */
- public void setVoiceOperatorName(String longName, String shortName, String numeric) {
- mVoiceOperatorAlphaLong = longName;
- mVoiceOperatorAlphaShort = shortName;
- mVoiceOperatorNumeric = numeric;
- }
-
- /** @hide */
- public void setDataOperatorName(String longName, String shortName, String numeric) {
- mDataOperatorAlphaLong = longName;
- mDataOperatorAlphaShort = shortName;
- mDataOperatorNumeric = numeric;
+ mOperatorAlphaLong = longName;
+ mOperatorAlphaShort = shortName;
+ mOperatorNumeric = numeric;
}
/**
@@ -1233,19 +1188,8 @@
* @hide
*/
@UnsupportedAppUsage
- public void setOperatorAlphaLong(String longName) {
- mVoiceOperatorAlphaLong = longName;
- mDataOperatorAlphaLong = longName;
- }
-
- /** @hide */
- public void setVoiceOperatorAlphaLong(String longName) {
- mVoiceOperatorAlphaLong = longName;
- }
-
- /** @hide */
- public void setDataOperatorAlphaLong(String longName) {
- mDataOperatorAlphaLong = longName;
+ public void setOperatorAlphaLong(@Nullable String longName) {
+ mOperatorAlphaLong = longName;
}
public void setIsManualSelection(boolean isManual) {
@@ -1293,12 +1237,12 @@
m.putInt("dataRegState", mDataRegState);
m.putInt("dataRoamingType", getDataRoamingType());
m.putInt("voiceRoamingType", getVoiceRoamingType());
- m.putString("operator-alpha-long", mVoiceOperatorAlphaLong);
- m.putString("operator-alpha-short", mVoiceOperatorAlphaShort);
- m.putString("operator-numeric", mVoiceOperatorNumeric);
- m.putString("data-operator-alpha-long", mDataOperatorAlphaLong);
- m.putString("data-operator-alpha-short", mDataOperatorAlphaShort);
- m.putString("data-operator-numeric", mDataOperatorNumeric);
+ m.putString("operator-alpha-long", mOperatorAlphaLong);
+ m.putString("operator-alpha-short", mOperatorAlphaShort);
+ m.putString("operator-numeric", mOperatorNumeric);
+ m.putString("data-operator-alpha-long", mOperatorAlphaLong);
+ m.putString("data-operator-alpha-short", mOperatorAlphaShort);
+ m.putString("data-operator-numeric", mOperatorNumeric);
m.putBoolean("manual", mIsManualNetworkSelection);
m.putInt("radioTechnology", getRilVoiceRadioTechnology());
m.putInt("dataRadioTechnology", getRadioTechnology());
@@ -1535,8 +1479,9 @@
return AccessNetworkType.CDMA2000;
case RIL_RADIO_TECHNOLOGY_LTE:
case RIL_RADIO_TECHNOLOGY_LTE_CA:
- case RIL_RADIO_TECHNOLOGY_NR:
return AccessNetworkType.EUTRAN;
+ case RIL_RADIO_TECHNOLOGY_NR:
+ return AccessNetworkType.NGRAN;
case RIL_RADIO_TECHNOLOGY_IWLAN:
return AccessNetworkType.IWLAN;
case RIL_RADIO_TECHNOLOGY_UNKNOWN:
@@ -1933,12 +1878,9 @@
}
if (!removeCoarseLocation) return state;
- state.mDataOperatorAlphaLong = null;
- state.mDataOperatorAlphaShort = null;
- state.mDataOperatorNumeric = null;
- state.mVoiceOperatorAlphaLong = null;
- state.mVoiceOperatorAlphaShort = null;
- state.mVoiceOperatorNumeric = null;
+ state.mOperatorAlphaLong = null;
+ state.mOperatorAlphaShort = null;
+ state.mOperatorNumeric = null;
return state;
}
diff --git a/telephony/java/android/telephony/SignalThresholdInfo.java b/telephony/java/android/telephony/SignalThresholdInfo.java
new file mode 100644
index 0000000..f6f6d75
--- /dev/null
+++ b/telephony/java/android/telephony/SignalThresholdInfo.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Defines the threshold value of the signal strength.
+ * @hide
+ */
+public class SignalThresholdInfo implements Parcelable {
+ /**
+ * Received Signal Strength Indication.
+ * Range: -113 dBm and -51 dBm
+ * Used RAN: GERAN, CDMA2000
+ * Reference: 3GPP TS 27.007 section 8.5.
+ */
+ public static final int SIGNAL_RSSI = 1;
+
+ /**
+ * Received Signal Code Power.
+ * Range: -120 dBm to -25 dBm;
+ * Used RAN: UTRAN
+ * Reference: 3GPP TS 25.123, section 9.1.1.1
+ */
+ public static final int SIGNAL_RSCP = 2;
+
+ /**
+ * Reference Signal Received Power.
+ * Range: -140 dBm to -44 dBm;
+ * Used RAN: EUTRAN
+ * Reference: 3GPP TS 36.133 9.1.4
+ */
+ public static final int SIGNAL_RSRP = 3;
+
+ /**
+ * Reference Signal Received Quality
+ * Range: -20 dB to -3 dB;
+ * Used RAN: EUTRAN
+ * Reference: 3GPP TS 36.133 9.1.7
+ */
+ public static final int SIGNAL_RSRQ = 4;
+
+ /**
+ * Reference Signal Signal to Noise Ratio
+ * Range: -20 dB to 30 dB;
+ * Used RAN: EUTRAN
+ */
+ public static final int SIGNAL_RSSNR = 5;
+
+ /**
+ * 5G SS reference signal received power.
+ * Range: -140 dBm to -44 dBm.
+ * Used RAN: NGRAN
+ * Reference: 3GPP TS 38.215.
+ */
+ public static final int SIGNAL_SSRSRP = 6;
+
+ /**
+ * 5G SS reference signal received quality.
+ * Range: -20 dB to -3 dB.
+ * Used RAN: NGRAN
+ * Reference: 3GPP TS 38.215.
+ */
+ public static final int SIGNAL_SSRSRQ = 7;
+
+ /**
+ * 5G SS signal-to-noise and interference ratio.
+ * Range: -23 dB to 40 dB
+ * Used RAN: NGRAN
+ * Reference: 3GPP TS 38.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1.
+ */
+ public static final int SIGNAL_SSSINR = 8;
+
+ /** @hide */
+ @IntDef(prefix = { "SIGNAL_" }, value = {
+ SIGNAL_RSSI,
+ SIGNAL_RSCP,
+ SIGNAL_RSRP,
+ SIGNAL_RSRQ,
+ SIGNAL_RSSNR,
+ SIGNAL_SSRSRP,
+ SIGNAL_SSRSRQ,
+ SIGNAL_SSSINR
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SignalMeasurementType {}
+
+ @SignalMeasurementType
+ private int mSignalMeasurement;
+
+ /**
+ * A hysteresis time in milliseconds to prevent flapping.
+ * A value of 0 disables hysteresis
+ */
+ private int mHysteresisMs;
+
+ /**
+ * An interval in dB defining the required magnitude change between reports.
+ * hysteresisDb must be smaller than the smallest threshold delta.
+ * An interval value of 0 disables hysteresis.
+ */
+ private int mHysteresisDb;
+
+ /**
+ * List of threshold values.
+ * Range and unit must reference specific SignalMeasurementType
+ * The threshold values for which to apply criteria.
+ * A vector size of 0 disables the use of thresholds for reporting.
+ */
+ private int[] mThresholds = null;
+
+ /**
+ * {@code true} means modem must trigger the report based on the criteria;
+ * {@code false} means modem must not trigger the report based on the criteria.
+ */
+ private boolean mIsEnabled = true;
+
+ /**
+ * Indicates the hysteresisMs is disabled.
+ */
+ public static final int HYSTERESIS_MS_DISABLED = 0;
+
+ /**
+ * Indicates the hysteresisDb is disabled.
+ */
+ public static final int HYSTERESIS_DB_DISABLED = 0;
+
+ /**
+ * Constructor
+ *
+ * @param signalMeasurement Signal Measurement Type
+ * @param hysteresisMs hysteresisMs
+ * @param hysteresisDb hysteresisDb
+ * @param thresholds threshold value
+ * @param isEnabled isEnabled
+ */
+ public SignalThresholdInfo(@SignalMeasurementType int signalMeasurement,
+ int hysteresisMs, int hysteresisDb, @NonNull int [] thresholds, boolean isEnabled) {
+ mSignalMeasurement = signalMeasurement;
+ mHysteresisMs = hysteresisMs < 0 ? HYSTERESIS_MS_DISABLED : hysteresisMs;
+ mHysteresisDb = hysteresisDb < 0 ? HYSTERESIS_DB_DISABLED : hysteresisDb;
+ mThresholds = thresholds == null ? null : thresholds.clone();
+ mIsEnabled = isEnabled;
+ }
+
+ public @SignalMeasurementType int getSignalMeasurement() {
+ return mSignalMeasurement;
+ }
+
+ public int getHysteresisMs() {
+ return mHysteresisMs;
+ }
+
+ public int getHysteresisDb() {
+ return mHysteresisDb;
+ }
+
+ public boolean isEnabled() {
+ return mIsEnabled;
+ }
+
+ public int[] getThresholds() {
+ return mThresholds == null ? null : mThresholds.clone();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mSignalMeasurement);
+ out.writeInt(mHysteresisMs);
+ out.writeInt(mHysteresisDb);
+ out.writeIntArray(mThresholds);
+ out.writeBoolean(mIsEnabled);
+ }
+
+ private SignalThresholdInfo(Parcel in) {
+ mSignalMeasurement = in.readInt();
+ mHysteresisMs = in.readInt();
+ mHysteresisDb = in.readInt();
+ mThresholds = in.createIntArray();
+ mIsEnabled = in.readBoolean();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+
+ if (!(o instanceof SignalThresholdInfo)) {
+ return false;
+ }
+
+ SignalThresholdInfo other = (SignalThresholdInfo) o;
+ return mSignalMeasurement == other.mSignalMeasurement
+ && mHysteresisMs == other.mHysteresisMs
+ && mHysteresisDb == other.mHysteresisDb
+ && Arrays.equals(mThresholds, other.mThresholds)
+ && mIsEnabled == other.mIsEnabled;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(
+ mSignalMeasurement, mHysteresisMs, mHysteresisDb, mThresholds, mIsEnabled);
+ }
+
+ public static final @NonNull Parcelable.Creator<SignalThresholdInfo> CREATOR =
+ new Parcelable.Creator<SignalThresholdInfo>() {
+ @Override
+ public SignalThresholdInfo createFromParcel(Parcel in) {
+ return new SignalThresholdInfo(in);
+ }
+
+ @Override
+ public SignalThresholdInfo[] newArray(int size) {
+ return new SignalThresholdInfo[size];
+ }
+ };
+
+ @Override
+ public String toString() {
+ return new StringBuilder("SignalThresholdInfo{")
+ .append("mSignalMeasurement=").append(mSignalMeasurement)
+ .append("mHysteresisMs=").append(mSignalMeasurement)
+ .append("mHysteresisDb=").append(mHysteresisDb)
+ .append("mThresholds=").append(Arrays.toString(mThresholds))
+ .append("mIsEnabled=").append(mIsEnabled)
+ .append("}").toString();
+ }
+}
diff --git a/telephony/java/android/telephony/SmsCbMessage.java b/telephony/java/android/telephony/SmsCbMessage.java
index fad70d2..045d1eb 100644
--- a/telephony/java/android/telephony/SmsCbMessage.java
+++ b/telephony/java/android/telephony/SmsCbMessage.java
@@ -29,6 +29,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -407,13 +408,17 @@
}
/**
- * Get the warning area coordinates information represent by polygons and circles.
- * @return a list of geometries, {@link Nullable} means there is no coordinate information
- * associated to this message.
+ * Get the warning area coordinates information represented by polygons and circles.
+ * @return a list of geometries, or an empty list if there is no coordinate information
+ * associated with this message.
* @hide
*/
- @Nullable
+ @SystemApi
+ @NonNull
public List<Geometry> getGeometries() {
+ if (mGeometries == null) {
+ return new ArrayList<>();
+ }
return mGeometries;
}
@@ -528,7 +533,8 @@
+ ", priority=" + mPriority
+ (mEtwsWarningInfo != null ? (", " + mEtwsWarningInfo.toString()) : "")
+ (mCmasWarningInfo != null ? (", " + mCmasWarningInfo.toString()) : "")
- + ", maximumWaitingTime = " + mMaximumWaitTimeSec
+ + ", maximumWaitingTime=" + mMaximumWaitTimeSec
+ + ", received time=" + mReceivedTimeMillis
+ ", slotIndex = " + mSlotIndex
+ ", geo=" + (mGeometries != null
? CbGeoUtils.encodeGeometriesToString(mGeometries) : "null")
@@ -720,6 +726,6 @@
* @return {@code True} if this message needs geo-fencing check.
*/
public boolean needGeoFencingCheck() {
- return mMaximumWaitTimeSec > 0 && mGeometries != null;
+ return mMaximumWaitTimeSec > 0 && mGeometries != null && !mGeometries.isEmpty();
}
}
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index daeacf8..5b49117 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -32,6 +32,7 @@
import android.database.CursorWindow;
import android.net.Uri;
import android.os.Binder;
+import android.os.BaseBundle;
import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
@@ -79,11 +80,6 @@
SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
private static final Object sLockObject = new Object();
- /** @hide */
- public static final int CELL_BROADCAST_RAN_TYPE_GSM = 0;
- /** @hide */
- public static final int CELL_BROADCAST_RAN_TYPE_CDMA = 1;
-
/** SMS record length from TS 51.011 10.5.3
* @hide
*/
@@ -2457,7 +2453,9 @@
}
}
- /** callback for providing asynchronous sms messages for financial app. */
+ /**
+ * callback for providing asynchronous sms messages for financial app.
+ */
public abstract static class FinancialSmsCallback {
/**
* Callback to send sms messages back to financial app asynchronously.
@@ -2483,24 +2481,14 @@
* @param params the parameters to filter SMS messages returned.
* @param executor the executor on which callback will be invoked.
* @param callback a callback to receive CursorWindow with SMS messages.
+ *
*/
@RequiresPermission(android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS)
public void getSmsMessagesForFinancialApp(
Bundle params,
@NonNull @CallbackExecutor Executor executor,
@NonNull FinancialSmsCallback callback) {
- try {
- ISms iccSms = getISmsServiceOrThrow();
- iccSms.getSmsMessagesForFinancialApp(
- getSubscriptionId(), ActivityThread.currentPackageName(), params,
- new IFinancialSmsCallback.Stub() {
- public void onGetSmsMessagesForFinancialApp(CursorWindow msgs) {
- Binder.withCleanCallingIdentity(() -> executor.execute(
- () -> callback.onFinancialSmsMessages(msgs)));
- }});
- } catch (RemoteException ex) {
- ex.rethrowFromSystemServer();
- }
+ // This API is not functional and thus removed to avoid future confusion.
}
/**
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 9eff809..257c606 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -30,7 +30,6 @@
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.Typeface;
-import android.os.Build;
import android.os.Parcel;
import android.os.ParcelUuid;
import android.os.Parcelable;
@@ -38,6 +37,8 @@
import android.util.DisplayMetrics;
import android.util.Log;
+import com.android.internal.telephony.util.TelephonyUtils;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -89,8 +90,8 @@
private int mCarrierId;
/**
- * The source of the name, NAME_SOURCE_DEFAULT_SOURCE, NAME_SOURCE_SIM_SOURCE or
- * NAME_SOURCE_USER_INPUT.
+ * The source of the name, NAME_SOURCE_DEFAULT_SOURCE, NAME_SOURCE_SIM_SPN,
+ * NAME_SOURCE_SIM_PNN, or NAME_SOURCE_USER_INPUT.
*/
private int mNameSource;
@@ -334,7 +335,7 @@
}
/**
- * @return the source of the name, eg NAME_SOURCE_DEFAULT_SOURCE, NAME_SOURCE_SIM_SOURCE or
+ * @return the source of the name, eg NAME_SOURCE_DEFAULT_SOURCE, NAME_SOURCE_SIM_SPN or
* NAME_SOURCE_USER_INPUT.
* @hide
*/
@@ -748,7 +749,7 @@
public static String givePrintableIccid(String iccId) {
String iccIdToPrint = null;
if (iccId != null) {
- if (iccId.length() > 9 && !Build.IS_DEBUGGABLE) {
+ if (iccId.length() > 9 && !TelephonyUtils.IS_DEBUGGABLE) {
iccIdToPrint = iccId.substring(0, 9) + Rlog.pii(false, iccId.substring(9));
} else {
iccIdToPrint = iccId;
@@ -764,7 +765,8 @@
return "{id=" + mId + " iccId=" + iccIdToPrint + " simSlotIndex=" + mSimSlotIndex
+ " carrierId=" + mCarrierId + " displayName=" + mDisplayName
+ " carrierName=" + mCarrierName + " nameSource=" + mNameSource
- + " iconTint=" + mIconTint + " mNumber=" + Rlog.pii(Build.IS_DEBUGGABLE, mNumber)
+ + " iconTint=" + mIconTint
+ + " mNumber=" + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, mNumber)
+ " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc " + mMcc
+ " mnc " + mMnc + "mCountryIso=" + mCountryIso + " isEmbedded " + mIsEmbedded
+ " nativeAccessRules " + Arrays.toString(mNativeAccessRules)
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index fbbc951..4f90840 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -35,7 +35,6 @@
import android.annotation.UnsupportedAppUsage;
import android.app.BroadcastOptions;
import android.app.PendingIntent;
-import android.app.job.JobService;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
@@ -148,10 +147,11 @@
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
* subscription wfc enabled {@link ImsMmTelManager#isVoWiFiSettingEnabled()}
- * while your app is running. You can also use a {@link JobService} to ensure your app
+ * while your app is running. You can also use a {@link android.app.job.JobService}
+ * to ensure your app
* is notified of changes to the {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
- * updates to the {@link Uri}.
+ * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+ * delivery of updates to the {@link Uri}.
* To be notified of changes to a specific subId, append subId to the URI
* {@link Uri#withAppendedPath(Uri, String)}.
* @hide
@@ -168,10 +168,10 @@
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
* subscription advanced calling enabled
* {@link ImsMmTelManager#isAdvancedCallingSettingEnabled()} while your app is running.
- * You can also use a {@link JobService} to ensure your app is notified of changes to the
- * {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
- * updates to the {@link Uri}.
+ * You can also use a {@link android.app.job.JobService} to ensure your app is notified of
+ * changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+ * delivery of updates to the {@link Uri}.
* To be notified of changes to a specific subId, append subId to the URI
* {@link Uri#withAppendedPath(Uri, String)}.
* @hide
@@ -187,10 +187,10 @@
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
* subscription wfc mode {@link ImsMmTelManager#getVoWiFiModeSetting()}
- * while your app is running. You can also use a {@link JobService} to ensure your app
- * is notified of changes to the {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
- * updates to the {@link Uri}.
+ * while your app is running. You can also use a {@link android.app.job.JobService} to ensure
+ * your app is notified of changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+ * delivery of updates to the {@link Uri}.
* To be notified of changes to a specific subId, append subId to the URI
* {@link Uri#withAppendedPath(Uri, String)}.
* @hide
@@ -205,10 +205,10 @@
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
* subscription wfc roaming mode {@link ImsMmTelManager#getVoWiFiRoamingModeSetting()}
- * while your app is running. You can also use a {@link JobService} to ensure your app
- * is notified of changes to the {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
- * updates to the {@link Uri}.
+ * while your app is running. You can also use a {@link android.app.job.JobService}
+ * to ensure your app is notified of changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+ * delivery of updates to the {@link Uri}.
* To be notified of changes to a specific subId, append subId to the URI
* {@link Uri#withAppendedPath(Uri, String)}.
* @hide
@@ -225,10 +225,10 @@
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
* subscription vt enabled {@link ImsMmTelManager#isVtSettingEnabled()}
- * while your app is running. You can also use a {@link JobService} to ensure your app
- * is notified of changes to the {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
- * updates to the {@link Uri}.
+ * while your app is running. You can also use a {@link android.app.job.JobService} to ensure
+ * your app is notified of changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+ * delivery of updates to the {@link Uri}.
* To be notified of changes to a specific subId, append subId to the URI
* {@link Uri#withAppendedPath(Uri, String)}.
* @hide
@@ -244,10 +244,10 @@
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
* subscription wfc roaming enabled {@link ImsMmTelManager#isVoWiFiRoamingSettingEnabled()}
- * while your app is running. You can also use a {@link JobService} to ensure your app
- * is notified of changes to the {@link Uri} even when it is not running.
- * Note, however, that using a {@link JobService} does not guarantee timely delivery of
- * updates to the {@link Uri}.
+ * while your app is running. You can also use a {@link android.app.job.JobService} to ensure
+ * your app is notified of changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+ * delivery of updates to the {@link Uri}.
* To be notified of changes to a specific subId, append subId to the URI
* {@link Uri#withAppendedPath(Uri, String)}.
* @hide
@@ -400,19 +400,19 @@
public static final String NAME_SOURCE = "name_source";
/**
- * The name_source is the default
+ * The name_source is the default, which is from the carrier id.
* @hide
*/
public static final int NAME_SOURCE_DEFAULT_SOURCE = 0;
/**
- * The name_source is from the SIM
+ * The name_source is from SIM EF_SPN.
* @hide
*/
- public static final int NAME_SOURCE_SIM_SOURCE = 1;
+ public static final int NAME_SOURCE_SIM_SPN = 1;
/**
- * The name_source is from the user
+ * The name_source is from user input
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -425,6 +425,24 @@
public static final int NAME_SOURCE_CARRIER = 3;
/**
+ * The name_source is from SIM EF_PNN.
+ * @hide
+ */
+ public static final int NAME_SOURCE_SIM_PNN = 4;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"NAME_SOURCE_"},
+ value = {
+ NAME_SOURCE_DEFAULT_SOURCE,
+ NAME_SOURCE_SIM_SPN,
+ NAME_SOURCE_USER_INPUT,
+ NAME_SOURCE_CARRIER,
+ NAME_SOURCE_SIM_PNN
+ })
+ public @interface SimDisplayNameSource {}
+
+ /**
* TelephonyProvider column name for the color of a SIM.
* <P>Type: INTEGER (int)</P>
*/
@@ -1660,13 +1678,12 @@
* Set display name by simInfo index with name source
* @param displayName the display name of SIM card
* @param subId the unique SubscriptionInfo index in database
- * @param nameSource 0: NAME_SOURCE_DEFAULT_SOURCE, 1: NAME_SOURCE_SIM_SOURCE,
- * 2: NAME_SOURCE_USER_INPUT
+ * @param nameSource SIM display name source
* @return the number of records updated or < 0 if invalid subId
* @hide
*/
@UnsupportedAppUsage
- public int setDisplayName(String displayName, int subId, int nameSource) {
+ public int setDisplayName(String displayName, int subId, @SimDisplayNameSource int nameSource) {
if (VDBG) {
logd("[setDisplayName]+ displayName:" + displayName + " subId:" + subId
+ " nameSource:" + nameSource);
@@ -2897,8 +2914,7 @@
*
* @throws SecurityException if the caller doesn't meet the requirements
* outlined above.
- * @throws IllegalArgumentException if the some subscriptions in the list doesn't exist,
- * or the groupUuid doesn't exist.
+ * @throws IllegalArgumentException if the some subscriptions in the list doesn't exist.
* @throws IllegalStateException if Telephony service is in bad state.
*
* @param subIdList list of subId that need adding into the group
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 2cfc2b7..642030b 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -416,14 +416,14 @@
int modemCount = 1;
switch (getMultiSimConfiguration()) {
case UNKNOWN:
- ConnectivityManager cm = mContext == null ? null : (ConnectivityManager) mContext
- .getSystemService(Context.CONNECTIVITY_SERVICE);
+ modemCount = MODEM_COUNT_SINGLE_MODEM;
// check for voice and data support, 0 if not supported
- if (!isVoiceCapable() && !isSmsCapable() && cm != null
- && !cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)) {
- modemCount = MODEM_COUNT_NO_MODEM;
- } else {
- modemCount = MODEM_COUNT_SINGLE_MODEM;
+ if (!isVoiceCapable() && !isSmsCapable() && mContext != null) {
+ ConnectivityManager cm = (ConnectivityManager) mContext
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (cm != null && !cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)) {
+ modemCount = MODEM_COUNT_NO_MODEM;
+ }
}
break;
case DSDS:
@@ -592,6 +592,7 @@
*
* @hide
*/
+ @SystemApi
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_EMERGENCY_ASSISTANCE =
"android.telephony.action.EMERGENCY_ASSISTANCE";
@@ -703,31 +704,6 @@
public static final String EXTRA_INCOMING_NUMBER = "incoming_number";
/**
- * Broadcast intent action indicating that a precise call state
- * (cellular) on the device has changed.
- *
- * <p>
- * The {@link #EXTRA_RINGING_CALL_STATE} extra indicates the ringing call state.
- * The {@link #EXTRA_FOREGROUND_CALL_STATE} extra indicates the foreground call state.
- * The {@link #EXTRA_BACKGROUND_CALL_STATE} extra indicates the background call state.
- *
- * <p class="note">
- * Requires the READ_PRECISE_PHONE_STATE permission.
- *
- * @see #EXTRA_RINGING_CALL_STATE
- * @see #EXTRA_FOREGROUND_CALL_STATE
- * @see #EXTRA_BACKGROUND_CALL_STATE
- *
- * <p class="note">
- * Requires the READ_PRECISE_PHONE_STATE permission.
- * @deprecated use {@link PhoneStateListener#LISTEN_PRECISE_CALL_STATE} instead
- * @hide
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_PRECISE_CALL_STATE_CHANGED =
- "android.intent.action.PRECISE_CALL_STATE";
-
- /**
* Broadcast intent action indicating that call disconnect cause has changed.
*
* <p>
@@ -749,78 +725,6 @@
/**
* The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast and
* {@link PhoneStateListener#onPreciseCallStateChanged(PreciseCallState)} for an integer
- * containing the state of the current ringing call.
- *
- * @see PreciseCallState#PRECISE_CALL_STATE_NOT_VALID
- * @see PreciseCallState#PRECISE_CALL_STATE_IDLE
- * @see PreciseCallState#PRECISE_CALL_STATE_ACTIVE
- * @see PreciseCallState#PRECISE_CALL_STATE_HOLDING
- * @see PreciseCallState#PRECISE_CALL_STATE_DIALING
- * @see PreciseCallState#PRECISE_CALL_STATE_ALERTING
- * @see PreciseCallState#PRECISE_CALL_STATE_INCOMING
- * @see PreciseCallState#PRECISE_CALL_STATE_WAITING
- * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
- * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
- *
- * <p class="note">
- * Retrieve with
- * {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
- *
- * @hide
- */
- public static final String EXTRA_RINGING_CALL_STATE = "ringing_state";
-
- /**
- * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast and
- * {@link PhoneStateListener#onPreciseCallStateChanged(PreciseCallState)} for an integer
- * containing the state of the current foreground call.
- *
- * @see PreciseCallState#PRECISE_CALL_STATE_NOT_VALID
- * @see PreciseCallState#PRECISE_CALL_STATE_IDLE
- * @see PreciseCallState#PRECISE_CALL_STATE_ACTIVE
- * @see PreciseCallState#PRECISE_CALL_STATE_HOLDING
- * @see PreciseCallState#PRECISE_CALL_STATE_DIALING
- * @see PreciseCallState#PRECISE_CALL_STATE_ALERTING
- * @see PreciseCallState#PRECISE_CALL_STATE_INCOMING
- * @see PreciseCallState#PRECISE_CALL_STATE_WAITING
- * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
- * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
- *
- * <p class="note">
- * Retrieve with
- * {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
- *
- * @hide
- */
- public static final String EXTRA_FOREGROUND_CALL_STATE = "foreground_state";
-
- /**
- * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast and
- * {@link PhoneStateListener#onPreciseCallStateChanged(PreciseCallState)} for an integer
- * containing the state of the current background call.
- *
- * @see PreciseCallState#PRECISE_CALL_STATE_NOT_VALID
- * @see PreciseCallState#PRECISE_CALL_STATE_IDLE
- * @see PreciseCallState#PRECISE_CALL_STATE_ACTIVE
- * @see PreciseCallState#PRECISE_CALL_STATE_HOLDING
- * @see PreciseCallState#PRECISE_CALL_STATE_DIALING
- * @see PreciseCallState#PRECISE_CALL_STATE_ALERTING
- * @see PreciseCallState#PRECISE_CALL_STATE_INCOMING
- * @see PreciseCallState#PRECISE_CALL_STATE_WAITING
- * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
- * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
- *
- * <p class="note">
- * Retrieve with
- * {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
- *
- * @hide
- */
- public static final String EXTRA_BACKGROUND_CALL_STATE = "background_state";
-
- /**
- * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast and
- * {@link PhoneStateListener#onPreciseCallStateChanged(PreciseCallState)} for an integer
* containing the disconnect cause.
*
* @see DisconnectCause
@@ -849,88 +753,6 @@
public static final String EXTRA_PRECISE_DISCONNECT_CAUSE = "precise_disconnect_cause";
/**
- * Broadcast intent action indicating a data connection has changed,
- * providing precise information about the connection.
- *
- * <p>
- * The {@link #EXTRA_DATA_STATE} extra indicates the connection state.
- * The {@link #EXTRA_DATA_NETWORK_TYPE} extra indicates the connection network type.
- * The {@link #EXTRA_DATA_APN_TYPE} extra indicates the APN type.
- * The {@link #EXTRA_DATA_APN} extra indicates the APN.
- * The {@link #EXTRA_DATA_IFACE_PROPERTIES} extra indicates the connection interface.
- * The {@link #EXTRA_DATA_FAILURE_CAUSE} extra indicates the connection fail cause.
- *
- * <p class="note">
- * Requires the READ_PRECISE_PHONE_STATE permission.
- *
- * @see #EXTRA_DATA_STATE
- * @see #EXTRA_DATA_NETWORK_TYPE
- * @see #EXTRA_DATA_APN_TYPE
- * @see #EXTRA_DATA_APN
- * @see #EXTRA_DATA_IFACE
- * @see #EXTRA_DATA_FAILURE_CAUSE
- * @hide
- *
- * @deprecated If the app is running in the background, it won't be able to receive this
- * broadcast. Apps should use ConnectivityManager {@link #registerNetworkCallback(
- * android.net.NetworkRequest, ConnectivityManager.NetworkCallback)} to listen for network
- * changes.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @Deprecated
- @UnsupportedAppUsage
- public static final String ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED =
- "android.intent.action.PRECISE_DATA_CONNECTION_STATE_CHANGED";
-
- /**
- * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
- * for an integer containing the state of the current data connection.
- *
- * @see TelephonyManager#DATA_UNKNOWN
- * @see TelephonyManager#DATA_DISCONNECTED
- * @see TelephonyManager#DATA_CONNECTING
- * @see TelephonyManager#DATA_CONNECTED
- * @see TelephonyManager#DATA_SUSPENDED
- *
- * <p class="note">
- * Retrieve with
- * {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
- *
- * @hide
- */
- public static final String EXTRA_DATA_STATE = PhoneConstants.STATE_KEY;
-
- /**
- * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
- * for an integer containing the network type.
- *
- * @see TelephonyManager#NETWORK_TYPE_UNKNOWN
- * @see TelephonyManager#NETWORK_TYPE_GPRS
- * @see TelephonyManager#NETWORK_TYPE_EDGE
- * @see TelephonyManager#NETWORK_TYPE_UMTS
- * @see TelephonyManager#NETWORK_TYPE_CDMA
- * @see TelephonyManager#NETWORK_TYPE_EVDO_0
- * @see TelephonyManager#NETWORK_TYPE_EVDO_A
- * @see TelephonyManager#NETWORK_TYPE_1xRTT
- * @see TelephonyManager#NETWORK_TYPE_HSDPA
- * @see TelephonyManager#NETWORK_TYPE_HSUPA
- * @see TelephonyManager#NETWORK_TYPE_HSPA
- * @see TelephonyManager#NETWORK_TYPE_IDEN
- * @see TelephonyManager#NETWORK_TYPE_EVDO_B
- * @see TelephonyManager#NETWORK_TYPE_LTE
- * @see TelephonyManager#NETWORK_TYPE_EHRPD
- * @see TelephonyManager#NETWORK_TYPE_HSPAP
- * @see TelephonyManager#NETWORK_TYPE_NR
- *
- * <p class="note">
- * Retrieve with
- * {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
- *
- * @hide
- */
- public static final String EXTRA_DATA_NETWORK_TYPE = PhoneConstants.DATA_NETWORK_TYPE_KEY;
-
- /**
* The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
* for an String containing the data APN type.
*
@@ -967,18 +789,6 @@
public static final String EXTRA_DATA_LINK_PROPERTIES_KEY = PhoneConstants.DATA_LINK_PROPERTIES_KEY;
/**
- * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
- * for the data connection fail cause.
- *
- * <p class="note">
- * Retrieve with
- * {@link android.content.Intent#getStringExtra(String name)}.
- *
- * @hide
- */
- public static final String EXTRA_DATA_FAILURE_CAUSE = PhoneConstants.DATA_FAILURE_CAUSE_KEY;
-
- /**
* Broadcast intent action for letting the default dialer to know to show voicemail
* notification.
*
@@ -1959,11 +1769,23 @@
/**
* Returns the Network Access Identifier (NAI). Return null if NAI is not available.
*
- * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
- * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+ * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+ * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
+ * managed profile on the device; for more details see <a
+ * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
+ * access is deprecated and will be removed in a future release.
+ *
+ * <ul>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app has the
+ * READ_PHONE_STATE permission then null is returned.</li>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+ * the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+ * higher, then a SecurityException is thrown.</li>
+ * </ul>
*/
- @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String getNai() {
return getNaiBySubscriberId(getSubId());
}
@@ -1971,6 +1793,21 @@
/**
* Returns the NAI. Return null if NAI is not available.
*
+ * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+ * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+ * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
+ * managed profile on the device; for more details see <a
+ * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
+ * access is deprecated and will be removed in a future release.
+ *
+ * <ul>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app has the
+ * READ_PHONE_STATE permission then null is returned.</li>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+ * the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+ * higher, then a SecurityException is thrown.</li>
+ * </ul>
+ *
* @param slotIndex of which Nai is returned
*/
/** {@hide}*/
@@ -2536,7 +2373,14 @@
* @return the lowercase 2 character ISO-3166 country code, or empty string if not available.
*/
public String getNetworkCountryIso() {
- return getNetworkCountryIso(getPhoneId());
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony == null) return "";
+ return telephony.getNetworkCountryIsoForPhone(getPhoneId(),
+ null /* no permission check */);
+ } catch (RemoteException ex) {
+ return "";
+ }
}
/**
@@ -2557,16 +2401,23 @@
*
* @return the lowercase 2 character ISO-3166 country code, or empty string if not available.
*
+ * @throws IllegalArgumentException when the slotIndex is invalid.
+ *
* {@hide}
*/
@SystemApi
@TestApi
@NonNull
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String getNetworkCountryIso(int slotIndex) {
try {
+ if (!SubscriptionManager.isValidSlotIndex(slotIndex)) {
+ throw new IllegalArgumentException("invalid slot index " + slotIndex);
+ }
+
ITelephony telephony = getITelephony();
if (telephony == null) return "";
- return telephony.getNetworkCountryIsoForPhone(slotIndex);
+ return telephony.getNetworkCountryIsoForPhone(slotIndex, getOpPackageName());
} catch (RemoteException ex) {
return "";
}
@@ -8008,17 +7859,25 @@
return Collections.EMPTY_LIST;
}
- /** @hide */
- public List<String> getPackagesWithCarrierPrivilegesForAllPhones() {
+ /**
+ * Get the names of packages with carrier privileges for all the active subscriptions.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @NonNull
+ public List<String> getCarrierPrivilegedPackagesForAllActiveSubscriptions() {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
return telephony.getPackagesWithCarrierPrivilegesForAllPhones();
}
} catch (RemoteException ex) {
- Rlog.e(TAG, "getPackagesWithCarrierPrivilegesForAllPhones RemoteException", ex);
+ Rlog.e(TAG, "getCarrierPrivilegedPackagesForAllActiveSubscriptions RemoteException",
+ ex);
} catch (NullPointerException ex) {
- Rlog.e(TAG, "getPackagesWithCarrierPrivilegesForAllPhones NPE", ex);
+ Rlog.e(TAG, "getCarrierPrivilegedPackagesForAllActiveSubscriptions NPE", ex);
}
return Collections.EMPTY_LIST;
}
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 60774e7..034fc22 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.content.ContentValues;
import android.database.Cursor;
-import android.hardware.radio.V1_4.ApnTypes;
+import android.hardware.radio.V1_5.ApnTypes;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -110,6 +110,8 @@
public static final int TYPE_EMERGENCY = ApnTypes.EMERGENCY;
/** APN type for MCX (Mission Critical Service) where X can be PTT/Video/Data */
public static final int TYPE_MCX = ApnTypes.MCX;
+ /** APN type for XCAP. */
+ public static final int TYPE_XCAP = ApnTypes.XCAP;
// Possible values for authentication types.
/** No authentication type. */
@@ -198,6 +200,7 @@
APN_TYPE_STRING_MAP.put("ia", TYPE_IA);
APN_TYPE_STRING_MAP.put("emergency", TYPE_EMERGENCY);
APN_TYPE_STRING_MAP.put("mcx", TYPE_MCX);
+ APN_TYPE_STRING_MAP.put("xcap", TYPE_XCAP);
APN_TYPE_INT_MAP = new ArrayMap<Integer, String>();
APN_TYPE_INT_MAP.put(TYPE_DEFAULT, "default");
APN_TYPE_INT_MAP.put(TYPE_MMS, "mms");
@@ -210,6 +213,7 @@
APN_TYPE_INT_MAP.put(TYPE_IA, "ia");
APN_TYPE_INT_MAP.put(TYPE_EMERGENCY, "emergency");
APN_TYPE_INT_MAP.put(TYPE_MCX, "mcx");
+ APN_TYPE_INT_MAP.put(TYPE_XCAP, "xcap");
PROTOCOL_STRING_MAP = new ArrayMap<String, Integer>();
PROTOCOL_STRING_MAP.put("IP", PROTOCOL_IP);
@@ -1944,8 +1948,9 @@
* {@link ApnSetting} built from this builder otherwise.
*/
public ApnSetting build() {
- if ((mApnTypeBitmask & (TYPE_DEFAULT | TYPE_MMS | TYPE_SUPL | TYPE_DUN | TYPE_HIPRI |
- TYPE_FOTA | TYPE_IMS | TYPE_CBS | TYPE_IA | TYPE_EMERGENCY | TYPE_MCX)) == 0
+ if ((mApnTypeBitmask & (TYPE_DEFAULT | TYPE_MMS | TYPE_SUPL | TYPE_DUN | TYPE_HIPRI
+ | TYPE_FOTA | TYPE_IMS | TYPE_CBS | TYPE_IA | TYPE_EMERGENCY | TYPE_MCX
+ | TYPE_XCAP)) == 0
|| TextUtils.isEmpty(mApnName) || TextUtils.isEmpty(mEntryName)) {
return null;
}
diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java
index 30c209b..96a5a81 100644
--- a/telephony/java/android/telephony/data/DataProfile.java
+++ b/telephony/java/android/telephony/data/DataProfile.java
@@ -22,7 +22,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.Annotation.ApnType;
@@ -31,6 +30,7 @@
import android.text.TextUtils;
import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.util.TelephonyUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -261,7 +261,7 @@
@Override
public String toString() {
return "DataProfile=" + mProfileId + "/" + mProtocolType + "/" + mAuthType
- + "/" + (Build.IS_USER ? "***/***/***" :
+ + "/" + (TelephonyUtils.IS_USER ? "***/***/***" :
(mApn + "/" + mUserName + "/" + mPassword)) + "/" + mType + "/"
+ mMaxConnectionsTime + "/" + mMaxConnections + "/"
+ mWaitTime + "/" + mEnabled + "/" + mSupportedApnTypesBitmask + "/"
diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java
index 47c4681..5adc99e 100644
--- a/telephony/java/android/telephony/ims/ImsCallSession.java
+++ b/telephony/java/android/telephony/ims/ImsCallSession.java
@@ -1173,18 +1173,8 @@
public void callSessionMergeComplete(IImsCallSession newSession) {
if (mListener != null) {
if (newSession != null) {
- // Check if the active session is the same session that was
- // active before the merge request was sent.
- ImsCallSession validActiveSession = ImsCallSession.this;
- try {
- if (!Objects.equals(miSession.getCallId(), newSession.getCallId())) {
- // New session created after conference
- validActiveSession = new ImsCallSession(newSession);
- }
- } catch (RemoteException rex) {
- Log.e(TAG, "callSessionMergeComplete: exception for getCallId!");
- }
- mListener.callSessionMergeComplete(validActiveSession);
+ // New session created after conference
+ mListener.callSessionMergeComplete(new ImsCallSession(newSession));
} else {
// Session already exists. Hence no need to pass
mListener.callSessionMergeComplete(null);
diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java
index 76b214b..f4b2cef 100644
--- a/telephony/java/android/telephony/ims/ImsReasonInfo.java
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java
@@ -889,6 +889,12 @@
*/
public static final int CODE_WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION = 1623;
+ /**
+ * The dialed RTT call should be retried without RTT
+ * @hide
+ */
+ public static final int CODE_RETRY_ON_IMS_WITHOUT_RTT = 3001;
+
/*
* OEM specific error codes. To be used by OEMs when they don't want to reveal error code which
* would be replaced by ERROR_UNSPECIFIED.
@@ -1069,6 +1075,7 @@
CODE_REJECT_VT_AVPF_NOT_ALLOWED,
CODE_REJECT_ONGOING_ENCRYPTED_CALL,
CODE_REJECT_ONGOING_CS_CALL,
+ CODE_RETRY_ON_IMS_WITHOUT_RTT,
CODE_OEM_CAUSE_1,
CODE_OEM_CAUSE_2,
CODE_OEM_CAUSE_3,
diff --git a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
index d4ed923..0630454 100644
--- a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
@@ -31,7 +31,7 @@
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
+import com.android.internal.telephony.util.ArrayUtils;
import com.android.server.SystemConfig;
import java.util.ArrayList;
diff --git a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
index 8e50a8f..4e79660 100644
--- a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
+++ b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
@@ -26,7 +26,7 @@
@UnsupportedAppUsage
PersistableBundle getConfigForSubId(int subId, String callingPackage);
- void overrideConfig(int subId, in PersistableBundle overrides);
+ void overrideConfig(int subId, in PersistableBundle overrides, boolean persistent);
void notifyConfigChangedForSubId(int subId);
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index c1d700a..91aa3ce 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -19,7 +19,6 @@
import android.app.PendingIntent;
import android.net.Uri;
import android.os.Bundle;
-import android.telephony.IFinancialSmsCallback;
import com.android.internal.telephony.SmsRawData;
/**
@@ -570,17 +569,6 @@
int subId, String callingPkg, String prefixes, in PendingIntent intent);
/**
- * Get sms inbox messages for the calling financial app.
- *
- * @param subId the SIM id.
- * @param callingPkg the package name of the calling app.
- * @param params parameters to filter the sms messages.
- * @param callback the callback interface to deliver the result.
- */
- void getSmsMessagesForFinancialApp(
- int subId, String callingPkg, in Bundle params, in IFinancialSmsCallback callback);
-
- /**
* Check if the destination is a possible premium short code.
*
* @param destAddress the destination address to test for possible short code
diff --git a/telephony/java/com/android/internal/telephony/ISmsImplBase.java b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
index ff816f2..d9d4b60 100644
--- a/telephony/java/com/android/internal/telephony/ISmsImplBase.java
+++ b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
@@ -19,7 +19,6 @@
import android.app.PendingIntent;
import android.net.Uri;
import android.os.Bundle;
-import android.telephony.IFinancialSmsCallback;
import java.util.List;
@@ -198,12 +197,6 @@
}
@Override
- public void getSmsMessagesForFinancialApp(
- int subId, String callingPkg, Bundle params, IFinancialSmsCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
public int checkSmsShortCodeDestination(
int subid, String callingApk, String destAddress, String countryIso) {
throw new UnsupportedOperationException();
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index eedfc6a..3264c751 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -301,7 +301,7 @@
* operator's MCC (Mobile Country Code).
* @see android.telephony.TelephonyManager#getNetworkCountryIso
*/
- String getNetworkCountryIsoForPhone(int phoneId);
+ String getNetworkCountryIsoForPhone(int phoneId, String callingPkg);
/**
* Returns the neighboring cell information of the device.
diff --git a/telephony/java/com/android/internal/telephony/IccCardConstants.java b/telephony/java/com/android/internal/telephony/IccCardConstants.java
index 6ff27b1..25f03c2 100644
--- a/telephony/java/com/android/internal/telephony/IccCardConstants.java
+++ b/telephony/java/com/android/internal/telephony/IccCardConstants.java
@@ -15,6 +15,7 @@
*/
package com.android.internal.telephony;
+import android.content.Intent;
import android.telephony.TelephonyManager;
import dalvik.annotation.compat.UnsupportedAppUsage;
@@ -25,37 +26,38 @@
public class IccCardConstants {
/* The extra data for broadcasting intent INTENT_ICC_STATE_CHANGE */
- public static final String INTENT_KEY_ICC_STATE = "ss";
+ public static final String INTENT_KEY_ICC_STATE = Intent.EXTRA_SIM_STATE;
/* UNKNOWN means the ICC state is unknown */
- public static final String INTENT_VALUE_ICC_UNKNOWN = "UNKNOWN";
+ public static final String INTENT_VALUE_ICC_UNKNOWN = Intent.SIM_STATE_UNKNOWN;
/* NOT_READY means the ICC interface is not ready (eg, radio is off or powering on) */
- public static final String INTENT_VALUE_ICC_NOT_READY = "NOT_READY";
+ public static final String INTENT_VALUE_ICC_NOT_READY = Intent.SIM_STATE_NOT_READY;
/* ABSENT means ICC is missing */
- public static final String INTENT_VALUE_ICC_ABSENT = "ABSENT";
+ public static final String INTENT_VALUE_ICC_ABSENT = Intent.SIM_STATE_ABSENT;
/* PRESENT means ICC is present */
- public static final String INTENT_VALUE_ICC_PRESENT = "PRESENT";
+ public static final String INTENT_VALUE_ICC_PRESENT = Intent.SIM_STATE_PRESENT;
/* CARD_IO_ERROR means for three consecutive times there was SIM IO error */
- static public final String INTENT_VALUE_ICC_CARD_IO_ERROR = "CARD_IO_ERROR";
+ static public final String INTENT_VALUE_ICC_CARD_IO_ERROR = Intent.SIM_STATE_CARD_IO_ERROR;
/* CARD_RESTRICTED means card is present but not usable due to carrier restrictions */
- static public final String INTENT_VALUE_ICC_CARD_RESTRICTED = "CARD_RESTRICTED";
+ static public final String INTENT_VALUE_ICC_CARD_RESTRICTED = Intent.SIM_STATE_CARD_RESTRICTED;
/* LOCKED means ICC is locked by pin or by network */
- public static final String INTENT_VALUE_ICC_LOCKED = "LOCKED";
+ public static final String INTENT_VALUE_ICC_LOCKED = Intent.SIM_STATE_LOCKED;
/* READY means ICC is ready to access */
- public static final String INTENT_VALUE_ICC_READY = "READY";
+ public static final String INTENT_VALUE_ICC_READY = Intent.SIM_STATE_READY;
/* IMSI means ICC IMSI is ready in property */
- public static final String INTENT_VALUE_ICC_IMSI = "IMSI";
+ public static final String INTENT_VALUE_ICC_IMSI = Intent.SIM_STATE_IMSI;
/* LOADED means all ICC records, including IMSI, are loaded */
- public static final String INTENT_VALUE_ICC_LOADED = "LOADED";
+ public static final String INTENT_VALUE_ICC_LOADED = Intent.SIM_STATE_LOADED;
/* The extra data for broadcasting intent INTENT_ICC_STATE_CHANGE */
- public static final String INTENT_KEY_LOCKED_REASON = "reason";
+ public static final String INTENT_KEY_LOCKED_REASON = Intent.EXTRA_SIM_LOCKED_REASON;
/* PIN means ICC is locked on PIN1 */
- public static final String INTENT_VALUE_LOCKED_ON_PIN = "PIN";
+ public static final String INTENT_VALUE_LOCKED_ON_PIN = Intent.SIM_LOCKED_ON_PIN;
/* PUK means ICC is locked on PUK1 */
- public static final String INTENT_VALUE_LOCKED_ON_PUK = "PUK";
+ public static final String INTENT_VALUE_LOCKED_ON_PUK = Intent.SIM_LOCKED_ON_PUK;
/* NETWORK means ICC is locked on NETWORK PERSONALIZATION */
- public static final String INTENT_VALUE_LOCKED_NETWORK = "NETWORK";
+ public static final String INTENT_VALUE_LOCKED_NETWORK = Intent.SIM_LOCKED_NETWORK;
/* PERM_DISABLED means ICC is permanently disabled due to puk fails */
- public static final String INTENT_VALUE_ABSENT_ON_PERM_DISABLED = "PERM_DISABLED";
+ public static final String INTENT_VALUE_ABSENT_ON_PERM_DISABLED =
+ Intent.SIM_ABSENT_ON_PERM_DISABLED;
/**
* This is combination of IccCardStatus.CardState and IccCardApplicationStatus.AppState
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index e4397cd..6e63514 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -161,6 +161,8 @@
public static final String APN_TYPE_EMERGENCY = "emergency";
/** APN type for Mission Critical Services */
public static final String APN_TYPE_MCX = "mcx";
+ /** APN type for XCAP */
+ public static final String APN_TYPE_XCAP = "xcap";
/** Array of all APN types */
public static final String[] APN_TYPES = {APN_TYPE_DEFAULT,
APN_TYPE_MMS,
@@ -172,7 +174,8 @@
APN_TYPE_CBS,
APN_TYPE_IA,
APN_TYPE_EMERGENCY,
- APN_TYPE_MCX
+ APN_TYPE_MCX,
+ APN_TYPE_XCAP,
};
public static final int RIL_CARD_MAX_APPS = 8;
@@ -189,10 +192,6 @@
public static final String SLOT_KEY = "slot";
- /** Fired when a subscriptions phone state changes. */
- public static final String ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED =
- "android.intent.action.SUBSCRIPTION_PHONE_STATE";
-
// FIXME: This is used to pass a subId via intents, we need to look at its usage, which is
// FIXME: extensive, and see if this should be an array of all active subId's or ...?
/**
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 03ea920..4421c77 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -485,6 +485,8 @@
int RIL_REQUEST_EMERGENCY_DIAL = 205;
int RIL_REQUEST_GET_PHONE_CAPABILITY = 206;
int RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG = 207;
+ int RIL_REQUEST_ENABLE_UICC_APPLICATIONS = 208;
+ int RIL_REQUEST_GET_UICC_APPLICATIONS_ENABLEMENT = 209;
/* Responses begin */
int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
@@ -548,4 +550,5 @@
int RIL_UNSOL_ICC_SLOT_STATUS = 1100;
int RIL_UNSOL_PHYSICAL_CHANNEL_CONFIG = 1101;
int RIL_UNSOL_EMERGENCY_NUMBER_LIST = 1102;
+ int RIL_UNSOL_UICC_APPLICATIONS_ENABLEMENT_CHANGED = 1103;
}
diff --git a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
index 2cdf2f6..dcea9bb 100644
--- a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
+++ b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
@@ -23,7 +23,7 @@
import android.util.SparseIntArray;
import com.android.internal.telephony.cdma.sms.UserData;
-import com.android.internal.util.XmlUtils;
+import com.android.internal.telephony.util.XmlUtils;
import dalvik.annotation.compat.UnsupportedAppUsage;
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 8b62872..b2c3fc7 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -240,25 +240,6 @@
*/
public static final String ACTION_NETWORK_SET_TIME = "android.intent.action.NETWORK_SET_TIME";
-
- /**
- * Broadcast Action: The timezone was set by the carrier (typically by the NITZ string).
- * This is a sticky broadcast.
- * The intent will have the following extra values:</p>
- * <ul>
- * <li><em>time-zone</em> - The java.util.TimeZone.getID() value identifying the new time
- * zone.</li>
- * </ul>
- *
- * <p class="note">
- * Requires the READ_PHONE_STATE permission.
- *
- * <p class="note">This is a protected intent that can only be sent
- * by the system.
- */
- public static final String ACTION_NETWORK_SET_TIMEZONE
- = "android.intent.action.NETWORK_SET_TIMEZONE";
-
/**
* <p>Broadcast Action: It indicates the Emergency callback mode blocks datacall/sms
* <p class="note">.
diff --git a/telephony/java/com/android/internal/telephony/util/ArrayUtils.java b/telephony/java/com/android/internal/telephony/util/ArrayUtils.java
new file mode 100644
index 0000000..2905125
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/util/ArrayUtils.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.telephony.util;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.lang.reflect.Array;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Objects;
+
+/** Utility methods for array operations. */
+public final class ArrayUtils {
+ private ArrayUtils() { /* cannot be instantiated */ }
+
+ /**
+ * Adds value to given array if not already present, providing set-like behavior.
+ */
+ @SuppressWarnings("unchecked")
+ public static @NonNull <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element) {
+ return appendElement(kind, array, element, false);
+ }
+
+ /**
+ * Adds value to given array.
+ */
+ @SuppressWarnings("unchecked")
+ public static @NonNull <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element,
+ boolean allowDuplicates) {
+ final T[] result;
+ final int end;
+ if (array != null) {
+ if (!allowDuplicates && contains(array, element)) return array;
+ end = array.length;
+ result = (T[]) Array.newInstance(kind, end + 1);
+ System.arraycopy(array, 0, result, 0, end);
+ } else {
+ end = 0;
+ result = (T[]) Array.newInstance(kind, 1);
+ }
+ result[end] = element;
+ return result;
+ }
+
+ /**
+ * Combine multiple arrays into a single array.
+ *
+ * @param kind The class of the array elements
+ * @param arrays The arrays to combine
+ * @param <T> The class of the array elements (inferred from kind).
+ * @return A single array containing all the elements of the parameter arrays.
+ */
+ @SuppressWarnings("unchecked")
+ public static @NonNull <T> T[] concatElements(Class<T> kind, @Nullable T[]... arrays) {
+ if (arrays == null || arrays.length == 0) {
+ return createEmptyArray(kind);
+ }
+
+ int totalLength = 0;
+ for (T[] item : arrays) {
+ if (item == null) {
+ continue;
+ }
+
+ totalLength += item.length;
+ }
+
+ // Optimization for entirely empty arrays.
+ if (totalLength == 0) {
+ return createEmptyArray(kind);
+ }
+
+ final T[] all = (T[]) Array.newInstance(kind, totalLength);
+ int pos = 0;
+ for (T[] item : arrays) {
+ if (item == null || item.length == 0) {
+ continue;
+ }
+ System.arraycopy(item, 0, all, pos, item.length);
+ pos += item.length;
+ }
+ return all;
+ }
+
+ private static @NonNull <T> T[] createEmptyArray(Class<T> kind) {
+ if (kind == String.class) {
+ return (T[]) EmptyArray.STRING;
+ } else if (kind == Object.class) {
+ return (T[]) EmptyArray.OBJECT;
+ }
+
+ return (T[]) Array.newInstance(kind, 0);
+ }
+
+ private static final class EmptyArray {
+ private EmptyArray() {}
+
+ public static final Object[] OBJECT = new Object[0];
+ public static final String[] STRING = new String[0];
+ }
+
+ /**
+ * Checks if {@code value} is in {@code array}.
+ */
+ public static boolean contains(@Nullable char[] array, char value) {
+ if (array == null) return false;
+ for (char element : array) {
+ if (element == value) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks if {@code value} is in {@code array}.
+ */
+ public static <T> boolean contains(@Nullable Collection<T> cur, T val) {
+ return (cur != null) ? cur.contains(val) : false;
+ }
+
+ /**
+ * Checks if {@code value} is in {@code array}.
+ */
+ public static boolean contains(@Nullable int[] array, int value) {
+ if (array == null) return false;
+ for (int element : array) {
+ if (element == value) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks if {@code value} is in {@code array}.
+ */
+ public static boolean contains(@Nullable long[] array, long value) {
+ if (array == null) return false;
+ for (long element : array) {
+ if (element == value) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks if {@code value} is in {@code array}.
+ */
+ public static <T> boolean contains(@Nullable T[] array, T value) {
+ return indexOf(array, value) != -1;
+ }
+
+ /**
+ * Return first index of {@code value} in {@code array}, or {@code -1} if
+ * not found.
+ */
+ public static <T> int indexOf(@Nullable T[] array, T value) {
+ if (array == null) return -1;
+ for (int i = 0; i < array.length; i++) {
+ if (Objects.equals(array[i], value)) return i;
+ }
+ return -1;
+ }
+
+ /**
+ * Checks if given array is null or has zero elements.
+ */
+ public static boolean isEmpty(@Nullable Collection<?> array) {
+ return array == null || array.isEmpty();
+ }
+
+ /**
+ * Checks if given map is null or has zero elements.
+ */
+ public static boolean isEmpty(@Nullable Map<?, ?> map) {
+ return map == null || map.isEmpty();
+ }
+
+ /**
+ * Checks if given array is null or has zero elements.
+ */
+ public static <T> boolean isEmpty(@Nullable T[] array) {
+ return array == null || array.length == 0;
+ }
+
+ /**
+ * Checks if given array is null or has zero elements.
+ */
+ public static boolean isEmpty(@Nullable int[] array) {
+ return array == null || array.length == 0;
+ }
+
+ /**
+ * Checks if given array is null or has zero elements.
+ */
+ public static boolean isEmpty(@Nullable long[] array) {
+ return array == null || array.length == 0;
+ }
+
+ /**
+ * Checks if given array is null or has zero elements.
+ */
+ public static boolean isEmpty(@Nullable byte[] array) {
+ return array == null || array.length == 0;
+ }
+
+ /**
+ * Checks if given array is null or has zero elements.
+ */
+ public static boolean isEmpty(@Nullable boolean[] array) {
+ return array == null || array.length == 0;
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java
new file mode 100644
index 0000000..a28d65c
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.telephony.util;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.ComponentInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+
+import java.io.PrintWriter;
+
+/**
+ * This class provides various util functions
+ */
+public final class TelephonyUtils {
+ public static boolean IS_USER = "user".equals(android.os.Build.TYPE);
+ public static boolean IS_DEBUGGABLE = SystemProperties.getInt("ro.debuggable", 0) == 1;
+
+ /**
+ * Verify that caller holds {@link android.Manifest.permission#DUMP}.
+ *
+ * @return true if access should be granted.
+ */
+ public static boolean checkDumpPermission(Context context, String tag, PrintWriter pw) {
+ if (context.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump " + tag + " from from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+ + " due to missing android.permission.DUMP permission");
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /** Returns an empty string if the input is {@code null}. */
+ public static String emptyIfNull(@Nullable String str) {
+ return str == null ? "" : str;
+ }
+
+ /** Throws a {@link RuntimeException} that wrapps the {@link RemoteException}. */
+ public static RuntimeException rethrowAsRuntimeException(RemoteException remoteException) {
+ throw new RuntimeException(remoteException);
+ }
+
+ /**
+ * Returns a {@link ComponentInfo} from the {@link ResolveInfo},
+ * or throws an {@link IllegalStateException} if not available.
+ */
+ public static ComponentInfo getComponentInfo(@NonNull ResolveInfo resolveInfo) {
+ if (resolveInfo.activityInfo != null) return resolveInfo.activityInfo;
+ if (resolveInfo.serviceInfo != null) return resolveInfo.serviceInfo;
+ if (resolveInfo.providerInfo != null) return resolveInfo.providerInfo;
+ throw new IllegalStateException("Missing ComponentInfo!");
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/util/XmlUtils.java b/telephony/java/com/android/internal/telephony/util/XmlUtils.java
new file mode 100644
index 0000000..72c5d3a
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/util/XmlUtils.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.util;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/** Utility methods for XML operations. */
+public final class XmlUtils {
+ private XmlUtils() {}
+
+ /**
+ * Moves parser to the first start tag, and expects the tag name being {@code firstElementName}.
+ */
+ public static void beginDocument(XmlPullParser parser, String firstElementName)
+ throws XmlPullParserException, IOException {
+ int type;
+ while ((type = parser.next()) != parser.START_TAG && type != parser.END_DOCUMENT) {
+ // no-op
+ }
+
+ if (type != parser.START_TAG) {
+ throw new XmlPullParserException("No start tag found");
+ }
+
+ if (!parser.getName().equals(firstElementName)) {
+ throw new XmlPullParserException("Unexpected start tag: found " + parser.getName()
+ + ", expected " + firstElementName);
+ }
+ }
+
+ /**
+ * Moves parser to the next start tag.
+ */
+ public static void nextElement(XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ int type;
+ while ((type = parser.next()) != parser.START_TAG && type != parser.END_DOCUMENT) {
+ // no-op
+ }
+ }
+
+ /**
+ * Moves parser to the next start tag within the {@code outerDepth}.
+ */
+ public static boolean nextElementWithin(XmlPullParser parser, int outerDepth)
+ throws IOException, XmlPullParserException {
+ for (;;) {
+ int type = parser.next();
+ if (type == XmlPullParser.END_DOCUMENT
+ || (type == XmlPullParser.END_TAG && parser.getDepth() == outerDepth)) {
+ return false;
+ }
+ if (type == XmlPullParser.START_TAG && parser.getDepth() == outerDepth + 1) {
+ return true;
+ }
+ }
+ }
+}
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index aa4174a..616b6b0 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -30,6 +30,7 @@
libs: [
"framework-all",
"app-compat-annotations",
+ "unsupportedappusage",
],
api_packages: [
diff --git a/tests/FlickerTests/AndroidTest.xml b/tests/FlickerTests/AndroidTest.xml
index d433df5..d1da47f 100644
--- a/tests/FlickerTests/AndroidTest.xml
+++ b/tests/FlickerTests/AndroidTest.xml
@@ -25,6 +25,6 @@
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
<option name="directory-keys" value="/sdcard/flicker" />
<option name="collect-on-run-ended-only" value="true" />
- <option name="clean-up" value="false" />
+ <option name="clean-up" value="true" />
</metrics_collector>
</configuration>