diff options
32 files changed, 372 insertions, 131 deletions
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java index bccbb381bfb1..2a854b2f6513 100644 --- a/core/java/android/app/BroadcastOptions.java +++ b/core/java/android/app/BroadcastOptions.java @@ -37,8 +37,6 @@ import android.os.PowerExemptionManager; import android.os.PowerExemptionManager.ReasonCode; import android.os.PowerExemptionManager.TempAllowListType; -import com.android.internal.util.Preconditions; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; @@ -61,7 +59,8 @@ public class BroadcastOptions extends ComponentOptions { private long mRequireCompatChangeId = CHANGE_INVALID; private long mIdForResponseEvent; private @DeliveryGroupPolicy int mDeliveryGroupPolicy; - private @Nullable String mDeliveryGroupMatchingKey; + private @Nullable String mDeliveryGroupMatchingNamespaceFragment; + private @Nullable String mDeliveryGroupMatchingKeyFragment; private @Nullable BundleMerger mDeliveryGroupExtrasMerger; private @Nullable IntentFilter mDeliveryGroupMatchingFilter; private @DeferralPolicy int mDeferralPolicy; @@ -209,7 +208,13 @@ public class BroadcastOptions extends ComponentOptions { "android:broadcast.deliveryGroupPolicy"; /** - * Corresponds to {@link #setDeliveryGroupMatchingKey(String, String)}. + * Corresponds to namespace fragment of {@link #setDeliveryGroupMatchingKey(String, String)}. + */ + private static final String KEY_DELIVERY_GROUP_NAMESPACE = + "android:broadcast.deliveryGroupMatchingNamespace"; + + /** + * Corresponds to key fragment of {@link #setDeliveryGroupMatchingKey(String, String)}. */ private static final String KEY_DELIVERY_GROUP_KEY = "android:broadcast.deliveryGroupMatchingKey"; @@ -350,7 +355,8 @@ public class BroadcastOptions extends ComponentOptions { mIdForResponseEvent = opts.getLong(KEY_ID_FOR_RESPONSE_EVENT); mDeliveryGroupPolicy = opts.getInt(KEY_DELIVERY_GROUP_POLICY, DELIVERY_GROUP_POLICY_ALL); - mDeliveryGroupMatchingKey = opts.getString(KEY_DELIVERY_GROUP_KEY); + mDeliveryGroupMatchingNamespaceFragment = opts.getString(KEY_DELIVERY_GROUP_NAMESPACE); + mDeliveryGroupMatchingKeyFragment = opts.getString(KEY_DELIVERY_GROUP_KEY); mDeliveryGroupExtrasMerger = opts.getParcelable(KEY_DELIVERY_GROUP_EXTRAS_MERGER, BundleMerger.class); mDeliveryGroupMatchingFilter = opts.getParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER, @@ -864,11 +870,8 @@ public class BroadcastOptions extends ComponentOptions { @NonNull public BroadcastOptions setDeliveryGroupMatchingKey(@NonNull String namespace, @NonNull String key) { - Preconditions.checkArgument(!namespace.contains(":"), - "namespace should not contain ':'"); - Preconditions.checkArgument(!key.contains(":"), - "key should not contain ':'"); - mDeliveryGroupMatchingKey = namespace + ":" + key; + mDeliveryGroupMatchingNamespaceFragment = Objects.requireNonNull(namespace); + mDeliveryGroupMatchingKeyFragment = Objects.requireNonNull(key); return this; } @@ -881,7 +884,38 @@ public class BroadcastOptions extends ComponentOptions { */ @Nullable public String getDeliveryGroupMatchingKey() { - return mDeliveryGroupMatchingKey; + if (mDeliveryGroupMatchingNamespaceFragment == null + || mDeliveryGroupMatchingKeyFragment == null) { + return null; + } + return String.join(":", mDeliveryGroupMatchingNamespaceFragment, + mDeliveryGroupMatchingKeyFragment); + } + + /** + * Return the namespace fragment that is used to identify the delivery group that this + * broadcast belongs to. + * + * @return the delivery group namespace fragment that was previously set using + * {@link #setDeliveryGroupMatchingKey(String, String)}. + * @hide + */ + @Nullable + public String getDeliveryGroupMatchingNamespaceFragment() { + return mDeliveryGroupMatchingNamespaceFragment; + } + + /** + * Return the key fragment that is used to identify the delivery group that this + * broadcast belongs to. + * + * @return the delivery group key fragment that was previously set using + * {@link #setDeliveryGroupMatchingKey(String, String)}. + * @hide + */ + @Nullable + public String getDeliveryGroupMatchingKeyFragment() { + return mDeliveryGroupMatchingKeyFragment; } /** @@ -889,7 +923,8 @@ public class BroadcastOptions extends ComponentOptions { * {@link #setDeliveryGroupMatchingKey(String, String)}. */ public void clearDeliveryGroupMatchingKey() { - mDeliveryGroupMatchingKey = null; + mDeliveryGroupMatchingNamespaceFragment = null; + mDeliveryGroupMatchingKeyFragment = null; } /** @@ -1101,8 +1136,11 @@ public class BroadcastOptions extends ComponentOptions { if (mDeliveryGroupPolicy != DELIVERY_GROUP_POLICY_ALL) { b.putInt(KEY_DELIVERY_GROUP_POLICY, mDeliveryGroupPolicy); } - if (mDeliveryGroupMatchingKey != null) { - b.putString(KEY_DELIVERY_GROUP_KEY, mDeliveryGroupMatchingKey); + if (mDeliveryGroupMatchingNamespaceFragment != null) { + b.putString(KEY_DELIVERY_GROUP_NAMESPACE, mDeliveryGroupMatchingNamespaceFragment); + } + if (mDeliveryGroupMatchingKeyFragment != null) { + b.putString(KEY_DELIVERY_GROUP_KEY, mDeliveryGroupMatchingKeyFragment); } if (mDeliveryGroupPolicy == DELIVERY_GROUP_POLICY_MERGED) { if (mDeliveryGroupExtrasMerger != null) { diff --git a/core/java/android/hardware/soundtrigger/OWNERS b/core/java/android/hardware/soundtrigger/OWNERS index 01b2cb981bbb..1e41886fe716 100644 --- a/core/java/android/hardware/soundtrigger/OWNERS +++ b/core/java/android/hardware/soundtrigger/OWNERS @@ -1,2 +1 @@ -atneya@google.com -elaurent@google.com +include /media/java/android/media/soundtrigger/OWNERS diff --git a/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java index 38b3174abd4c..46cf0163c0e5 100644 --- a/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java +++ b/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java @@ -354,6 +354,7 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork } /** @hide */ + @Override public Map<Integer, Integer> getCapabilitiesMatchCriteria() { return Collections.unmodifiableMap(new HashMap<>(mCapabilitiesMatchCriteria)); } diff --git a/core/java/android/net/vcn/VcnConfig.java b/core/java/android/net/vcn/VcnConfig.java index 6f9c9dd918d1..a27e9230d473 100644 --- a/core/java/android/net/vcn/VcnConfig.java +++ b/core/java/android/net/vcn/VcnConfig.java @@ -16,6 +16,7 @@ package android.net.vcn; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; +import static android.net.NetworkCapabilities.TRANSPORT_TEST; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static com.android.internal.annotations.VisibleForTesting.Visibility; @@ -75,6 +76,7 @@ public final class VcnConfig implements Parcelable { static { ALLOWED_TRANSPORTS.add(TRANSPORT_WIFI); ALLOWED_TRANSPORTS.add(TRANSPORT_CELLULAR); + ALLOWED_TRANSPORTS.add(TRANSPORT_TEST); } private static final String PACKAGE_NAME_KEY = "mPackageName"; @@ -155,6 +157,11 @@ public final class VcnConfig implements Parcelable { + transport + " which might be from a new version of VcnConfig"); } + + if (transport == TRANSPORT_TEST && !mIsTestModeProfile) { + throw new IllegalArgumentException( + "Found TRANSPORT_TEST in a non-test-mode profile"); + } } } diff --git a/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java index 9235d0913295..edf2c093bc8b 100644 --- a/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java +++ b/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java @@ -29,6 +29,7 @@ import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Map; import java.util.Objects; /** @@ -307,4 +308,7 @@ public abstract class VcnUnderlyingNetworkTemplate { public int getMinExitDownstreamBandwidthKbps() { return mMinExitDownstreamBandwidthKbps; } + + /** @hide */ + public abstract Map<Integer, Integer> getCapabilitiesMatchCriteria(); } diff --git a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java index 2544a6d63561..2e6b09f032fb 100644 --- a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java +++ b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java @@ -15,6 +15,9 @@ */ package android.net.vcn; +import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; +import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY; + import static com.android.internal.annotations.VisibleForTesting.Visibility; import static com.android.server.vcn.util.PersistableBundleUtils.STRING_DESERIALIZER; import static com.android.server.vcn.util.PersistableBundleUtils.STRING_SERIALIZER; @@ -23,6 +26,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.net.NetworkCapabilities; +import android.net.vcn.VcnUnderlyingNetworkTemplate.MatchCriteria; import android.os.PersistableBundle; import android.util.ArraySet; @@ -32,6 +36,7 @@ import com.android.server.vcn.util.PersistableBundleUtils; import java.util.ArrayList; import java.util.Collections; +import java.util.Map; import java.util.Objects; import java.util.Set; @@ -162,6 +167,12 @@ public final class VcnWifiUnderlyingNetworkTemplate extends VcnUnderlyingNetwork return Collections.unmodifiableSet(mSsids); } + /** @hide */ + @Override + public Map<Integer, Integer> getCapabilitiesMatchCriteria() { + return Collections.singletonMap(NET_CAPABILITY_INTERNET, MATCH_REQUIRED); + } + /** This class is used to incrementally build VcnWifiUnderlyingNetworkTemplate objects. */ public static final class Builder { private int mMeteredMatchCriteria = MATCH_ANY; diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 3c1b4ba8f8b5..0012572540ae 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -8410,7 +8410,7 @@ public final class ContactsContract { extras.putString(KEY_ACCOUNT_NAME, accountName); extras.putString(KEY_ACCOUNT_TYPE, accountType); - contentResolver.call(ContactsContract.AUTHORITY_URI, + nullSafeCall(contentResolver, ContactsContract.AUTHORITY_URI, ContactsContract.SimContacts.ADD_SIM_ACCOUNT_METHOD, null, extras); } @@ -8433,7 +8433,7 @@ public final class ContactsContract { Bundle extras = new Bundle(); extras.putInt(KEY_SIM_SLOT_INDEX, simSlotIndex); - contentResolver.call(ContactsContract.AUTHORITY_URI, + nullSafeCall(contentResolver, ContactsContract.AUTHORITY_URI, ContactsContract.SimContacts.REMOVE_SIM_ACCOUNT_METHOD, null, extras); } @@ -8445,7 +8445,7 @@ public final class ContactsContract { */ public static @NonNull List<SimAccount> getSimAccounts( @NonNull ContentResolver contentResolver) { - Bundle response = contentResolver.call(ContactsContract.AUTHORITY_URI, + Bundle response = nullSafeCall(contentResolver, ContactsContract.AUTHORITY_URI, ContactsContract.SimContacts.QUERY_SIM_ACCOUNTS_METHOD, null, null); List<SimAccount> result = response.getParcelableArrayList(KEY_SIM_ACCOUNTS); @@ -9064,7 +9064,8 @@ public final class ContactsContract { * @param contactId the id of the contact to undemote. */ public static void undemote(ContentResolver contentResolver, long contactId) { - contentResolver.call(ContactsContract.AUTHORITY_URI, PinnedPositions.UNDEMOTE_METHOD, + nullSafeCall(contentResolver, ContactsContract.AUTHORITY_URI, + PinnedPositions.UNDEMOTE_METHOD, String.valueOf(contactId), null); } @@ -10276,4 +10277,13 @@ public final class ContactsContract { public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_metadata_sync_state"; } + + private static Bundle nullSafeCall(@NonNull ContentResolver resolver, @NonNull Uri uri, + @NonNull String method, @Nullable String arg, @Nullable Bundle extras) { + try (ContentProviderClient client = resolver.acquireContentProviderClient(uri)) { + return client.call(method, arg, extras); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } } diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index a7c7d0ba35bc..b24dc8a9e63b 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -413,9 +413,13 @@ protected: if (env->ExceptionCheck()) { ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred()); - binder_report_exception(env, excep.get(), - "*** Uncaught remote exception! " - "(Exceptions are not yet supported across processes.)"); + + auto state = IPCThreadState::self(); + String8 msg; + msg.appendFormat("*** Uncaught remote exception! Exceptions are not yet supported " + "across processes. Client PID %d UID %d.", + state->getCallingPid(), state->getCallingUid()); + binder_report_exception(env, excep.get(), msg.c_str()); res = JNI_FALSE; } @@ -431,6 +435,7 @@ protected: ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred()); binder_report_exception(env, excep.get(), "*** Uncaught exception in onBinderStrictModePolicyChange"); + // TODO: should turn this to fatal? } // Need to always call through the native implementation of diff --git a/media/OWNERS b/media/OWNERS index 5f501372666b..4a6648e91af4 100644 --- a/media/OWNERS +++ b/media/OWNERS @@ -1,4 +1,5 @@ # Bug component: 1344 +atneya@google.com elaurent@google.com essick@google.com etalvala@google.com diff --git a/media/aidl/android/media/soundtrigger_middleware/OWNERS b/media/aidl/android/media/soundtrigger_middleware/OWNERS index 01b2cb981bbb..1e41886fe716 100644 --- a/media/aidl/android/media/soundtrigger_middleware/OWNERS +++ b/media/aidl/android/media/soundtrigger_middleware/OWNERS @@ -1,2 +1 @@ -atneya@google.com -elaurent@google.com +include /media/java/android/media/soundtrigger/OWNERS diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 22033c6d8401..6b29fc319c6b 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -72,7 +72,7 @@ public class AudioSystem throw new UnsupportedOperationException("Trying to instantiate AudioSystem"); } - /* These values must be kept in sync with system/audio.h */ + /* These values must be kept in sync with system/media/audio/include/system/audio-hal-enums.h */ /* * If these are modified, please also update Settings.System.VOLUME_SETTINGS * and attrs.xml and AudioManager.java. @@ -963,7 +963,8 @@ public class AudioSystem */ // - // audio device definitions: must be kept in sync with values in system/core/audio.h + // audio device definitions: must be kept in sync with values + // in system/media/audio/include/system/audio-hal-enums.h // /** @hide */ public static final int DEVICE_NONE = 0x0; diff --git a/media/java/android/media/soundtrigger/OWNERS b/media/java/android/media/soundtrigger/OWNERS index 01b2cb981bbb..85f7a4d605e6 100644 --- a/media/java/android/media/soundtrigger/OWNERS +++ b/media/java/android/media/soundtrigger/OWNERS @@ -1,2 +1,3 @@ +# Bug component: 48436 atneya@google.com elaurent@google.com diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index ce9c067116ef..2daf04d1f8b9 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -75,6 +75,9 @@ import android.content.pm.ProviderInfo; import android.content.pm.UserInfo; import android.content.res.ObbInfo; import android.database.ContentObserver; +import android.media.MediaCodecList; +import android.media.MediaCodecInfo; +import android.media.MediaFormat; import android.net.Uri; import android.os.BatteryManager; import android.os.Binder; @@ -1006,10 +1009,27 @@ class StorageManagerService extends IStorageManager.Stub } } + private boolean isHevcDecoderSupported() { + MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS); + MediaCodecInfo[] codecInfos = codecList.getCodecInfos(); + for (MediaCodecInfo codecInfo : codecInfos) { + if (codecInfo.isEncoder()) { + continue; + } + String[] supportedTypes = codecInfo.getSupportedTypes(); + for (String type : supportedTypes) { + if (type.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) { + return true; + } + } + } + return false; + } + private void configureTranscoding() { // See MediaProvider TranscodeHelper#getBooleanProperty for more information boolean transcodeEnabled = false; - boolean defaultValue = true; + boolean defaultValue = isHevcDecoderSupported() ? true : false; if (SystemProperties.getBoolean("persist.sys.fuse.transcode_user_control", false)) { transcodeEnabled = SystemProperties.getBoolean("persist.sys.fuse.transcode_enabled", diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java index 78d4708e70a2..e8c85ce68f22 100644 --- a/services/core/java/com/android/server/VcnManagementService.java +++ b/services/core/java/com/android/server/VcnManagementService.java @@ -1074,9 +1074,10 @@ public class VcnManagementService extends IVcnManagementService.Stub { subGrp, mLastSnapshot, mConfigs.get(subGrp)); for (int restrictedTransport : restrictedTransports) { if (ncCopy.hasTransport(restrictedTransport)) { - if (restrictedTransport == TRANSPORT_CELLULAR) { - // Only make a cell network as restricted when the VCN is in - // active mode. + if (restrictedTransport == TRANSPORT_CELLULAR + || restrictedTransport == TRANSPORT_TEST) { + // For cell or test network, only mark it as restricted when + // the VCN is in active mode. isRestricted |= (vcn.getStatus() == VCN_STATUS_CODE_ACTIVE); } else { isRestricted = true; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index d48723a4bd04..99f186351f0f 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -8415,13 +8415,16 @@ public class ActivityManagerService extends IActivityManager.Stub } } + boolean recoverable = eventType.equals("native_recoverable_crash"); + EventLogTags.writeAmCrash(Binder.getCallingPid(), UserHandle.getUserId(Binder.getCallingUid()), processName, r == null ? -1 : r.info.flags, crashInfo.exceptionClassName, crashInfo.exceptionMessage, crashInfo.throwFileName, - crashInfo.throwLineNumber); + crashInfo.throwLineNumber, + recoverable ? 1 : 0); int processClassEnum = processName.equals("system_server") ? ServerProtoEnums.SYSTEM_SERVER : (r != null) ? r.getProcessClassEnum() @@ -8489,7 +8492,13 @@ public class ActivityManagerService extends IActivityManager.Stub eventType, r, processName, null, null, null, null, null, null, crashInfo, new Float(loadingProgress), incrementalMetrics, null); - mAppErrors.crashApplication(r, crashInfo); + // For GWP-ASan recoverable crashes, don't make the app crash (the whole point of + // 'recoverable' is that the app doesn't crash). Normally, for nonrecoreable native crashes, + // debuggerd will terminate the process, but there's a backup where ActivityManager will + // also kill it. Avoid that. + if (!recoverable) { + mAppErrors.crashApplication(r, crashInfo); + } } public void handleApplicationStrictModeViolation( diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags index d080036733a5..6ce70a1ee1d4 100644 --- a/services/core/java/com/android/server/am/EventLogTags.logtags +++ b/services/core/java/com/android/server/am/EventLogTags.logtags @@ -53,7 +53,7 @@ option java_package com.android.server.am 30037 am_process_start_timeout (User|1|5),(PID|1|5),(UID|1|5),(Process Name|3) # Unhandled exception -30039 am_crash (User|1|5),(PID|1|5),(Process Name|3),(Flags|1|5),(Exception|3),(Message|3),(File|3),(Line|1|5) +30039 am_crash (User|1|5),(PID|1|5),(Process Name|3),(Flags|1|5),(Exception|3),(Message|3),(File|3),(Line|1|5),(Recoverable|1|5) # Log.wtf() called 30040 am_wtf (User|1|5),(PID|1|5),(Process Name|3),(Flags|1|5),(Tag|3),(Message|3) diff --git a/services/core/java/com/android/server/am/NativeCrashListener.java b/services/core/java/com/android/server/am/NativeCrashListener.java index 94eb07611037..cd119e7e3fbc 100644 --- a/services/core/java/com/android/server/am/NativeCrashListener.java +++ b/services/core/java/com/android/server/am/NativeCrashListener.java @@ -64,12 +64,15 @@ final class NativeCrashListener extends Thread { class NativeCrashReporter extends Thread { ProcessRecord mApp; int mSignal; + boolean mGwpAsanRecoverableCrash; String mCrashReport; - NativeCrashReporter(ProcessRecord app, int signal, String report) { + NativeCrashReporter(ProcessRecord app, int signal, boolean gwpAsanRecoverableCrash, + String report) { super("NativeCrashReport"); mApp = app; mSignal = signal; + mGwpAsanRecoverableCrash = gwpAsanRecoverableCrash; mCrashReport = report; } @@ -85,7 +88,9 @@ final class NativeCrashListener extends Thread { ci.stackTrace = mCrashReport; if (DEBUG) Slog.v(TAG, "Calling handleApplicationCrash()"); - mAm.handleApplicationCrashInner("native_crash", mApp, mApp.processName, ci); + mAm.handleApplicationCrashInner( + mGwpAsanRecoverableCrash ? "native_recoverable_crash" : "native_crash", + mApp, mApp.processName, ci); if (DEBUG) Slog.v(TAG, "<-- handleApplicationCrash() returned"); } catch (Exception e) { Slog.e(TAG, "Unable to report native crash", e); @@ -207,9 +212,14 @@ final class NativeCrashListener extends Thread { // permits crash_dump to connect to it. This allows us to trust the // received values. - // first, the pid and signal number - int headerBytes = readExactly(fd, buf, 0, 8); - if (headerBytes != 8) { + // Activity Manager protocol: + // - 32-bit network-byte-order: pid + // - 32-bit network-byte-order: signal number + // - byte: gwpAsanRecoverableCrash + // - bytes: raw text of the dump + // - null terminator + int headerBytes = readExactly(fd, buf, 0, 9); + if (headerBytes != 9) { // protocol failure; give up Slog.e(TAG, "Unable to read from debuggerd"); return; @@ -217,69 +227,76 @@ final class NativeCrashListener extends Thread { int pid = unpackInt(buf, 0); int signal = unpackInt(buf, 4); + boolean gwpAsanRecoverableCrash = buf[8] != 0; if (DEBUG) { - Slog.v(TAG, "Read pid=" + pid + " signal=" + signal); + Slog.v(TAG, "Read pid=" + pid + " signal=" + signal + + " recoverable=" + gwpAsanRecoverableCrash); + } + if (pid < 0) { + Slog.e(TAG, "Bogus pid!"); + return; } // now the text of the dump - if (pid > 0) { - final ProcessRecord pr; - synchronized (mAm.mPidsSelfLocked) { - pr = mAm.mPidsSelfLocked.get(pid); + final ProcessRecord pr; + synchronized (mAm.mPidsSelfLocked) { + pr = mAm.mPidsSelfLocked.get(pid); + } + if (pr == null) { + Slog.w(TAG, "Couldn't find ProcessRecord for pid " + pid); + return; + } + + // Don't attempt crash reporting for persistent apps + if (pr.isPersistent()) { + if (DEBUG) { + Slog.v(TAG, "Skipping report for persistent app " + pr); } - if (pr != null) { - // Don't attempt crash reporting for persistent apps - if (pr.isPersistent()) { - if (DEBUG) { - Slog.v(TAG, "Skipping report for persistent app " + pr); - } - return; - } + return; + } - int bytes; - do { - // get some data - bytes = Os.read(fd, buf, 0, buf.length); - if (bytes > 0) { - if (MORE_DEBUG) { - String s = new String(buf, 0, bytes, "UTF-8"); - Slog.v(TAG, "READ=" + bytes + "> " + s); - } - // did we just get the EOD null byte? - if (buf[bytes-1] == 0) { - os.write(buf, 0, bytes-1); // exclude the EOD token - break; - } - // no EOD, so collect it and read more - os.write(buf, 0, bytes); - } - } while (bytes > 0); - - // Okay, we've got the report. - if (DEBUG) Slog.v(TAG, "processing"); - - // Mark the process record as being a native crash so that the - // cleanup mechanism knows we're still submitting the report - // even though the process will vanish as soon as we let - // debuggerd proceed. - synchronized (mAm) { - synchronized (mAm.mProcLock) { - pr.mErrorState.setCrashing(true); - pr.mErrorState.setForceCrashReport(true); - } + int bytes; + do { + // get some data + bytes = Os.read(fd, buf, 0, buf.length); + if (bytes > 0) { + if (MORE_DEBUG) { + String s = new String(buf, 0, bytes, "UTF-8"); + Slog.v(TAG, "READ=" + bytes + "> " + s); + } + // did we just get the EOD null byte? + if (buf[bytes - 1] == 0) { + os.write(buf, 0, bytes - 1); // exclude the EOD token + break; + } + // no EOD, so collect it and read more + os.write(buf, 0, bytes); + } + } while (bytes > 0); + + // Okay, we've got the report. + if (DEBUG) Slog.v(TAG, "processing"); + + // Mark the process record as being a native crash so that the + // cleanup mechanism knows we're still submitting the report even + // though the process will vanish as soon as we let debuggerd + // proceed. This isn't relevant for recoverable crashes, as we don't + // show the user an "app crashed" dialogue because the app (by + // design) didn't crash. + if (!gwpAsanRecoverableCrash) { + synchronized (mAm) { + synchronized (mAm.mProcLock) { + pr.mErrorState.setCrashing(true); + pr.mErrorState.setForceCrashReport(true); } - - // Crash reporting is synchronous but we want to let debuggerd - // go about it business right away, so we spin off the actual - // reporting logic on a thread and let it take it's time. - final String reportString = new String(os.toByteArray(), "UTF-8"); - (new NativeCrashReporter(pr, signal, reportString)).start(); - } else { - Slog.w(TAG, "Couldn't find ProcessRecord for pid " + pid); } - } else { - Slog.e(TAG, "Bogus pid!"); } + + // Crash reporting is synchronous but we want to let debuggerd + // go about it business right away, so we spin off the actual + // reporting logic on a thread and let it take it's time. + final String reportString = new String(os.toByteArray(), "UTF-8"); + (new NativeCrashReporter(pr, signal, gwpAsanRecoverableCrash, reportString)).start(); } catch (Exception e) { Slog.e(TAG, "Exception dealing with report", e); // ugh, fail. diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java index a74f4154eb85..210fc910ef57 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java +++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java @@ -1209,6 +1209,9 @@ public class AudioDeviceInventory { "LE Audio device addr=" + address + " now available").printLog(TAG)); } + // Reset LEA suspend state each time a new sink is connected + mAudioSystem.setParameters("LeAudioSuspended=false"); + mConnectedDevices.put(DeviceInfo.makeDeviceListKey(device, address), new DeviceInfo(device, name, address, AudioSystem.AUDIO_FORMAT_DEFAULT)); mDeviceBroker.postAccessoryPlugMediaUnmute(device); @@ -1254,6 +1257,9 @@ public class AudioDeviceInventory { @GuardedBy("mDevicesLock") private void makeLeAudioDeviceUnavailableLater(String address, int device, int delayMs) { + // prevent any activity on the LEA output to avoid unwanted + // reconnection of the sink. + mAudioSystem.setParameters("LeAudioSuspended=true"); // the device will be made unavailable later, so consider it disconnected right away mConnectedDevices.remove(DeviceInfo.makeDeviceListKey(device, address)); // send the delayed message to make the device unavailable later diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 46ab3304c46e..a7c2ddf1b9d3 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -896,7 +896,7 @@ public class AudioService extends IAudioService.Stub // Defines the format for the connection "address" for ALSA devices public static String makeAlsaAddressString(int card, int device) { - return "card=" + card + ";device=" + device + ";"; + return "card=" + card + ";device=" + device; } public static final class Lifecycle extends SystemService { @@ -4087,13 +4087,14 @@ public class AudioService extends IAudioService.Stub return; } - // Forcefully set LE audio volume as a workaround, since in some cases - // (like the outgoing call) the value of 'device' is not DEVICE_OUT_BLE_* - // even when BLE is connected. + // In some cases (like the outgoing or rejected call) the value of 'device' is not + // DEVICE_OUT_BLE_* even when BLE is connected. Changing the volume level in such case + // may cuase the other devices volume level leaking into the LeAudio device settings. if (!AudioSystem.isLeAudioDeviceType(device)) { - Log.w(TAG, "setLeAudioVolumeOnModeUpdate got unexpected device=" + device - + ", forcing to device=" + AudioSystem.DEVICE_OUT_BLE_HEADSET); - device = AudioSystem.DEVICE_OUT_BLE_HEADSET; + Log.w(TAG, "setLeAudioVolumeOnModeUpdate ignoring invalid device=" + + device + ", mode=" + mode + ", index=" + index + " maxIndex=" + maxIndex + + " streamType=" + streamType); + return; } if (DEBUG_VOL) { diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java index 6cd42f87aede..d3b76065f998 100644 --- a/services/core/java/com/android/server/audio/BtHelper.java +++ b/services/core/java/com/android/server/audio/BtHelper.java @@ -477,6 +477,7 @@ public class BtHelper { mScoAudioState = SCO_STATE_INACTIVE; broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); AudioSystem.setParameters("A2dpSuspended=false"); + AudioSystem.setParameters("LeAudioSuspended=false"); mDeviceBroker.setBluetoothScoOn(false, "resetBluetoothSco"); } diff --git a/services/core/java/com/android/server/soundtrigger_middleware/OWNERS b/services/core/java/com/android/server/soundtrigger_middleware/OWNERS index 01b2cb981bbb..1e41886fe716 100644 --- a/services/core/java/com/android/server/soundtrigger_middleware/OWNERS +++ b/services/core/java/com/android/server/soundtrigger_middleware/OWNERS @@ -1,2 +1 @@ -atneya@google.com -elaurent@google.com +include /media/java/android/media/soundtrigger/OWNERS diff --git a/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java b/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java index 2141eba3be50..7f129ea3801c 100644 --- a/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java +++ b/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java @@ -171,6 +171,18 @@ class NetworkPriorityClassifier { return false; } + for (Map.Entry<Integer, Integer> entry : + networkPriority.getCapabilitiesMatchCriteria().entrySet()) { + final int cap = entry.getKey(); + final int matchCriteria = entry.getValue(); + + if (matchCriteria == MATCH_REQUIRED && !caps.hasCapability(cap)) { + return false; + } else if (matchCriteria == MATCH_FORBIDDEN && caps.hasCapability(cap)) { + return false; + } + } + if (vcnContext.isInTestMode() && caps.hasTransport(TRANSPORT_TEST)) { return true; } @@ -319,18 +331,6 @@ class NetworkPriorityClassifier { return false; } - for (Map.Entry<Integer, Integer> entry : - networkPriority.getCapabilitiesMatchCriteria().entrySet()) { - final int cap = entry.getKey(); - final int matchCriteria = entry.getValue(); - - if (matchCriteria == MATCH_REQUIRED && !caps.hasCapability(cap)) { - return false; - } else if (matchCriteria == MATCH_FORBIDDEN && caps.hasCapability(cap)) { - return false; - } - } - return true; } diff --git a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS index 33385afbdfd6..1e41886fe716 100644 --- a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS +++ b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS @@ -1 +1 @@ -include /media/aidl/android/media/soundtrigger_middleware/OWNERS +include /media/java/android/media/soundtrigger/OWNERS diff --git a/services/voiceinteraction/OWNERS b/services/voiceinteraction/OWNERS index ef1061b28b63..40e8d26931e1 100644 --- a/services/voiceinteraction/OWNERS +++ b/services/voiceinteraction/OWNERS @@ -1 +1,2 @@ include /core/java/android/service/voice/OWNERS +include /media/java/android/media/soundtrigger/OWNERS diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS b/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS index 01b2cb981bbb..1e41886fe716 100644 --- a/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS +++ b/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS @@ -1,2 +1 @@ -atneya@google.com -elaurent@google.com +include /media/java/android/media/soundtrigger/OWNERS diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 33e6fa70ffd1..03e019d2edde 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -1214,8 +1214,13 @@ public class ServiceState implements Parcelable { /** * Initialize the service state. Set everything to the default value. + * + * @param legacyMode {@code true} if the device is on IWLAN legacy mode, where IWLAN is + * considered as a RAT on WWAN {@link NetworkRegistrationInfo}. {@code false} if the device + * is on AP-assisted mode, where IWLAN should be reported through WLAN. + * {@link NetworkRegistrationInfo}. */ - private void init() { + private void init(boolean legacyMode) { if (DBG) Rlog.d(LOG_TAG, "init"); mVoiceRegState = STATE_OUT_OF_SERVICE; mDataRegState = STATE_OUT_OF_SERVICE; @@ -1247,11 +1252,13 @@ public class ServiceState implements Parcelable { .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN) .build()); - addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder() - .setDomain(NetworkRegistrationInfo.DOMAIN_PS) - .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN) - .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN) - .build()); + if (!legacyMode) { + addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder() + .setDomain(NetworkRegistrationInfo.DOMAIN_PS) + .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN) + .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN) + .build()); + } } mOperatorAlphaLongRaw = null; mOperatorAlphaShortRaw = null; @@ -1260,11 +1267,11 @@ public class ServiceState implements Parcelable { } public void setStateOutOfService() { - init(); + init(true); } public void setStateOff() { - init(); + init(true); mVoiceRegState = STATE_POWER_OFF; mDataRegState = STATE_POWER_OFF; } @@ -1272,11 +1279,14 @@ public class ServiceState implements Parcelable { /** * Set the service state to out-of-service * + * @param legacyMode {@code true} if the device is on IWLAN legacy mode, where IWLAN is + * considered as a RAT on WWAN {@link NetworkRegistrationInfo}. {@code false} if the device + * is on AP-assisted mode, where IWLAN should be reported through WLAN. * @param powerOff {@code true} if this is a power off case (i.e. Airplane mode on). * @hide */ - public void setOutOfService(boolean powerOff) { - init(); + public void setOutOfService(boolean legacyMode, boolean powerOff) { + init(legacyMode); if (powerOff) { mVoiceRegState = STATE_POWER_OFF; mDataRegState = STATE_POWER_OFF; diff --git a/tests/SoundTriggerTestApp/OWNERS b/tests/SoundTriggerTestApp/OWNERS index 9db19a37812b..a0fcfc52704d 100644 --- a/tests/SoundTriggerTestApp/OWNERS +++ b/tests/SoundTriggerTestApp/OWNERS @@ -1,2 +1,2 @@ -include /core/java/android/media/soundtrigger/OWNERS +include /media/java/android/media/soundtrigger/OWNERS mdooley@google.com diff --git a/tests/SoundTriggerTests/OWNERS b/tests/SoundTriggerTests/OWNERS index 816bc6bba639..1e41886fe716 100644 --- a/tests/SoundTriggerTests/OWNERS +++ b/tests/SoundTriggerTests/OWNERS @@ -1 +1 @@ -include /core/java/android/media/soundtrigger/OWNERS +include /media/java/android/media/soundtrigger/OWNERS diff --git a/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java b/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java new file mode 100644 index 000000000000..b94bb41c0988 --- /dev/null +++ b/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2023 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.test; + +import static android.permission.PermissionManager.PERMISSION_GRANTED; +import static android.permission.PermissionManager.PERMISSION_HARD_DENIED; + +import android.annotation.NonNull; +import android.content.AttributionSource; +import android.os.PermissionEnforcer; + +import java.util.HashSet; +import java.util.Set; + +/** + * Fake for {@link PermissionEnforcer}. Useful for tests wanting to mock the + * permission checks of an AIDL service. FakePermissionEnforcer may be passed + * to the constructor of the AIDL-generated Stub class. + * + */ +public class FakePermissionEnforcer extends PermissionEnforcer { + private Set<String> mGranted; + + public FakePermissionEnforcer() { + mGranted = new HashSet(); + } + + public void grant(String permission) { + mGranted.add(permission); + } + + public void revoke(String permission) { + mGranted.remove(permission); + } + + private boolean granted(String permission) { + return mGranted.contains(permission); + } + + @Override + protected int checkPermission(@NonNull String permission, + @NonNull AttributionSource source) { + return granted(permission) ? PERMISSION_GRANTED : PERMISSION_HARD_DENIED; + } + + @Override + protected int checkPermission(@NonNull String permission, int pid, int uid) { + return granted(permission) ? PERMISSION_GRANTED : PERMISSION_HARD_DENIED; + } +} diff --git a/tests/utils/testutils/java/android/os/test/OWNERS b/tests/utils/testutils/java/android/os/test/OWNERS new file mode 100644 index 000000000000..3a9129e1bb69 --- /dev/null +++ b/tests/utils/testutils/java/android/os/test/OWNERS @@ -0,0 +1 @@ +per-file FakePermissionEnforcer.java = file:/tests/EnforcePermission/OWNERS diff --git a/tests/vcn/java/android/net/vcn/VcnConfigTest.java b/tests/vcn/java/android/net/vcn/VcnConfigTest.java index b313c9fc6c28..73a0a6183cb6 100644 --- a/tests/vcn/java/android/net/vcn/VcnConfigTest.java +++ b/tests/vcn/java/android/net/vcn/VcnConfigTest.java @@ -17,6 +17,7 @@ package android.net.vcn; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; +import static android.net.NetworkCapabilities.TRANSPORT_TEST; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static org.junit.Assert.assertEquals; @@ -160,6 +161,37 @@ public class VcnConfigTest { assertNotEquals(config, configNotEqual); } + private VcnConfig buildConfigRestrictTransportTest(boolean isTestMode) throws Exception { + VcnConfig.Builder builder = + new VcnConfig.Builder(mContext) + .setRestrictedUnderlyingNetworkTransports(Set.of(TRANSPORT_TEST)); + if (isTestMode) { + builder.setIsTestModeProfile(); + } + + for (VcnGatewayConnectionConfig gatewayConnectionConfig : GATEWAY_CONNECTION_CONFIGS) { + builder.addGatewayConnectionConfig(gatewayConnectionConfig); + } + + return builder.build(); + } + + @Test + public void testRestrictTransportTestInTestModeProfile() throws Exception { + final VcnConfig config = buildConfigRestrictTransportTest(true /* isTestMode */); + assertEquals(Set.of(TRANSPORT_TEST), config.getRestrictedUnderlyingNetworkTransports()); + } + + @Test + public void testRestrictTransportTestInNonTestModeProfile() throws Exception { + try { + buildConfigRestrictTransportTest(false /* isTestMode */); + fail("Expected exception because the config is not a test mode profile"); + } catch (Exception expected) { + + } + } + @Test public void testParceling() { final VcnConfig config = buildTestConfig(mContext); diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java index 629e988495cc..226604108522 100644 --- a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java +++ b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java @@ -95,6 +95,7 @@ public class NetworkPriorityClassifierTest { private static final NetworkCapabilities WIFI_NETWORK_CAPABILITIES = new NetworkCapabilities.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .setSignalStrength(WIFI_RSSI) .setSsid(SSID) .setLinkUpstreamBandwidthKbps(LINK_UPSTREAM_BANDWIDTH_KBPS) @@ -509,12 +510,14 @@ public class NetworkPriorityClassifierTest { VcnCellUnderlyingNetworkTemplate template, boolean expectMatch) { assertEquals( expectMatch, - checkMatchesCellPriorityRule( + checkMatchesPriorityRule( mVcnContext, template, mCellNetworkRecord, SUB_GROUP, - mSubscriptionSnapshot)); + mSubscriptionSnapshot, + null /* currentlySelected */, + null /* carrierConfig */)); } @Test |