diff options
38 files changed, 882 insertions, 62 deletions
diff --git a/Android.bp b/Android.bp index fe4fdb2a502e..8023fc5dcaf9 100644 --- a/Android.bp +++ b/Android.bp @@ -544,6 +544,7 @@ java_defaults { "telephony/java/com/android/internal/telephony/IApnSourceService.aidl", "telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl", "telephony/java/com/android/internal/telephony/IMms.aidl", + "telephony/java/com/android/internal/telephony/INumberVerificationCallback.aidl", "telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl", "telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl", "telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl", @@ -675,6 +676,7 @@ java_defaults { ], static_libs: [ + "apex_aidl_interface-java", "framework-protos", "android.hidl.base-V1.0-java", "android.hardware.cas-V1.0-java", diff --git a/api/current.txt b/api/current.txt index b9615e0c2af3..31a5443a4e84 100755 --- a/api/current.txt +++ b/api/current.txt @@ -11012,6 +11012,7 @@ package android.content.pm { field public int[] gids; field public int installLocation; field public android.content.pm.InstrumentationInfo[] instrumentation; + field public boolean isApex; field public long lastUpdateTime; field public java.lang.String packageName; field public android.content.pm.PermissionInfo[] permissions; @@ -11390,6 +11391,7 @@ package android.content.pm { field public static final int INSTALL_REASON_UNKNOWN = 0; // 0x0 field public static final int INSTALL_REASON_USER = 4; // 0x4 field public static final int MATCH_ALL = 131072; // 0x20000 + field public static final int MATCH_APEX = 1073741824; // 0x40000000 field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000 field public static final int MATCH_DIRECT_BOOT_AWARE = 524288; // 0x80000 field public static final int MATCH_DIRECT_BOOT_UNAWARE = 262144; // 0x40000 diff --git a/api/system-current.txt b/api/system-current.txt index 945dbf10f469..966cb328723c 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4471,8 +4471,8 @@ package android.service.carrier { public abstract class ApnService extends android.app.Service { ctor public ApnService(); - method public abstract java.util.List<android.content.ContentValues> onRestoreApns(int); method public android.os.IBinder onBind(android.content.Intent); + method public abstract java.util.List<android.content.ContentValues> onRestoreApns(int); } } @@ -5186,6 +5186,26 @@ package android.telephony { field public static final int RESULT_SUCCESS = 0; // 0x0 } + public abstract interface NumberVerificationCallback { + method public default void onCallReceived(java.lang.String); + method public default void onVerificationFailed(int); + field public static final int REASON_CONCURRENT_REQUESTS = 4; // 0x4 + field public static final int REASON_IN_ECBM = 5; // 0x5 + field public static final int REASON_IN_EMERGENCY_CALL = 6; // 0x6 + field public static final int REASON_NETWORK_NOT_AVAILABLE = 2; // 0x2 + field public static final int REASON_TIMED_OUT = 1; // 0x1 + field public static final int REASON_TOO_MANY_CALLS = 3; // 0x3 + field public static final int REASON_UNSPECIFIED = 0; // 0x0 + } + + public final class PhoneNumberRange implements android.os.Parcelable { + ctor public PhoneNumberRange(java.lang.String, java.lang.String, java.lang.String, java.lang.String); + method public int describeContents(); + method public boolean matches(java.lang.String); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.telephony.PhoneNumberRange> CREATOR; + } + public class PhoneStateListener { method public void onRadioPowerStateChanged(int); method public void onSrvccStateChanged(int); @@ -5350,6 +5370,7 @@ package android.telephony { method public boolean needsOtaServiceProvisioning(); method public boolean rebootRadio(); method public void requestCellInfoUpdate(android.os.WorkSource, java.util.concurrent.Executor, android.telephony.TelephonyManager.CellInfoCallback); + method public void requestNumberVerification(android.telephony.PhoneNumberRange, long, java.util.concurrent.Executor, android.telephony.NumberVerificationCallback); method public boolean resetRadioConfig(); method public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>); method public void setCarrierDataEnabled(boolean); @@ -5379,6 +5400,7 @@ package android.telephony { field public static final java.lang.String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE"; field public static final java.lang.String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL"; field public static final java.lang.String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING"; + field public static final long MAX_NUMBER_VERIFICATION_TIMEOUT_MILLIS = 60000L; // 0xea60L field public static final int NETWORK_MODE_CDMA_EVDO = 4; // 0x4 field public static final int NETWORK_MODE_CDMA_NO_EVDO = 5; // 0x5 field public static final int NETWORK_MODE_EVDO_NO_CDMA = 6; // 0x6 diff --git a/cmds/telecom/src/com/android/commands/telecom/Telecom.java b/cmds/telecom/src/com/android/commands/telecom/Telecom.java index 8e9b91dab95d..f3bf6e7b7231 100644 --- a/cmds/telecom/src/com/android/commands/telecom/Telecom.java +++ b/cmds/telecom/src/com/android/commands/telecom/Telecom.java @@ -46,6 +46,10 @@ public final class Telecom extends BaseCommand { private static final String COMMAND_SET_PHONE_ACCOUNT_DISABLED = "set-phone-account-disabled"; private static final String COMMAND_REGISTER_PHONE_ACCOUNT = "register-phone-account"; private static final String COMMAND_REGISTER_SIM_PHONE_ACCOUNT = "register-sim-phone-account"; + private static final String COMMAND_SET_TEST_CALL_SCREENING_APP = "set-test-call-screening-app"; + private static final String COMMAND_ADD_OR_REMOVE_CALL_COMPANION_APP = + "add-or-remove-call-companion-app"; + private static final String COMMAND_SET_TEST_AUTO_MODE_APP = "set-test-auto-mode-app"; private static final String COMMAND_UNREGISTER_PHONE_ACCOUNT = "unregister-phone-account"; private static final String COMMAND_SET_DEFAULT_DIALER = "set-default-dialer"; private static final String COMMAND_GET_DEFAULT_DIALER = "get-default-dialer"; @@ -64,6 +68,9 @@ public final class Telecom extends BaseCommand { "usage: telecom set-phone-account-enabled <COMPONENT> <ID> <USER_SN>\n" + "usage: telecom set-phone-account-disabled <COMPONENT> <ID> <USER_SN>\n" + "usage: telecom register-phone-account <COMPONENT> <ID> <USER_SN> <LABEL>\n" + + "usage: telecom set-test-call-screening-app <PACKAGE>\n" + + "usage: telecom set-test-auto-mode-app <PACKAGE>\n" + + "usage: telecom add-or-remove-call-companion-app <PACKAGE> <1/0>\n" + "usage: telecom register-sim-phone-account <COMPONENT> <ID> <USER_SN> <LABEL> <ADDRESS>\n" + "usage: telecom unregister-phone-account <COMPONENT> <ID> <USER_SN>\n" + "usage: telecom set-default-dialer <PACKAGE>\n" + @@ -113,6 +120,15 @@ public final class Telecom extends BaseCommand { case COMMAND_REGISTER_PHONE_ACCOUNT: runRegisterPhoneAccount(); break; + case COMMAND_SET_TEST_CALL_SCREENING_APP: + runSetTestCallScreeningApp(); + break; + case COMMAND_ADD_OR_REMOVE_CALL_COMPANION_APP: + runAddOrRemoveCallCompanionApp(); + break; + case COMMAND_SET_TEST_AUTO_MODE_APP: + runSetTestAutoModeApp(); + break; case COMMAND_REGISTER_SIM_PHONE_ACCOUNT: runRegisterSimPhoneAccount(); break; @@ -173,6 +189,23 @@ public final class Telecom extends BaseCommand { System.out.println("Success - " + handle + " registered."); } + private void runSetTestCallScreeningApp() throws RemoteException { + final String packageName = nextArg(); + mTelecomService.setTestDefaultCallScreeningApp(packageName); + } + + private void runAddOrRemoveCallCompanionApp() throws RemoteException { + final String packageName = nextArgRequired(); + String isAdded = nextArgRequired(); + boolean isAddedBool = "1".equals(isAdded); + mTelecomService.addOrRemoveTestCallCompanionApp(packageName, isAddedBool); + } + + private void runSetTestAutoModeApp() throws RemoteException { + final String packageName = nextArg(); + mTelecomService.setTestAutoModeApp(packageName); + } + private void runUnregisterPhoneAccount() throws RemoteException { final PhoneAccountHandle handle = getPhoneAccountHandleFromArgs(); mTelecomService.unregisterPhoneAccount(handle); diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt index ab7b24867026..da5c98848254 100644 --- a/config/hiddenapi-light-greylist.txt +++ b/config/hiddenapi-light-greylist.txt @@ -2773,7 +2773,6 @@ Lcom/android/internal/telephony/dataconnection/DcTracker;->onRecordsLoadedOrSubI Lcom/android/internal/telephony/dataconnection/DcTracker;->onSetUserDataEnabled(Z)V Lcom/android/internal/telephony/dataconnection/DcTracker;->onTrySetupData(Lcom/android/internal/telephony/dataconnection/ApnContext;)Z Lcom/android/internal/telephony/dataconnection/DcTracker;->onTrySetupData(Ljava/lang/String;)Z -Lcom/android/internal/telephony/dataconnection/DcTracker;->registerForAllDataDisconnected(Landroid/os/Handler;ILjava/lang/Object;)V Lcom/android/internal/telephony/dataconnection/DcTracker;->registerSettingsObserver()V Lcom/android/internal/telephony/dataconnection/DcTracker;->resetPollStats()V Lcom/android/internal/telephony/dataconnection/DcTracker;->restartDataStallAlarm()V @@ -2787,7 +2786,6 @@ Lcom/android/internal/telephony/dataconnection/DcTracker;->startNetStatPoll()V Lcom/android/internal/telephony/dataconnection/DcTracker;->stopDataStallAlarm()V Lcom/android/internal/telephony/dataconnection/DcTracker;->stopNetStatPoll()V Lcom/android/internal/telephony/dataconnection/DcTracker;->unregisterForAllDataDisconnected(Landroid/os/Handler;)V -Lcom/android/internal/telephony/dataconnection/DcTracker;->updateRecords()V Lcom/android/internal/telephony/DctConstants$Activity;->DATAIN:Lcom/android/internal/telephony/DctConstants$Activity; Lcom/android/internal/telephony/DctConstants$Activity;->DATAINANDOUT:Lcom/android/internal/telephony/DctConstants$Activity; Lcom/android/internal/telephony/DctConstants$Activity;->DATAOUT:Lcom/android/internal/telephony/DctConstants$Activity; @@ -3278,7 +3276,6 @@ Lcom/android/internal/telephony/Phone;->isVolteEnabled()Z Lcom/android/internal/telephony/Phone;->isWifiCallingEnabled()Z Lcom/android/internal/telephony/Phone;->mCi:Lcom/android/internal/telephony/CommandsInterface; Lcom/android/internal/telephony/Phone;->mContext:Landroid/content/Context; -Lcom/android/internal/telephony/Phone;->mDcTracker:Lcom/android/internal/telephony/dataconnection/DcTracker; Lcom/android/internal/telephony/Phone;->mIccRecords:Ljava/util/concurrent/atomic/AtomicReference; Lcom/android/internal/telephony/Phone;->mImsPhone:Lcom/android/internal/telephony/Phone; Lcom/android/internal/telephony/Phone;->mMmiRegistrants:Landroid/os/RegistrantList; @@ -3371,7 +3368,6 @@ Lcom/android/internal/telephony/ProxyController;->mOldRadioAccessFamily:[I Lcom/android/internal/telephony/ProxyController;->mRadioCapabilitySessionId:I Lcom/android/internal/telephony/ProxyController;->mSetRadioAccessFamilyStatus:[I Lcom/android/internal/telephony/ProxyController;->mUniqueIdGenerator:Ljava/util/concurrent/atomic/AtomicInteger; -Lcom/android/internal/telephony/ProxyController;->registerForAllDataDisconnected(ILandroid/os/Handler;ILjava/lang/Object;)V Lcom/android/internal/telephony/ProxyController;->sendRadioCapabilityRequest(IIIILjava/lang/String;II)V Lcom/android/internal/telephony/ProxyController;->sProxyController:Lcom/android/internal/telephony/ProxyController; Lcom/android/internal/telephony/RadioCapability;->getRadioAccessFamily()I @@ -3471,7 +3467,6 @@ Lcom/android/internal/telephony/ServiceStateTracker;->mVoiceRoamingOnRegistrants Lcom/android/internal/telephony/ServiceStateTracker;->notifyDataRegStateRilRadioTechnologyChanged()V Lcom/android/internal/telephony/ServiceStateTracker;->notifySignalStrength()Z Lcom/android/internal/telephony/ServiceStateTracker;->pollState()V -Lcom/android/internal/telephony/ServiceStateTracker;->powerOffRadioSafely(Lcom/android/internal/telephony/dataconnection/DcTracker;)V Lcom/android/internal/telephony/ServiceStateTracker;->reRegisterNetwork(Landroid/os/Message;)V Lcom/android/internal/telephony/ServiceStateTracker;->resetServiceStateInIwlanMode()V Lcom/android/internal/telephony/ServiceStateTracker;->setOperatorIdd(Ljava/lang/String;)V diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index a74e4d75a33c..cdacd1ecb95a 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -1766,7 +1766,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * is on the package whitelist. * * @param policy configured policy for this app, or {@link #HIDDEN_API_ENFORCEMENT_DEFAULT} - * if nothing configured. + * if nothing configured. * @hide */ public void maybeUpdateHiddenApiEnforcementPolicy(@HiddenApiEnforcementPolicy int policy) { diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java index d9d177760243..89e8608eec08 100644 --- a/core/java/android/content/pm/PackageInfo.java +++ b/core/java/android/content/pm/PackageInfo.java @@ -18,6 +18,7 @@ package android.content.pm; import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; +import android.apex.ApexInfo; import android.os.Parcel; import android.os.Parcelable; @@ -390,6 +391,11 @@ public class PackageInfo implements Parcelable { @Nullable public String compileSdkVersionCodename; + /** + * Whether the package is an APEX package. + */ + public boolean isApex; + public PackageInfo() { } @@ -472,6 +478,7 @@ public class PackageInfo implements Parcelable { } else { dest.writeInt(0); } + dest.writeBoolean(isApex); } public static final Parcelable.Creator<PackageInfo> CREATOR @@ -533,7 +540,7 @@ public class PackageInfo implements Parcelable { if (hasSigningInfo != 0) { signingInfo = SigningInfo.CREATOR.createFromParcel(source); } - + isApex = source.readBoolean(); // The component lists were flattened with the redundant ApplicationInfo // instances omitted. Distribute the canonical one here as appropriate. if (applicationInfo != null) { @@ -544,6 +551,15 @@ public class PackageInfo implements Parcelable { } } + /** + * @hide + */ + public PackageInfo(ApexInfo apexInfo) { + packageName = apexInfo.packageName; + setLongVersionCode(apexInfo.versionCode); + isApex = true; + } + private void propagateApplicationInfo(ApplicationInfo appInfo, ComponentInfo[] components) { if (components != null) { for (ComponentInfo ci : components) { diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 2597f1d53937..1394c358868c 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -145,6 +145,7 @@ public abstract class PackageManager { MATCH_FACTORY_ONLY, MATCH_DEBUG_TRIAGED_MISSING, MATCH_INSTANT, + MATCH_APEX, GET_DISABLED_COMPONENTS, GET_DISABLED_UNTIL_USED_COMPONENTS, GET_UNINSTALLED_PACKAGES, @@ -531,6 +532,17 @@ public abstract class PackageManager { public static final int MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS = 0x20000000; /** + * {@link PackageInfo} flag: include APEX packages that are currently + * installed. In APEX terminology, this corresponds to packages that are + * currently active, i.e. mounted and available to other processes of the OS. + * In particular, this flag alone will not match APEX files that are staged + * for activation at next reboot. + * TODO(b/119767311): include uninstalled/inactive APEX if + * MATCH_UNINSTALLED_PACKAGES is set. + */ + public static final int MATCH_APEX = 0x40000000; + + /** * Flag for {@link #addCrossProfileIntentFilter}: if this flag is set: when * resolving an intent that matches the {@code CrossProfileIntentFilter}, * the current profile will be skipped. Only activities in the target user @@ -846,6 +858,14 @@ public abstract class PackageManager { */ public static final int INSTALL_VIRTUAL_PRELOAD = 0x00010000; + /** + * Flag parameter for {@link #installPackage} to indicate that this package + * is an APEX package + * + * @hide + */ + public static final int INSTALL_APEX = 0x00020000; + /** @hide */ @IntDef(flag = true, prefix = { "DONT_KILL_APP" }, value = { DONT_KILL_APP diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 3326d1219e77..ec24980a2e6e 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -34,7 +34,6 @@ cc_library_shared { ], cppflags: ["-Wno-conversion-null"], - cpp_std: "c++17", srcs: [ "AndroidRuntime.cpp", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index f7f10c49fbae..b94ac9c29f9f 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -1052,12 +1052,18 @@ void AndroidRuntime::start(const char* className, const Vector<String8>& options if (rootDir == NULL) { rootDir = "/system"; if (!hasDir("/system")) { - LOG_FATAL("No root directory specified, and /android does not exist."); + LOG_FATAL("No root directory specified, and /system does not exist."); return; } setenv("ANDROID_ROOT", rootDir, 1); } + const char* runtimeRootDir = getenv("ANDROID_RUNTIME_ROOT"); + if (runtimeRootDir == NULL) { + LOG_FATAL("No runtime directory specified with ANDROID_RUNTIME_ROOT environment variable."); + return; + } + //const char* kernelHack = getenv("LD_ASSUME_KERNEL"); //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack); diff --git a/core/proto/android/service/runtime.proto b/core/proto/android/service/runtime.proto new file mode 100644 index 000000000000..ecbccef7a94c --- /dev/null +++ b/core/proto/android/service/runtime.proto @@ -0,0 +1,40 @@ +/* + * 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. + */ + +syntax = "proto2"; +package android.service.runtime; + +import "frameworks/base/libs/incident/proto/android/privacy.proto"; + +option java_multiple_files = true; +option java_outer_classname = "RuntimeServiceProto"; + +// Represents dumpsys info from RuntimeService. +message RuntimeServiceInfoProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + // Generic debug information to include. + repeated DebugEntryProto debug_entry = 1; +} + +// A piece of key / value debug information. +message DebugEntryProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional string key = 1; + + optional string string_value = 2; +} diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 6533eb9a2d87..0a5b56b30e66 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -9,8 +9,6 @@ cc_defaults { "hwui_lto", ], - cpp_std: "c++17", - cflags: [ "-DEGL_EGLEXT_PROTOTYPES", "-DGL_GLEXT_PROTOTYPES", diff --git a/media/OWNERS b/media/OWNERS index 182f661fcfff..03b751c07c6c 100644 --- a/media/OWNERS +++ b/media/OWNERS @@ -1,9 +1,13 @@ +chz@google.com +dwkang@google.com elaurent@google.com etalvala@google.com +gkasten@google.com +hunga@google.com +jaewan@google.com +jmtrivi@google.com +jsharkey@android.com lajos@google.com marcone@google.com sungsoo@google.com wjia@google.com -jaewan@google.com -chz@google.com - diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java index 2395b24f7136..5b8fbc4041ae 100644 --- a/media/java/android/media/ExifInterface.java +++ b/media/java/android/media/ExifInterface.java @@ -2545,13 +2545,18 @@ public class ExifInterface { if (size == 0) { return 0; } - // We don't allow read positions after the available bytes, - // the input stream won't be able to seek back then. - if (position < 0 || position >= in.available()) { + if (position < 0) { return -1; } try { if (mPosition != position) { + // We don't allow seek to positions after the available bytes, + // the input stream won't be able to seek back then. + // However, if we hit an exception before (mPosition set to -1), + // let it try the seek in hope it might recover. + if (mPosition >= 0 && position >= mPosition + in.available()) { + return -1; + } in.seek(position); mPosition = position; } @@ -2559,8 +2564,8 @@ public class ExifInterface { // If the read will cause us to go over the available bytes, // reduce the size so that we stay in the available range. // Otherwise the input stream may not be able to seek back. - if (mPosition + size > in.available()) { - size = in.available() - (int)mPosition; + if (size > in.available()) { + size = in.available(); } int bytesRead = in.read(buffer, offset, size); diff --git a/packages/CarrierDefaultApp/OWNERS b/packages/CarrierDefaultApp/OWNERS index 7057ce6cb6fe..aef6a3cdf5c8 100644 --- a/packages/CarrierDefaultApp/OWNERS +++ b/packages/CarrierDefaultApp/OWNERS @@ -9,4 +9,5 @@ jackyu@google.com jminjie@google.com satk@google.com shuoq@google.com -refuhoo@google.com
\ No newline at end of file +refuhoo@google.com +nazaninb@google.com
\ No newline at end of file diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java index 4a9c35615131..8a5d1119696f 100644 --- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java @@ -222,7 +222,7 @@ public class ExternalStorageProvider extends FileSystemProvider { root.flags |= Root.FLAG_REMOVABLE_USB; } - if (!VolumeInfo.ID_EMULATED_INTERNAL.equals(volume.getId())) { + if (volume.getType() != VolumeInfo.TYPE_EMULATED) { root.flags |= Root.FLAG_SUPPORTS_EJECT; } diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 18f378e5919b..d9da10f2b43d 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -693,6 +693,8 @@ <string name="quick_settings_bluetooth_secondary_label_headset">Headset</string> <!-- QuickSettings: Bluetooth secondary label for an input/IO device being connected [CHAR LIMIT=20]--> <string name="quick_settings_bluetooth_secondary_label_input">Input</string> + <!-- QuickSettings: Bluetooth secondary label for a Hearing Aids device being connected [CHAR LIMIT=20]--> + <string name="quick_settings_bluetooth_secondary_label_hearing_aids">Hearing Aids</string> <!-- QuickSettings: Bluetooth secondary label shown when bluetooth is being enabled [CHAR LIMIT=NONE] --> <string name="quick_settings_bluetooth_secondary_label_transient">Turning on…</string> <!-- QuickSettings: Brightness [CHAR LIMIT=NONE] --> diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java index cd0031173f8b..22c42d4a6a57 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java @@ -207,7 +207,10 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { } else { final BluetoothClass bluetoothClass = lastDevice.getBtClass(); if (bluetoothClass != null) { - if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) { + if (lastDevice.isHearingAidDevice()) { + return mContext.getString( + R.string.quick_settings_bluetooth_secondary_label_hearing_aids); + } else if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) { return mContext.getString( R.string.quick_settings_bluetooth_secondary_label_audio); } else if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) { diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 7ee3d3b3bdc7..126bf6556538 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1236,7 +1236,8 @@ public class IpSecService extends IIpSecService.Stub { OsConstants.UDP_ENCAP, OsConstants.UDP_ENCAP_ESPINUDP); - mSrvConfig.getNetdInstance().ipSecSetEncapSocketOwner(sockFd, callingUid); + mSrvConfig.getNetdInstance().ipSecSetEncapSocketOwner( + new ParcelFileDescriptor(sockFd), callingUid); if (port != 0) { Log.v(TAG, "Binding to port " + port); Os.bind(sockFd, INADDR_ANY, port); @@ -1696,7 +1697,7 @@ public class IpSecService extends IIpSecService.Stub { mSrvConfig .getNetdInstance() .ipSecApplyTransportModeTransform( - socket.getFileDescriptor(), + socket, callingUid, direction, c.getSourceAddress(), @@ -1715,7 +1716,7 @@ public class IpSecService extends IIpSecService.Stub { throws RemoteException { mSrvConfig .getNetdInstance() - .ipSecRemoveTransportModeTransform(socket.getFileDescriptor()); + .ipSecRemoveTransportModeTransform(socket); } /** diff --git a/services/core/java/com/android/server/RuntimeService.java b/services/core/java/com/android/server/RuntimeService.java new file mode 100644 index 000000000000..ccfac80d22a7 --- /dev/null +++ b/services/core/java/com/android/server/RuntimeService.java @@ -0,0 +1,173 @@ +/* + * 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; + +import android.content.Context; +import android.os.Binder; +import android.service.runtime.DebugEntryProto; +import android.service.runtime.RuntimeServiceInfoProto; +import android.util.Slog; +import android.util.proto.ProtoOutputStream; + +import libcore.timezone.TimeZoneDataFiles; +import libcore.util.CoreLibraryDebug; +import libcore.util.DebugInfo; + +import com.android.internal.util.DumpUtils; +import com.android.timezone.distro.DistroException; +import com.android.timezone.distro.DistroVersion; +import com.android.timezone.distro.FileUtils; +import com.android.timezone.distro.TimeZoneDistro; + +import java.io.File; +import java.io.FileDescriptor; +import java.io.IOException; +import java.io.PrintWriter; + +/** + * This service exists only as a "dumpsys" target which reports information about the status of the + * runtime and related libraries. + */ +public class RuntimeService extends Binder { + + private static final String TAG = "RuntimeService"; + + private final Context mContext; + + public RuntimeService(Context context) { + mContext = context; + } + + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) { + return; + } + + boolean protoFormat = hasOption(args, "--proto"); + ProtoOutputStream proto = null; + + DebugInfo coreLibraryDebugInfo = CoreLibraryDebug.getDebugInfo(); + addTimeZoneApkDebugInfo(coreLibraryDebugInfo); + + if (protoFormat) { + proto = new ProtoOutputStream(fd); + reportTimeZoneInfoProto(coreLibraryDebugInfo, proto); + } else { + reportTimeZoneInfo(coreLibraryDebugInfo, pw); + } + + if (protoFormat) { + proto.flush(); + } + } + + /** Returns {@code true} if {@code args} contains {@code arg}. */ + private static boolean hasOption(String[] args, String arg) { + for (String opt : args) { + if (arg.equals(opt)) { + return true; + } + } + return false; + } + + /** + * Add information to {@link DebugInfo} about the time zone data supplied by the + * "Time zone updates via APK" feature. + */ + private static void addTimeZoneApkDebugInfo(DebugInfo coreLibraryDebugInfo) { + // Add /data tz data set using the DistroVersion class (which libcore cannot use). + // This update mechanism will be removed after the time zone APEX is launched so this + // untidiness will disappear with it. + String debugKeyPrefix = "core_library.timezone.data_"; + String versionFileName = TimeZoneDataFiles.getDataTimeZoneFile( + TimeZoneDistro.DISTRO_VERSION_FILE_NAME); + addDistroVersionDebugInfo(versionFileName, debugKeyPrefix, coreLibraryDebugInfo); + } + + /** + * Prints {@code coreLibraryDebugInfo} to {@code pw}. + * + * <p>If you change this method, make sure to modify + * {@link #reportTimeZoneInfoProto(DebugInfo, ProtoOutputStream)} as well. + */ + private static void reportTimeZoneInfo(DebugInfo coreLibraryDebugInfo, + PrintWriter pw) { + pw.println("Core Library Debug Info: "); + for (DebugInfo.DebugEntry debugEntry : coreLibraryDebugInfo.getDebugEntries()) { + pw.print(debugEntry.getKey()); + pw.print(": \""); + pw.print(debugEntry.getStringValue()); + pw.println("\""); + } + } + + /** + * Adds {@code coreLibraryDebugInfo} to {@code protoStream}. + * + * <p>If you change this method, make sure to modify + * {@link #reportTimeZoneInfo(DebugInfo, PrintWriter)}. + */ + private static void reportTimeZoneInfoProto( + DebugInfo coreLibraryDebugInfo, ProtoOutputStream protoStream) { + for (DebugInfo.DebugEntry debugEntry : coreLibraryDebugInfo.getDebugEntries()) { + long entryToken = protoStream.start(RuntimeServiceInfoProto.DEBUG_ENTRY); + protoStream.write(DebugEntryProto.KEY, debugEntry.getKey()); + protoStream.write(DebugEntryProto.STRING_VALUE, debugEntry.getStringValue()); + protoStream.end(entryToken); + } + } + + /** + * Adds version information to {@code debugInfo} from the distro_version file that may exist + * at {@code distroVersionFileName}. If the file does not exist or cannot be read this is + * reported as debug information too. + */ + private static void addDistroVersionDebugInfo(String distroVersionFileName, + String debugKeyPrefix, DebugInfo debugInfo) { + File file = new File(distroVersionFileName); + String statusKey = debugKeyPrefix + "status"; + if (file.exists()) { + try { + byte[] versionBytes = + FileUtils.readBytes(file, DistroVersion.DISTRO_VERSION_FILE_LENGTH); + DistroVersion distroVersion = DistroVersion.fromBytes(versionBytes); + String formatVersionString = distroVersion.formatMajorVersion + "." + + distroVersion.formatMinorVersion; + debugInfo.addStringEntry(statusKey, "OK") + .addStringEntry(debugKeyPrefix + "formatVersion", formatVersionString) + .addStringEntry(debugKeyPrefix + "rulesVersion", + distroVersion.rulesVersion) + .addStringEntry(debugKeyPrefix + "revision", + distroVersion.revision); + } catch (IOException | DistroException e) { + debugInfo.addStringEntry(statusKey, "ERROR"); + debugInfo.addStringEntry(debugKeyPrefix + "exception_class", + e.getClass().getName()); + debugInfo.addStringEntry(debugKeyPrefix + "exception_msg", e.getMessage()); + logMessage("Error reading " + file, e); + } + } else { + debugInfo.addStringEntry(statusKey, "NOT_FOUND"); + } + } + + private static void logMessage(String msg, Throwable t) { + Slog.v(TAG, msg, t); + } +} diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java index c2f4406c615d..bf95210195b7 100644 --- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java @@ -313,6 +313,7 @@ public class NetworkMonitor extends StateMachine { private final State mCaptivePortalState = new CaptivePortalState(); private final State mEvaluatingPrivateDnsState = new EvaluatingPrivateDnsState(); private final State mProbingState = new ProbingState(); + private final State mWaitingForNextProbeState = new WaitingForNextProbeState(); private CustomIntentReceiver mLaunchCaptivePortalAppBroadcastReceiver = null; @@ -368,6 +369,7 @@ public class NetworkMonitor extends StateMachine { addState(mMaybeNotifyState, mDefaultState); addState(mEvaluatingState, mMaybeNotifyState); addState(mProbingState, mEvaluatingState); + addState(mWaitingForNextProbeState, mEvaluatingState); addState(mCaptivePortalState, mMaybeNotifyState); addState(mEvaluatingPrivateDnsState, mDefaultState); addState(mValidatedState, mDefaultState); @@ -877,6 +879,11 @@ public class NetworkMonitor extends StateMachine { @Override public void enter() { + if (mEvaluateAttempts >= BLAME_FOR_EVALUATION_ATTEMPTS) { + //Don't continue to blame UID forever. + TrafficStats.clearThreadStatsUid(); + } + final int token = ++mProbeToken; mThread = new Thread(() -> sendMessage(obtainMessage(CMD_PROBE_COMPLETE, token, 0, isCaptivePortal()))); @@ -904,29 +911,16 @@ public class NetworkMonitor extends StateMachine { mLastPortalProbeResult = probeResult; transitionTo(mCaptivePortalState); } else { - final Message msg = obtainMessage(CMD_REEVALUATE, ++mReevaluateToken, 0); - sendMessageDelayed(msg, mReevaluateDelayMs); logNetworkEvent(NetworkEvent.NETWORK_VALIDATION_FAILED); notifyNetworkTestResultInvalid(probeResult.redirectUrl); - if (mEvaluateAttempts >= BLAME_FOR_EVALUATION_ATTEMPTS) { - // Don't continue to blame UID forever. - TrafficStats.clearThreadStatsUid(); - } - mReevaluateDelayMs *= 2; - if (mReevaluateDelayMs > MAX_REEVALUATE_DELAY_MS) { - mReevaluateDelayMs = MAX_REEVALUATE_DELAY_MS; - } + transitionTo(mWaitingForNextProbeState); } return HANDLED; - case CMD_REEVALUATE: - // Leave the event to EvaluatingState. Defer this message will result in reset - // of mReevaluateDelayMs and mEvaluateAttempts. - case CMD_NETWORK_DISCONNECTED: case EVENT_DNS_NOTIFICATION: + // Leave the event to DefaultState to record correct dns timestamp. return NOT_HANDLED; default: - // TODO: Some events may able to handle in this state, instead of deferring to - // next state. + // Wait for probe result and defer events to next state by default. deferMessage(message); return HANDLED; } @@ -941,6 +935,29 @@ public class NetworkMonitor extends StateMachine { } } + // Being in the WaitingForNextProbeState indicates that evaluating probes failed and state is + // transited from ProbingState. This ensures that the state machine is only in ProbingState + // while a probe is in progress, not while waiting to perform the next probe. That allows + // ProbingState to defer most messages until the probe is complete, which keeps the code simple + // and matches the pre-Q behaviour where probes were a blocking operation performed on the state + // machine thread. + private class WaitingForNextProbeState extends State { + @Override + public void enter() { + final Message msg = obtainMessage(CMD_REEVALUATE, ++mReevaluateToken, 0); + sendMessageDelayed(msg, mReevaluateDelayMs); + mReevaluateDelayMs *= 2; + if (mReevaluateDelayMs > MAX_REEVALUATE_DELAY_MS) { + mReevaluateDelayMs = MAX_REEVALUATE_DELAY_MS; + } + } + + @Override + public boolean processMessage(Message message) { + return NOT_HANDLED; + } + } + // Limits the list of IP addresses returned by getAllByName or tried by openConnection to at // most one per address family. This ensures we only wait up to 20 seconds for TCP connections // to complete, regardless of how many IP addresses a host has. diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 0b32d1a5d69b..6ccd0406bfcc 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -58,7 +58,6 @@ import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SELinux; -import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; @@ -646,8 +645,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub { } try { - Os.mkdir(stageDir.getAbsolutePath(), 0755); - Os.chmod(stageDir.getAbsolutePath(), 0755); + Os.mkdir(stageDir.getAbsolutePath(), 0775); + Os.chmod(stageDir.getAbsolutePath(), 0775); } catch (ErrnoException e) { // This purposefully throws if directory already exists throw new IOException("Failed to prepare session dir: " + stageDir, e); diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 81a836749a7f..57deb3f18969 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -42,6 +42,7 @@ import static com.android.server.pm.PackageInstallerService.prepareStageDir; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; +import android.apex.IApexService; import android.app.admin.DeviceAdminInfo; import android.app.admin.DevicePolicyManagerInternal; import android.content.Context; @@ -73,6 +74,7 @@ import android.os.ParcelableException; import android.os.Process; import android.os.RemoteException; import android.os.RevocableFileDescriptor; +import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UserHandle; import android.os.storage.StorageManager; @@ -858,12 +860,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { resolveStageDirLocked(); mSealed = true; - - // Verify that stage looks sane with respect to existing application. - // This currently only ensures packageName, versionCode, and certificate - // consistency. try { - validateInstallLocked(pkgInfo); + if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) { + validateApexInstallLocked(pkgInfo); + } else { + // Verify that stage looks sane with respect to existing application. + // This currently only ensures packageName, versionCode, and certificate + // consistency. + validateApkInstallLocked(pkgInfo); + } } catch (PackageManagerException e) { throw e; } catch (Throwable e) { @@ -942,6 +947,31 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { Preconditions.checkNotNull(mSigningDetails); Preconditions.checkNotNull(mResolvedBaseFile); + if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) { + commitApexLocked(); + } else { + commitApkLocked(); + } + } + + @GuardedBy("mLock") + private void commitApexLocked() throws PackageManagerException { + try { + IApexService apex = IApexService.Stub.asInterface( + ServiceManager.getService("apexservice")); + apex.stagePackage(mResolvedBaseFile.toString()); + } catch (Throwable e) { + // Convert all exceptions into package manager exceptions as only those are handled + // in the code above + throw new PackageManagerException(e); + } finally { + destroyInternal(); + dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "APEX installed", null); + } + } + + @GuardedBy("mLock") + private void commitApkLocked() throws PackageManagerException { if (needToAskForPermissionsLocked()) { // User needs to accept permissions; give installer an intent they // can use to involve user. @@ -1063,6 +1093,57 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { (params.installFlags & PackageManager.DONT_KILL_APP) != 0; } + @GuardedBy("mLock") + private void validateApexInstallLocked(@Nullable PackageInfo pkgInfo) + throws PackageManagerException { + mResolvedStagedFiles.clear(); + mResolvedInheritedFiles.clear(); + + try { + resolveStageDirLocked(); + } catch (IOException e) { + throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR, + "Failed to resolve stage location", e); + } + + final File[] addedFiles = mResolvedStageDir.listFiles(sAddedFilter); + if (ArrayUtils.isEmpty(addedFiles)) { + throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged"); + } + + if (addedFiles.length > 1) { + throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, + "Only one APEX file at a time might be installed"); + } + File addedFile = addedFiles[0]; + final ApkLite apk; + try { + apk = PackageParser.parseApkLite( + addedFile, PackageParser.PARSE_COLLECT_CERTIFICATES); + } catch (PackageParserException e) { + throw PackageManagerException.from(e); + } + + mPackageName = apk.packageName; + mVersionCode = apk.getLongVersionCode(); + mSigningDetails = apk.signingDetails; + mResolvedBaseFile = addedFile; + + assertApkConsistentLocked(String.valueOf(addedFile), apk); + + if (mSigningDetails == PackageParser.SigningDetails.UNKNOWN) { + try { + // STOPSHIP: For APEX we should also implement proper APK Signature verification. + mSigningDetails = ApkSignatureVerifier.plsCertsNoVerifyOnlyCerts( + pkgInfo.applicationInfo.sourceDir, + PackageParser.SigningDetails.SignatureSchemeVersion.JAR); + } catch (PackageParserException e) { + throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, + "Couldn't obtain signatures from base APK"); + } + } + } + /** * Validate install by confirming that all application packages are have * consistent package name, version code, and signing certificates. @@ -1076,7 +1157,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { * {@link PackageManagerService}. */ @GuardedBy("mLock") - private void validateInstallLocked(@Nullable PackageInfo pkgInfo) + private void validateApkInstallLocked(@Nullable PackageInfo pkgInfo) throws PackageManagerException { mPackageName = null; mVersionCode = -1; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 47723daf95b0..52b6ffcd3d19 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -65,6 +65,7 @@ import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATIO import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; import static android.content.pm.PackageManager.MATCH_ALL; import static android.content.pm.PackageManager.MATCH_ANY_USER; +import static android.content.pm.PackageManager.MATCH_APEX; import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; @@ -123,6 +124,8 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; +import android.apex.ApexInfo; +import android.apex.IApexService; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.AppOpsManager; @@ -7912,6 +7915,8 @@ public class PackageManagerService extends IPackageManager.Stub if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList(); flags = updateFlagsForPackage(flags, userId, null); final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0; + final boolean listApex = (flags & MATCH_APEX) != 0; + mPermissionManager.enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */, false /* checkShell */, "get installed packages"); @@ -7950,7 +7955,22 @@ public class PackageManagerService extends IPackageManager.Stub } } } - + if (listApex) { + final IApexService apex = IApexService.Stub.asInterface( + ServiceManager.getService("apexservice")); + if (apex != null) { + try { + final ApexInfo[] activePkgs = apex.getActivePackages(); + for (ApexInfo apexInfo : activePkgs) { + list.add(new PackageInfo(apexInfo)); + } + } catch (RemoteException e) { + Log.e(TAG, "Unable to retrieve packages from apexservice: " + e.toString()); + } + } else { + Log.e(TAG, "Unable to connect to apexservice for querying packages."); + } + } return new ParceledListSlice<>(list); } } diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index 96bf44ac6d5a..580126f5c330 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -915,7 +915,10 @@ class PackageManagerShellCommand extends ShellCommand { pw.println("Error: must either specify a package size or an APK file"); return 1; } - if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk", + final boolean isApex = + (params.sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0; + String splitName = "base." + (isApex ? "apex" : "apk"); + if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, splitName, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { return 1; } @@ -2229,6 +2232,9 @@ class PackageManagerShellCommand extends ShellCommand { case "--force-sdk": sessionParams.installFlags |= PackageManager.INSTALL_FORCE_SDK; break; + case "--apex": + sessionParams.installFlags |= PackageManager.INSTALL_APEX; + break; default: throw new IllegalArgumentException("Unknown option " + opt); } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 439f313e0f0a..80b0e6f4fca7 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1419,6 +1419,14 @@ public final class SystemServer { } traceEnd(); + traceBeginAndSlog("RuntimeService"); + try { + ServiceManager.addService("runtime", new RuntimeService(context)); + } catch (Throwable e) { + reportWtf("starting RuntimeService", e); + } + traceEnd(); + // timezone.RulesManagerService will prevent a device starting up if the chain of trust // required for safe time zone updates might be broken. RuleManagerService cannot do // this check when mOnlyCore == true, so we don't enable the service in this case. diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp index 0c40a6b5fa84..de40e0df48e7 100644 --- a/startop/view_compiler/Android.bp +++ b/startop/view_compiler/Android.bp @@ -24,7 +24,6 @@ cc_defaults { "libdexfile", "slicer", ], - cppflags: ["-std=c++17"], } cc_library_host_static { diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl index d97f0c5f7684..143b323892f3 100644 --- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl +++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl @@ -304,4 +304,10 @@ interface ITelecomService { * @see TelecomServiceImpl#handleCallIntent */ void handleCallIntent(in Intent intent); + + void setTestDefaultCallScreeningApp(String packageName); + + void addOrRemoveTestCallCompanionApp(String packageName, boolean isAdded); + + void setTestAutoModeApp(String packageName); } diff --git a/telephony/OWNERS b/telephony/OWNERS index 054288b85ba6..2236cba498aa 100644 --- a/telephony/OWNERS +++ b/telephony/OWNERS @@ -13,3 +13,4 @@ satk@google.com shuoq@google.com refuhoo@google.com paulye@google.com +nazaninb@google.com
\ No newline at end of file diff --git a/telephony/java/android/telephony/NumberVerificationCallback.java b/telephony/java/android/telephony/NumberVerificationCallback.java new file mode 100644 index 000000000000..b00c57351589 --- /dev/null +++ b/telephony/java/android/telephony/NumberVerificationCallback.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.SystemApi; + +/** + * A callback for number verification. After a request for number verification is received, + * the system will call {@link #onCallReceived(String)} if a phone call was received from a number + * matching the provided {@link PhoneNumberRange} or it will call {@link #onVerificationFailed(int)} + * if an error occurs. + * @hide + */ +@SystemApi +public interface NumberVerificationCallback { + /** @hide */ + @IntDef(value = {REASON_UNSPECIFIED, REASON_TIMED_OUT, REASON_NETWORK_NOT_AVAILABLE, + REASON_TOO_MANY_CALLS, REASON_CONCURRENT_REQUESTS, REASON_IN_ECBM, + REASON_IN_EMERGENCY_CALL}, + prefix = {"REASON_"}) + @interface NumberVerificationFailureReason {} + + /** + * Verification failed for an unspecified reason. + */ + int REASON_UNSPECIFIED = 0; + + /** + * Verification failed because no phone call was received from a matching number within the + * provided timeout. + */ + int REASON_TIMED_OUT = 1; + + /** + * Verification failed because no cellular voice network is available. + */ + int REASON_NETWORK_NOT_AVAILABLE = 2; + + /** + * Verification failed because there are currently too many ongoing phone calls for a new + * incoming phone call to be received. + */ + int REASON_TOO_MANY_CALLS = 3; + + /** + * Verification failed because a previous request for verification has not yet completed. + */ + int REASON_CONCURRENT_REQUESTS = 4; + + /** + * Verification failed because the phone is in emergency callback mode. + */ + int REASON_IN_ECBM = 5; + + /** + * Verification failed because the phone is currently in an emergency call. + */ + int REASON_IN_EMERGENCY_CALL = 6; + + /** + * Called when the device receives a phone call from the provided {@link PhoneNumberRange}. + * @param phoneNumber The phone number within the range that called. May or may not contain the + * country code, but will be entirely numeric. + */ + default void onCallReceived(@NonNull String phoneNumber) { } + + /** + * Called when verification fails for some reason. + * @param reason The reason for failure. + */ + default void onVerificationFailed(@NumberVerificationFailureReason int reason) { } +} diff --git a/telephony/java/android/telephony/PhoneNumberRange.aidl b/telephony/java/android/telephony/PhoneNumberRange.aidl new file mode 100644 index 000000000000..b0727be50e0b --- /dev/null +++ b/telephony/java/android/telephony/PhoneNumberRange.aidl @@ -0,0 +1,19 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony; + +parcelable PhoneNumberRange; diff --git a/telephony/java/android/telephony/PhoneNumberRange.java b/telephony/java/android/telephony/PhoneNumberRange.java new file mode 100644 index 000000000000..d65156fd3ca2 --- /dev/null +++ b/telephony/java/android/telephony/PhoneNumberRange.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + +import java.util.Objects; +import java.util.regex.Pattern; + +/** + * This class is used to represent a range of phone numbers. Each range corresponds to a contiguous + * block of phone numbers. + * + * Example: + * {@code + * { + * mCountryCode = "1" + * mPrefix = "650555" + * mLowerBound = "0055" + * mUpperBound = "0899" + * } + * } + * would match 16505550089 and 6505550472, but not 63827593759 or 16505550900 + * @hide + */ +@SystemApi +public final class PhoneNumberRange implements Parcelable { + public static final Creator<PhoneNumberRange> CREATOR = new Creator<PhoneNumberRange>() { + @Override + public PhoneNumberRange createFromParcel(Parcel in) { + return new PhoneNumberRange(in); + } + + @Override + public PhoneNumberRange[] newArray(int size) { + return new PhoneNumberRange[size]; + } + }; + + private final String mCountryCode; + private final String mPrefix; + private final String mLowerBound; + private final String mUpperBound; + + /** + * @param countryCode The country code, omitting the leading "+" + * @param prefix A prefix that all numbers matching the range must have. + * @param lowerBound When concatenated with the prefix, represents the lower bound of phone + * numbers that match this range. + * @param upperBound When concatenated with the prefix, represents the upper bound of phone + * numbers that match this range. + */ + public PhoneNumberRange(@NonNull String countryCode, @NonNull String prefix, + @NonNull String lowerBound, @NonNull String upperBound) { + validateLowerAndUpperBounds(lowerBound, upperBound); + if (!Pattern.matches("[0-9]+", countryCode)) { + throw new IllegalArgumentException("Country code must be all numeric"); + } + if (!Pattern.matches("[0-9]+", prefix)) { + throw new IllegalArgumentException("Prefix must be all numeric"); + } + mCountryCode = countryCode; + mPrefix = prefix; + mLowerBound = lowerBound; + mUpperBound = upperBound; + } + + private PhoneNumberRange(Parcel in) { + mCountryCode = in.readStringNoHelper(); + mPrefix = in.readStringNoHelper(); + mLowerBound = in.readStringNoHelper(); + mUpperBound = in.readStringNoHelper(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeStringNoHelper(mCountryCode); + dest.writeStringNoHelper(mPrefix); + dest.writeStringNoHelper(mLowerBound); + dest.writeStringNoHelper(mUpperBound); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PhoneNumberRange that = (PhoneNumberRange) o; + return Objects.equals(mCountryCode, that.mCountryCode) + && Objects.equals(mPrefix, that.mPrefix) + && Objects.equals(mLowerBound, that.mLowerBound) + && Objects.equals(mUpperBound, that.mUpperBound); + } + + @Override + public int hashCode() { + return Objects.hash(mCountryCode, mPrefix, mLowerBound, mUpperBound); + } + + @Override + public String toString() { + return "PhoneNumberRange{" + + "mCountryCode='" + mCountryCode + '\'' + + ", mPrefix='" + mPrefix + '\'' + + ", mLowerBound='" + mLowerBound + '\'' + + ", mUpperBound='" + mUpperBound + '\'' + + '}'; + } + + private void validateLowerAndUpperBounds(String lowerBound, String upperBound) { + if (lowerBound.length() != upperBound.length()) { + throw new IllegalArgumentException("Lower and upper bounds must have the same length"); + } + if (!Pattern.matches("[0-9]+", lowerBound)) { + throw new IllegalArgumentException("Lower bound must be all numeric"); + } + if (!Pattern.matches("[0-9]+", upperBound)) { + throw new IllegalArgumentException("Upper bound must be all numeric"); + } + if (Integer.parseInt(lowerBound) > Integer.parseInt(upperBound)) { + throw new IllegalArgumentException("Lower bound must be lower than upper bound"); + } + } + + /** + * Checks to see if the provided phone number matches this range. + * @param number A phone number, with or without separators or a country code. + * @return {@code true} if the number matches, {@code false} otherwise. + */ + public boolean matches(String number) { + // Check the prefix, make sure it matches either with or without the country code. + String normalizedNumber = number.replaceAll("[^0-9]", ""); + String prefixWithCountryCode = mCountryCode + mPrefix; + String numberPostfix; + if (normalizedNumber.startsWith(prefixWithCountryCode)) { + numberPostfix = normalizedNumber.substring(prefixWithCountryCode.length()); + } else if (normalizedNumber.startsWith(mPrefix)) { + numberPostfix = normalizedNumber.substring(mPrefix.length()); + } else { + return false; + } + + // Next check the postfix to make sure it lies within the bounds. + try { + int lower = Integer.parseInt(mLowerBound); + int upper = Integer.parseInt(mUpperBound); + int numberToCheck = Integer.parseInt(numberPostfix); + return numberToCheck <= upper && numberToCheck >= lower; + } catch (NumberFormatException e) { + Log.e(PhoneNumberRange.class.getSimpleName(), "Invalid bounds or number.", e); + return false; + } + } +} diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 2bc1e0d23323..d4788e3b726e 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -77,6 +77,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telecom.ITelecomService; import com.android.internal.telephony.CellNetworkScanResult; import com.android.internal.telephony.IAns; +import com.android.internal.telephony.INumberVerificationCallback; import com.android.internal.telephony.IPhoneSubInfo; import com.android.internal.telephony.ITelephony; import com.android.internal.telephony.ITelephonyRegistry; @@ -1332,6 +1333,13 @@ public class TelephonyManager { */ public static final String EXTRA_RECOVERY_ACTION = "recoveryAction"; + /** + * The max value for the timeout passed in {@link #requestNumberVerification}. + * @hide + */ + @SystemApi + public static final long MAX_NUMBER_VERIFICATION_TIMEOUT_MILLIS = 60000; + // // // Device Info @@ -5347,7 +5355,7 @@ public class TelephonyManager { /** * Rollback modem configurations to factory default except some config which are in whitelist. - * Used for device configuration by some CDMA operators. + * Used for device configuration by some carriers. * * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling @@ -5374,7 +5382,7 @@ public class TelephonyManager { } /** - * Generate a radio modem reset. Used for device configuration by some CDMA operators. + * Generate a radio modem reset. Used for device configuration by some carriers. * * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling @@ -5478,6 +5486,52 @@ public class TelephonyManager { } /** + * Request that the next incoming call from a number matching {@code range} be intercepted. + * + * This API is intended for OEMs to provide a service for apps to verify the device's phone + * number. When called, the Telephony stack will store the provided {@link PhoneNumberRange} and + * intercept the next incoming call from a number that lies within the range, within a timeout + * specified by {@code timeoutMillis}. + * + * If such a phone call is received, the caller will be notified via + * {@link NumberVerificationCallback#onCallReceived(String)} on the provided {@link Executor}. + * If verification fails for any reason, the caller will be notified via + * {@link NumberVerificationCallback#onVerificationFailed(int)} + * on the provided {@link Executor}. + * + * In addition to the {@link Manifest.permission#MODIFY_PHONE_STATE} permission, callers of this + * API must also be listed in the device configuration as an authorized app in + * {@code packages/services/Telephony/res/values/config.xml} under the + * {@code config_number_verification_package_name} key. + * + * @hide + * @param range The range of phone numbers the caller expects a phone call from. + * @param timeoutMillis The amount of time to wait for such a call, or + * {@link #MAX_NUMBER_VERIFICATION_TIMEOUT_MILLIS}, whichever is lesser. + * @param executor The {@link Executor} that callbacks should be executed on. + * @param callback The callback to use for delivering results. + */ + @SystemApi + @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) + public void requestNumberVerification(@NonNull PhoneNumberRange range, long timeoutMillis, + @NonNull @CallbackExecutor Executor executor, + @NonNull NumberVerificationCallback callback) { + INumberVerificationCallback internalCallback = new INumberVerificationCallback.Stub() { + @Override + public void onCallReceived(String phoneNumber) throws RemoteException { + Binder.withCleanCallingIdentity(() -> callback.onCallReceived(phoneNumber)); + } + + @Override + public void onVerificationFailed(int reason) throws RemoteException { + Binder.withCleanCallingIdentity(() -> callback.onVerificationFailed(reason)); + } + }; + + // TODO -- call the aidl method + } + + /** * Sets a per-phone telephony property with the value specified. * * @hide diff --git a/telephony/java/com/android/internal/telephony/INumberVerificationCallback.aidl b/telephony/java/com/android/internal/telephony/INumberVerificationCallback.aidl new file mode 100644 index 000000000000..76918afb564a --- /dev/null +++ b/telephony/java/com/android/internal/telephony/INumberVerificationCallback.aidl @@ -0,0 +1,22 @@ +/* + * 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.internal.telephony; + +oneway interface INumberVerificationCallback { + void onCallReceived(String phoneNumber); + void onVerificationFailed(int reason); +} diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java index 4dc0341c8e2b..d8f961850906 100644 --- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java @@ -542,7 +542,7 @@ public class IpSecServiceParameterizedTest { verify(mMockNetd) .ipSecApplyTransportModeTransform( - eq(pfd.getFileDescriptor()), + eq(pfd), eq(mUid), eq(IpSecManager.DIRECTION_OUT), anyString(), @@ -555,7 +555,7 @@ public class IpSecServiceParameterizedTest { ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket()); mIpSecService.removeTransportModeTransforms(pfd); - verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor()); + verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd); } private IpSecTunnelInterfaceResponse createAndValidateTunnel( diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java index 2c94a601fbf6..724446e11c83 100644 --- a/tests/net/java/com/android/server/IpSecServiceTest.java +++ b/tests/net/java/com/android/server/IpSecServiceTest.java @@ -425,7 +425,7 @@ public class IpSecServiceTest { ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket()); mIpSecService.removeTransportModeTransforms(pfd); - verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor()); + verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd); } @Test @@ -620,10 +620,10 @@ public class IpSecServiceTest { mIpSecService.openUdpEncapsulationSocket(0, new Binder()); FileDescriptor sockFd = udpEncapResp.fileDescriptor.getFileDescriptor(); - ArgumentMatcher<FileDescriptor> fdMatcher = (arg) -> { + ArgumentMatcher<ParcelFileDescriptor> fdMatcher = (arg) -> { try { StructStat sockStat = Os.fstat(sockFd); - StructStat argStat = Os.fstat(arg); + StructStat argStat = Os.fstat(arg.getFileDescriptor()); return sockStat.st_ino == argStat.st_ino && sockStat.st_dev == argStat.st_dev; diff --git a/tools/aosp/aosp_sha.sh b/tools/aosp/aosp_sha.sh index e50c70d0656a..f25fcdcb7479 100755 --- a/tools/aosp/aosp_sha.sh +++ b/tools/aosp/aosp_sha.sh @@ -19,6 +19,6 @@ else echo "If your change contains no confidential details (such as security fixes), please" echo "upload and merge this change at https://android-review.googlesource.com/." echo - exit 77 + exit 1 fi fi diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py index 2f1e53ca5065..01728fa1a0db 100755 --- a/tools/hiddenapi/generate_hiddenapi_lists.py +++ b/tools/hiddenapi/generate_hiddenapi_lists.py @@ -26,6 +26,7 @@ FLAG_WHITELIST = "whitelist" FLAG_GREYLIST = "greylist" FLAG_BLACKLIST = "blacklist" FLAG_GREYLIST_MAX_O = "greylist-max-o" +FLAG_GREYLIST_MAX_P = "greylist-max-p" # List of all known flags. FLAGS = [ @@ -33,6 +34,7 @@ FLAGS = [ FLAG_GREYLIST, FLAG_BLACKLIST, FLAG_GREYLIST_MAX_O, + FLAG_GREYLIST_MAX_P, ] FLAGS_SET = set(FLAGS) |