diff options
47 files changed, 912 insertions, 376 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 38ffc1990ad5..8710e613602f 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -20300,6 +20300,10 @@ package android.media { field @NonNull public static final android.media.AudioMetadata.Key<java.lang.Integer> KEY_BIT_WIDTH; field @NonNull public static final android.media.AudioMetadata.Key<java.lang.Integer> KEY_CHANNEL_MASK; field @NonNull public static final android.media.AudioMetadata.Key<java.lang.String> KEY_MIME; + field @NonNull public static final android.media.AudioMetadata.Key<java.lang.Integer> KEY_PRESENTATION_CONTENT_CLASSIFIER; + field @NonNull public static final android.media.AudioMetadata.Key<java.lang.Integer> KEY_PRESENTATION_ID; + field @NonNull public static final android.media.AudioMetadata.Key<java.lang.String> KEY_PRESENTATION_LANGUAGE; + field @NonNull public static final android.media.AudioMetadata.Key<java.lang.Integer> KEY_PROGRAM_ID; field @NonNull public static final android.media.AudioMetadata.Key<java.lang.Integer> KEY_SAMPLE_RATE; } @@ -20354,6 +20358,15 @@ package android.media { method public boolean hasAudioDescription(); method public boolean hasDialogueEnhancement(); method public boolean hasSpokenSubtitles(); + field public static final int CONTENT_COMMENTARY = 5; // 0x5 + field public static final int CONTENT_DIALOG = 4; // 0x4 + field public static final int CONTENT_EMERGENCY = 6; // 0x6 + field public static final int CONTENT_HEARING_IMPAIRED = 3; // 0x3 + field public static final int CONTENT_MAIN = 0; // 0x0 + field public static final int CONTENT_MUSIC_AND_EFFECTS = 1; // 0x1 + field public static final int CONTENT_UNKNOWN = -1; // 0xffffffff + field public static final int CONTENT_VISUALLY_IMPAIRED = 2; // 0x2 + field public static final int CONTENT_VOICEOVER = 7; // 0x7 field public static final int MASTERED_FOR_3D = 3; // 0x3 field public static final int MASTERED_FOR_HEADPHONE = 4; // 0x4 field public static final int MASTERED_FOR_STEREO = 1; // 0x1 diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 60325b3cbd37..91ccefee5d54 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -44,6 +44,14 @@ package android.app { } +package android.app.usage { + + public class NetworkStatsManager { + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void notifyNetworkStatus(@NonNull java.util.List<android.net.Network>, @NonNull java.util.List<android.net.NetworkStateSnapshot>, @Nullable String, @NonNull java.util.List<android.net.UnderlyingNetworkInfo>); + } + +} + package android.content { public abstract class Context { diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 59bc9bda1205..019e7ffe11ef 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -1888,11 +1888,18 @@ package android.bluetooth { field public static final int ACCESS_REJECTED = 2; // 0x2 field public static final int ACCESS_UNKNOWN = 0; // 0x0 field public static final String ACTION_SILENCE_MODE_CHANGED = "android.bluetooth.device.action.SILENCE_MODE_CHANGED"; + field public static final String DEVICE_TYPE_DEFAULT = "Default"; + field public static final String DEVICE_TYPE_UNTETHERED_HEADSET = "Untethered Headset"; + field public static final String DEVICE_TYPE_WATCH = "Watch"; field public static final int METADATA_COMPANION_APP = 4; // 0x4 + field public static final int METADATA_DEVICE_TYPE = 17; // 0x11 field public static final int METADATA_ENHANCED_SETTINGS_UI_URI = 16; // 0x10 field public static final int METADATA_HARDWARE_VERSION = 3; // 0x3 field public static final int METADATA_IS_UNTETHERED_HEADSET = 6; // 0x6 + field public static final int METADATA_MAIN_BATTERY = 18; // 0x12 + field public static final int METADATA_MAIN_CHARGING = 19; // 0x13 field public static final int METADATA_MAIN_ICON = 5; // 0x5 + field public static final int METADATA_MAIN_LOW_BATTERY_THRESHOLD = 20; // 0x14 field public static final int METADATA_MANUFACTURER_NAME = 0; // 0x0 field public static final int METADATA_MAX_LENGTH = 2048; // 0x800 field public static final int METADATA_MODEL_NAME = 1; // 0x1 @@ -1900,12 +1907,15 @@ package android.bluetooth { field public static final int METADATA_UNTETHERED_CASE_BATTERY = 12; // 0xc field public static final int METADATA_UNTETHERED_CASE_CHARGING = 15; // 0xf field public static final int METADATA_UNTETHERED_CASE_ICON = 9; // 0x9 + field public static final int METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD = 23; // 0x17 field public static final int METADATA_UNTETHERED_LEFT_BATTERY = 10; // 0xa field public static final int METADATA_UNTETHERED_LEFT_CHARGING = 13; // 0xd field public static final int METADATA_UNTETHERED_LEFT_ICON = 7; // 0x7 + field public static final int METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD = 21; // 0x15 field public static final int METADATA_UNTETHERED_RIGHT_BATTERY = 11; // 0xb field public static final int METADATA_UNTETHERED_RIGHT_CHARGING = 14; // 0xe field public static final int METADATA_UNTETHERED_RIGHT_ICON = 8; // 0x8 + field public static final int METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD = 22; // 0x16 } public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile { diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS index 1ff64dbe6d2e..e0e9b62d3809 100644 --- a/core/java/android/app/OWNERS +++ b/core/java/android/app/OWNERS @@ -73,6 +73,7 @@ per-file ClientTransactionHandler.java = file:/services/core/java/com/android/se per-file Fragment.java = file:/services/core/java/com/android/server/wm/OWNERS per-file *Task* = file:/services/core/java/com/android/server/wm/OWNERS per-file Window* = file:/services/core/java/com/android/server/wm/OWNERS +per-file ConfigurationController.java = file:/services/core/java/com/android/server/wm/OWNERS # TODO(b/174932174): determine the ownership of KeyguardManager.java diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 1d5dc1d5df1c..098d8b6c6058 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -16,6 +16,8 @@ package android.app.usage; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; + import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -28,8 +30,11 @@ import android.content.Context; import android.net.ConnectivityManager; import android.net.DataUsageRequest; import android.net.INetworkStatsService; +import android.net.Network; import android.net.NetworkStack; +import android.net.NetworkStateSnapshot; import android.net.NetworkTemplate; +import android.net.UnderlyingNetworkInfo; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; import android.os.Binder; @@ -48,6 +53,7 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.net.module.util.NetworkIdentityUtils; +import java.util.List; import java.util.Objects; /** @@ -633,6 +639,50 @@ public class NetworkStatsManager { return template; } + /** + * Notify {@code NetworkStatsService} about network status changed. + * + * Notifies NetworkStatsService of network state changes for data usage accounting purposes. + * + * To avoid races that attribute data usage to wrong network, such as new network with + * the same interface after SIM hot-swap, this function will not return until + * {@code NetworkStatsService} finishes its work of retrieving traffic statistics from + * all data sources. + * + * @param defaultNetworks the list of all networks that could be used by network traffic that + * does not explicitly select a network. + * @param networkStateSnapshots a list of {@link NetworkStateSnapshot}s, one for + * each network that is currently connected. + * @param activeIface the active (i.e., connected) default network interface for the calling + * uid. Used to determine on which network future calls to + * {@link android.net.TrafficStats#incrementOperationCount} applies to. + * @param underlyingNetworkInfos the list of underlying network information for all + * currently-connected VPNs. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK}) + public void notifyNetworkStatus( + @NonNull List<Network> defaultNetworks, + @NonNull List<NetworkStateSnapshot> networkStateSnapshots, + @Nullable String activeIface, + @NonNull List<UnderlyingNetworkInfo> underlyingNetworkInfos) { + try { + Objects.requireNonNull(defaultNetworks); + Objects.requireNonNull(networkStateSnapshots); + Objects.requireNonNull(underlyingNetworkInfos); + // TODO: Change internal namings after the name is decided. + mService.forceUpdateIfaces(defaultNetworks.toArray(new Network[0]), + networkStateSnapshots.toArray(new NetworkStateSnapshot[0]), activeIface, + underlyingNetworkInfos.toArray(new UnderlyingNetworkInfo[0])); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + private static class CallbackHandler extends Handler { private final int mNetworkType; private final String mSubscriberId; diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index e7661dbad749..ec94faa544d3 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -374,6 +374,35 @@ public final class BluetoothDevice implements Parcelable { public static final String ACTION_SDP_RECORD = "android.bluetooth.device.action.SDP_RECORD"; + /** @hide */ + @IntDef(prefix = "METADATA_", value = { + METADATA_MANUFACTURER_NAME, + METADATA_MODEL_NAME, + METADATA_SOFTWARE_VERSION, + METADATA_HARDWARE_VERSION, + METADATA_COMPANION_APP, + METADATA_MAIN_ICON, + METADATA_IS_UNTETHERED_HEADSET, + METADATA_UNTETHERED_LEFT_ICON, + METADATA_UNTETHERED_RIGHT_ICON, + METADATA_UNTETHERED_CASE_ICON, + METADATA_UNTETHERED_LEFT_BATTERY, + METADATA_UNTETHERED_RIGHT_BATTERY, + METADATA_UNTETHERED_CASE_BATTERY, + METADATA_UNTETHERED_LEFT_CHARGING, + METADATA_UNTETHERED_RIGHT_CHARGING, + METADATA_UNTETHERED_CASE_CHARGING, + METADATA_ENHANCED_SETTINGS_UI_URI, + METADATA_DEVICE_TYPE, + METADATA_MAIN_BATTERY, + METADATA_MAIN_CHARGING, + METADATA_MAIN_LOW_BATTERY_THRESHOLD, + METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD, + METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD, + METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD}) + @Retention(RetentionPolicy.SOURCE) + public @interface MetadataKey{} + /** * Maximum length of a metadata entry, this is to avoid exploding Bluetooth * disk usage @@ -523,6 +552,89 @@ public final class BluetoothDevice implements Parcelable { public static final int METADATA_ENHANCED_SETTINGS_UI_URI = 16; /** + * Type of the Bluetooth device, must be within the list of + * BluetoothDevice.DEVICE_TYPE_* + * Data type should be {@String} as {@link Byte} array. + * @hide + */ + @SystemApi + public static final int METADATA_DEVICE_TYPE = 17; + + /** + * Battery level of the Bluetooth device, use when the Bluetooth device + * does not support HFP battery indicator. + * Data type should be {@String} as {@link Byte} array. + * @hide + */ + @SystemApi + public static final int METADATA_MAIN_BATTERY = 18; + + /** + * Whether the device is charging. + * Data type should be {@String} as {@link Byte} array. + * @hide + */ + @SystemApi + public static final int METADATA_MAIN_CHARGING = 19; + + /** + * The battery threshold of the Bluetooth device to show low battery icon. + * Data type should be {@String} as {@link Byte} array. + * @hide + */ + @SystemApi + public static final int METADATA_MAIN_LOW_BATTERY_THRESHOLD = 20; + + /** + * The battery threshold of the left headset to show low battery icon. + * Data type should be {@String} as {@link Byte} array. + * @hide + */ + @SystemApi + public static final int METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD = 21; + + /** + * The battery threshold of the right headset to show low battery icon. + * Data type should be {@String} as {@link Byte} array. + * @hide + */ + @SystemApi + public static final int METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD = 22; + + /** + * The battery threshold of the case to show low battery icon. + * Data type should be {@String} as {@link Byte} array. + * @hide + */ + @SystemApi + public static final int METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD = 23; + + /** + * Device type which is used in METADATA_DEVICE_TYPE + * Indicates this Bluetooth device is a standard Bluetooth accessory or + * not listed in METADATA_DEVICE_TYPE_*. + * @hide + */ + @SystemApi + public static final String DEVICE_TYPE_DEFAULT = "Default"; + + /** + * Device type which is used in METADATA_DEVICE_TYPE + * Indicates this Bluetooth device is a watch. + * @hide + */ + @SystemApi + public static final String DEVICE_TYPE_WATCH = "Watch"; + + /** + * Device type which is used in METADATA_DEVICE_TYPE + * Indicates this Bluetooth device is an untethered headset. + * @hide + */ + @SystemApi + public static final String DEVICE_TYPE_UNTETHERED_HEADSET = "Untethered Headset"; + + /** * Broadcast Action: This intent is used to broadcast the {@link UUID} * wrapped as a {@link android.os.ParcelUuid} of the remote device after it * has been fetched. This intent is sent only when the UUIDs of the remote @@ -2316,7 +2428,7 @@ public final class BluetoothDevice implements Parcelable { */ @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) - public boolean setMetadata(int key, @NonNull byte[] value) { + public boolean setMetadata(@MetadataKey int key, @NonNull byte[] value) { final IBluetooth service = sService; if (service == null) { Log.e(TAG, "Bluetooth is not enabled. Cannot set metadata"); @@ -2344,7 +2456,7 @@ public final class BluetoothDevice implements Parcelable { @SystemApi @Nullable @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) - public byte[] getMetadata(int key) { + public byte[] getMetadata(@MetadataKey int key) { final IBluetooth service = sService; if (service == null) { Log.e(TAG, "Bluetooth is not enabled. Cannot get metadata"); @@ -2357,4 +2469,14 @@ public final class BluetoothDevice implements Parcelable { return null; } } + + /** + * Get the maxinum metadata key ID. + * + * @return the last supported metadata key + * @hide + */ + public static @MetadataKey int getMaxMetadataKey() { + return METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD; + } } diff --git a/core/java/android/view/ImeFocusController.java b/core/java/android/view/ImeFocusController.java index 4a5c95f43d46..d23a1e5992cc 100644 --- a/core/java/android/view/ImeFocusController.java +++ b/core/java/android/view/ImeFocusController.java @@ -116,8 +116,9 @@ public final class ImeFocusController { if (!hasWindowFocus || !mHasImeFocus || isInLocalFocusMode(windowAttribute)) { return; } + View viewForWindowFocus = focusedView != null ? focusedView : mViewRootImpl.mView; if (DEBUG) { - Log.v(TAG, "onWindowFocus: " + focusedView + Log.v(TAG, "onWindowFocus: " + viewForWindowFocus + " softInputMode=" + InputMethodDebug.softInputModeToString( windowAttribute.softInputMode)); } @@ -128,8 +129,8 @@ public final class ImeFocusController { if (DEBUG) Log.v(TAG, "Restarting due to isRestartOnNextWindowFocus as true"); forceFocus = true; } + // Update mNextServedView when focusedView changed. - final View viewForWindowFocus = focusedView != null ? focusedView : mViewRootImpl.mView; onViewFocusChanged(viewForWindowFocus, true); // Starting new input when the next focused view is same as served view but the currently diff --git a/core/java/com/android/internal/inputmethod/InputMethodDebug.java b/core/java/com/android/internal/inputmethod/InputMethodDebug.java index c353de88dc3b..93374ba0cf46 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodDebug.java +++ b/core/java/com/android/internal/inputmethod/InputMethodDebug.java @@ -228,6 +228,8 @@ public final class InputMethodDebug { return "HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR"; case SoftInputShowHideReason.HIDE_REMOVE_CLIENT: return "HIDE_REMOVE_CLIENT"; + case SoftInputShowHideReason.SHOW_RESTORE_IME_VISIBILITY: + return "SHOW_RESTORE_IME_VISIBILITY"; default: return "Unknown=" + reason; } diff --git a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java index 1553e2eb0793..f1cdf2b38c4c 100644 --- a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java +++ b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java @@ -49,7 +49,8 @@ import java.lang.annotation.Retention; SoftInputShowHideReason.HIDE_RECENTS_ANIMATION, SoftInputShowHideReason.HIDE_BUBBLES, SoftInputShowHideReason.HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR, - SoftInputShowHideReason.HIDE_REMOVE_CLIENT}) + SoftInputShowHideReason.HIDE_REMOVE_CLIENT, + SoftInputShowHideReason.SHOW_RESTORE_IME_VISIBILITY}) public @interface SoftInputShowHideReason { /** Show soft input by {@link android.view.inputmethod.InputMethodManager#showSoftInput}. */ int SHOW_SOFT_INPUT = 0; @@ -167,4 +168,10 @@ public @interface SoftInputShowHideReason { * Hide soft input when a {@link com.android.internal.view.IInputMethodClient} is removed. */ int HIDE_REMOVE_CLIENT = 21; + + /** + * Show soft input when the system invoking + * {@link com.android.server.wm.WindowManagerInternal#shouldRestoreImeVisibility}. + */ + int SHOW_RESTORE_IME_VISIBILITY = 22; } diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index c9062d8a50bc..bcfb06b15ab8 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -304,15 +304,14 @@ static std::array<UsapTableEntry, USAP_POOL_SIZE_MAX_LIMIT> gUsapTable; static FileDescriptorTable* gOpenFdTable = nullptr; // Must match values in com.android.internal.os.Zygote. -// Note that there are gaps in the constants: -// This is to further keep the values consistent with IVold.aidl +// The values should be consistent with IVold.aidl enum MountExternalKind { MOUNT_EXTERNAL_NONE = 0, MOUNT_EXTERNAL_DEFAULT = 1, - MOUNT_EXTERNAL_INSTALLER = 5, - MOUNT_EXTERNAL_PASS_THROUGH = 7, - MOUNT_EXTERNAL_ANDROID_WRITABLE = 8, - MOUNT_EXTERNAL_COUNT = 9 + MOUNT_EXTERNAL_INSTALLER = 2, + MOUNT_EXTERNAL_PASS_THROUGH = 3, + MOUNT_EXTERNAL_ANDROID_WRITABLE = 4, + MOUNT_EXTERNAL_COUNT = 5 }; // Must match values in com.android.internal.os.Zygote. diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto index ec502c3c272f..f26bf7cdb6c1 100644 --- a/core/proto/android/server/windowmanagerservice.proto +++ b/core/proto/android/server/windowmanagerservice.proto @@ -337,7 +337,7 @@ message ActivityRecordProto { optional bool starting_displayed = 20; optional bool starting_moved = 201; optional bool visible_set_from_transferred_starting_window = 22; - repeated .android.graphics.RectProto frozen_bounds = 23; + repeated .android.graphics.RectProto frozen_bounds = 23 [deprecated=true]; optional bool visible = 24; reserved 25; // configuration_container optional IdentifierProto identifier = 26 [deprecated=true]; diff --git a/media/java/android/media/AudioMetadata.java b/media/java/android/media/AudioMetadata.java index ff9fd4187272..ca175b4853a6 100644 --- a/media/java/android/media/AudioMetadata.java +++ b/media/java/android/media/AudioMetadata.java @@ -195,6 +195,61 @@ public final class AudioMetadata { @NonNull public static final Key<Integer> KEY_AUDIO_ENCODING = createKey("audio-encoding", Integer.class); + + /** + * A key representing the audio presentation id being decoded by a next generation + * audio decoder. + * + * An Integer value representing presentation id. + * + * @see AudioPresentation#getPresentationId() + */ + @NonNull public static final Key<Integer> KEY_PRESENTATION_ID = + createKey("presentation-id", Integer.class); + + /** + * A key representing the audio program id being decoded by a next generation + * audio decoder. + * + * An Integer value representing program id. + * + * @see AudioPresentation#getProgramId() + */ + @NonNull public static final Key<Integer> KEY_PROGRAM_ID = + createKey("program-id", Integer.class); + + + /** + * A key representing the audio presentation content classifier being rendered + * by a next generation audio decoder. + * + * An Integer value representing presentation content classifier. + * + * @see AudioPresentation.ContentClassifier + * One of {@link AudioPresentation#CONTENT_UNKNOWN}, + * {@link AudioPresentation#CONTENT_MAIN}, + * {@link AudioPresentation#CONTENT_MUSIC_AND_EFFECTS}, + * {@link AudioPresentation#CONTENT_VISUALLY_IMPAIRED}, + * {@link AudioPresentation#CONTENT_HEARING_IMPAIRED}, + * {@link AudioPresentation#CONTENT_DIALOG}, + * {@link AudioPresentation#CONTENT_COMMENTARY}, + * {@link AudioPresentation#CONTENT_EMERGENCY}, + * {@link AudioPresentation#CONTENT_VOICEOVER}. + */ + @NonNull public static final Key<Integer> KEY_PRESENTATION_CONTENT_CLASSIFIER = + createKey("presentation-content-classifier", Integer.class); + + /** + * A key representing the audio presentation language being rendered by a next + * generation audio decoder. + * + * A String value representing ISO 639-2 (three letter code). + * + * @see AudioPresentation#getLocale() + */ + @NonNull public static final Key<String> KEY_PRESENTATION_LANGUAGE = + createKey("presentation-language", String.class); + private Format() {} // delete constructor } diff --git a/media/java/android/media/AudioPresentation.java b/media/java/android/media/AudioPresentation.java index 894fbba6c983..47358be3e926 100644 --- a/media/java/android/media/AudioPresentation.java +++ b/media/java/android/media/AudioPresentation.java @@ -57,6 +57,64 @@ public final class AudioPresentation { /** @hide */ @IntDef( value = { + CONTENT_UNKNOWN, + CONTENT_MAIN, + CONTENT_MUSIC_AND_EFFECTS, + CONTENT_VISUALLY_IMPAIRED, + CONTENT_HEARING_IMPAIRED, + CONTENT_DIALOG, + CONTENT_COMMENTARY, + CONTENT_EMERGENCY, + CONTENT_VOICEOVER, + }) + + /** + * The ContentClassifier int definitions represent the AudioPresentation content + * classifier (as per TS 103 190-1 v1.2.1 4.3.3.8.1) + */ + @Retention(RetentionPolicy.SOURCE) + public @interface ContentClassifier {} + + /** + * Audio presentation classifier: Unknown. + */ + public static final int CONTENT_UNKNOWN = -1; + /** + * Audio presentation classifier: Complete main. + */ + public static final int CONTENT_MAIN = 0; + /** + * Audio presentation content classifier: Music and effects. + */ + public static final int CONTENT_MUSIC_AND_EFFECTS = 1; + /** + * Audio presentation content classifier: Visually impaired. + */ + public static final int CONTENT_VISUALLY_IMPAIRED = 2; + /** + * Audio presentation content classifier: Hearing impaired. + */ + public static final int CONTENT_HEARING_IMPAIRED = 3; + /** + * Audio presentation content classifier: Dialog. + */ + public static final int CONTENT_DIALOG = 4; + /** + * Audio presentation content classifier: Commentary. + */ + public static final int CONTENT_COMMENTARY = 5; + /** + * Audio presentation content classifier: Emergency. + */ + public static final int CONTENT_EMERGENCY = 6; + /** + * Audio presentation content classifier: Voice over. + */ + public static final int CONTENT_VOICEOVER = 7; + + /** @hide */ + @IntDef( + value = { MASTERING_NOT_INDICATED, MASTERED_FOR_STEREO, MASTERED_FOR_SURROUND, diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java index 7f19662c6961..c1dca5df1b2f 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java @@ -394,16 +394,20 @@ public class DynamicSystemInstallationService extends Service } private void executeNotifyIfInUseCommand() { - int status = getStatus(); - - if (status == STATUS_IN_USE) { - startForeground(NOTIFICATION_ID, - buildNotification(STATUS_IN_USE, CAUSE_NOT_SPECIFIED)); - } else if (status == STATUS_READY) { - startForeground(NOTIFICATION_ID, - buildNotification(STATUS_READY, CAUSE_NOT_SPECIFIED)); - } else { - stopSelf(); + switch (getStatus()) { + case STATUS_IN_USE: + startForeground(NOTIFICATION_ID, + buildNotification(STATUS_IN_USE, CAUSE_NOT_SPECIFIED)); + break; + case STATUS_READY: + startForeground(NOTIFICATION_ID, + buildNotification(STATUS_READY, CAUSE_NOT_SPECIFIED)); + break; + case STATUS_IN_PROGRESS: + break; + case STATUS_NOT_STARTED: + default: + stopSelf(); } } diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 761512ce3d14..4bdc16b050a8 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -91,9 +91,6 @@ <!-- The number of columns in the QuickSettings --> <integer name="quick_settings_num_columns">3</integer> - <!-- The number of columns in the Quick Settings customizer --> - <integer name="quick_settings_edit_num_columns">@integer/quick_settings_num_columns</integer> - <!-- The number of rows in the QuickSettings --> <integer name="quick_settings_max_rows">3</integer> diff --git a/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt index c3cc3af10e83..52f111e7ab48 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt @@ -18,7 +18,6 @@ package com.android.systemui.qs import android.content.Context import android.util.AttributeSet -import com.android.systemui.R open class SideLabelTileLayout( context: Context, @@ -28,9 +27,6 @@ open class SideLabelTileLayout( override fun updateResources(): Boolean { return super.updateResources().also { mMaxAllowedRows = 4 - mCellMarginHorizontal = (mCellMarginHorizontal * 1.2).toInt() - mCellMarginVertical = mCellMarginHorizontal - mMaxCellHeight = context.resources.getDimensionPixelSize(R.dimen.qs_quick_tile_size) } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java index 47cb45b14b9b..ce8f6c1737d7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java @@ -16,19 +16,19 @@ package com.android.systemui.qs.customize; import android.content.Context; import android.view.View; -import android.widget.TextView; import com.android.systemui.plugins.qs.QSIconView; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.qs.tileimpl.QSTileView; -public class CustomizeTileView extends QSTileView { +public class CustomizeTileView extends QSTileView implements TileAdapter.CustomizeView { private boolean mShowAppLabel; public CustomizeTileView(Context context, QSIconView icon) { super(context, icon); } + @Override public void setShowAppLabel(boolean showAppLabel) { mShowAppLabel = showAppLabel; mSecondLine.setVisibility(showAppLabel ? View.VISIBLE : View.GONE); @@ -41,10 +41,6 @@ public class CustomizeTileView extends QSTileView { mSecondLine.setVisibility(mShowAppLabel ? View.VISIBLE : View.GONE); } - public TextView getAppLabel() { - return mSecondLine; - } - @Override protected boolean animationsEnabled() { return false; @@ -54,4 +50,9 @@ public class CustomizeTileView extends QSTileView { public boolean isLongClickable() { return false; } + + @Override + public void changeState(QSTile.State state) { + handleStateChanged(state); + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileViewHorizontal.kt b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileViewHorizontal.kt new file mode 100644 index 000000000000..4ffcd8cdd9ce --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileViewHorizontal.kt @@ -0,0 +1,50 @@ +package com.android.systemui.qs.customize + +import android.content.Context +import android.graphics.drawable.Drawable +import android.view.View +import com.android.systemui.plugins.qs.QSIconView +import com.android.systemui.plugins.qs.QSTile +import com.android.systemui.qs.tileimpl.QSTileViewHorizontal + +/** + * Class for displaying tiles in [QSCustomizer] with the new design (labels on the side). + * + * This is a class parallel to [CustomizeTileView], but inheriting from [QSTileViewHorizontal]. + */ +class CustomizeTileViewHorizontal( + context: Context, + icon: QSIconView +) : QSTileViewHorizontal(context, icon), + TileAdapter.CustomizeView { + + private var showAppLabel = false + + override fun setShowAppLabel(showAppLabel: Boolean) { + this.showAppLabel = showAppLabel + mSecondLine.visibility = if (showAppLabel) View.VISIBLE else View.GONE + mLabel.isSingleLine = showAppLabel + } + + override fun handleStateChanged(state: QSTile.State) { + super.handleStateChanged(state) + mSecondLine.visibility = if (showAppLabel) View.VISIBLE else View.GONE + } + + override fun animationsEnabled(): Boolean { + return false + } + + override fun isLongClickable(): Boolean { + return false + } + + override fun changeState(state: QSTile.State) { + handleStateChanged(state) + } + + override fun newTileBackground(): Drawable? { + super.newTileBackground() + return paintDrawable + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java index 7a91421b00a1..0adc8448b89f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java @@ -14,6 +14,8 @@ package com.android.systemui.qs.customize; +import static com.android.systemui.qs.dagger.QSFlagsModule.QS_LABELS_FLAG; + import android.content.ComponentName; import android.content.Context; import android.content.res.Resources; @@ -30,6 +32,7 @@ import android.widget.FrameLayout; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.core.view.AccessibilityDelegateCompat; import androidx.core.view.ViewCompat; import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup; @@ -41,6 +44,7 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder; import com.android.internal.logging.UiEventLogger; import com.android.systemui.R; +import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.qs.QSEditEvent; import com.android.systemui.qs.QSTileHost; import com.android.systemui.qs.customize.TileAdapter.Holder; @@ -49,11 +53,13 @@ import com.android.systemui.qs.customize.TileQueryHelper.TileStateListener; import com.android.systemui.qs.dagger.QSScope; import com.android.systemui.qs.external.CustomTile; import com.android.systemui.qs.tileimpl.QSIconViewImpl; +import com.android.systemui.qs.tileimpl.QSTileView; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; +import javax.inject.Named; /** */ @QSScope @@ -75,7 +81,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta private static final int ACTION_ADD = 1; private static final int ACTION_MOVE = 2; - private static final int NUM_COLUMNS_ID = R.integer.quick_settings_edit_num_columns; + private static final int NUM_COLUMNS_ID = R.integer.quick_settings_num_columns; private final Context mContext; @@ -102,9 +108,11 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta private final AccessibilityDelegateCompat mAccessibilityDelegate; private RecyclerView mRecyclerView; private int mNumColumns; + private final boolean mUseHorizontalTiles; @Inject - public TileAdapter(Context context, QSTileHost qsHost, UiEventLogger uiEventLogger) { + public TileAdapter(Context context, QSTileHost qsHost, UiEventLogger uiEventLogger, + @Named(QS_LABELS_FLAG) boolean useHorizontalTiles) { mContext = context; mHost = qsHost; mUiEventLogger = uiEventLogger; @@ -114,6 +122,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta mMinNumTiles = context.getResources().getInteger(R.integer.quick_settings_min_num_tiles); mNumColumns = context.getResources().getInteger(NUM_COLUMNS_ID); mAccessibilityDelegate = new TileAdapterDelegate(); + mUseHorizontalTiles = useHorizontalTiles; } @Override @@ -271,7 +280,10 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta } FrameLayout frame = (FrameLayout) inflater.inflate(R.layout.qs_customize_tile_frame, parent, false); - frame.addView(new CustomizeTileView(context, new QSIconViewImpl(context))); + View view = mUseHorizontalTiles + ? new CustomizeTileViewHorizontal(context, new QSIconViewImpl(context)) + : new CustomizeTileView(context, new QSIconViewImpl(context)); + frame.addView(view); return new Holder(frame); } @@ -354,8 +366,9 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta } info.state.expandedAccessibilityClassName = ""; - holder.mTileView.handleStateChanged(info.state); - holder.mTileView.setShowAppLabel(position > mEditIndex && !info.isSystem); + // The holder has a tileView, therefore this call is not null + holder.getTileAsCustomizeView().changeState(info.state); + holder.getTileAsCustomizeView().setShowAppLabel(position > mEditIndex && !info.isSystem); holder.mTileView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); holder.mTileView.setClickable(true); holder.mTileView.setOnClickListener(null); @@ -534,25 +547,34 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta } public class Holder extends ViewHolder { - private CustomizeTileView mTileView; + private QSTileView mTileView; public Holder(View itemView) { super(itemView); if (itemView instanceof FrameLayout) { - mTileView = (CustomizeTileView) ((FrameLayout) itemView).getChildAt(0); - mTileView.setBackground(null); + mTileView = (QSTileView) ((FrameLayout) itemView).getChildAt(0); + if (mTileView instanceof CustomizeTileView) { + mTileView.setBackground(null); + } mTileView.getIcon().disableAnimation(); mTileView.setTag(this); ViewCompat.setAccessibilityDelegate(mTileView, mAccessibilityDelegate); } } + @Nullable + public CustomizeView getTileAsCustomizeView() { + return (CustomizeView) mTileView; + } + public void clearDrag() { itemView.clearAnimation(); - mTileView.findViewById(R.id.tile_label).clearAnimation(); - mTileView.findViewById(R.id.tile_label).setAlpha(1); - mTileView.getAppLabel().clearAnimation(); - mTileView.getAppLabel().setAlpha(.6f); + if (mTileView instanceof CustomizeTileView) { + mTileView.findViewById(R.id.tile_label).clearAnimation(); + mTileView.findViewById(R.id.tile_label).setAlpha(1); + mTileView.getAppLabel().clearAnimation(); + mTileView.getAppLabel().setAlpha(.6f); + } } public void startDrag() { @@ -560,12 +582,14 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta .setDuration(DRAG_LENGTH) .scaleX(DRAG_SCALE) .scaleY(DRAG_SCALE); - mTileView.findViewById(R.id.tile_label).animate() - .setDuration(DRAG_LENGTH) - .alpha(0); - mTileView.getAppLabel().animate() - .setDuration(DRAG_LENGTH) - .alpha(0); + if (mTileView instanceof CustomizeTileView) { + mTileView.findViewById(R.id.tile_label).animate() + .setDuration(DRAG_LENGTH) + .alpha(0); + mTileView.getAppLabel().animate() + .setDuration(DRAG_LENGTH) + .alpha(0); + } } public void stopDrag() { @@ -573,12 +597,14 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta .setDuration(DRAG_LENGTH) .scaleX(1) .scaleY(1); - mTileView.findViewById(R.id.tile_label).animate() - .setDuration(DRAG_LENGTH) - .alpha(1); - mTileView.getAppLabel().animate() - .setDuration(DRAG_LENGTH) - .alpha(.6f); + if (mTileView instanceof CustomizeTileView) { + mTileView.findViewById(R.id.tile_label).animate() + .setDuration(DRAG_LENGTH) + .alpha(1); + mTileView.getAppLabel().animate() + .setDuration(DRAG_LENGTH) + .alpha(.6f); + } } boolean canRemove() { @@ -722,7 +748,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta int position = mCurrentDrag.getAdapterPosition(); if (position == RecyclerView.NO_POSITION) return; TileInfo info = mTiles.get(position); - mCurrentDrag.mTileView.setShowAppLabel( + ((CustomizeView) mCurrentDrag.mTileView).setShowAppLabel( position > mEditIndex && !info.isSystem); mCurrentDrag.stopDrag(); mCurrentDrag = null; @@ -782,4 +808,9 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta public void onSwiped(ViewHolder viewHolder, int direction) { } }; + + interface CustomizeView { + void setShowAppLabel(boolean showAppLabel); + void changeState(@NonNull QSTile.State state); + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java index 207b25d001b9..b59326ae56d5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java @@ -174,4 +174,8 @@ public class QSTileView extends QSTileBaseView { mLabelContainer.setClickable(false); mLabelContainer.setLongClickable(false); } + + public TextView getAppLabel() { + return mSecondLine; + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewHorizontal.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewHorizontal.kt index 07d48f32ff20..231037fdd158 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewHorizontal.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewHorizontal.kt @@ -35,13 +35,13 @@ import com.android.systemui.qs.tileimpl.QSTileImpl.getColorForState // Placeholder private const val CORNER_RADIUS = 40f -class QSTileViewHorizontal( +open class QSTileViewHorizontal( context: Context, icon: QSIconView ) : QSTileView(context, icon, false) { - private var paintDrawable: PaintDrawable? = null - private var paintColor = Color.TRANSPARENT + protected var paintDrawable: PaintDrawable? = null + private var paintColor = Color.WHITE private var paintAnimator: ValueAnimator? = null init { @@ -103,7 +103,7 @@ class QSTileViewHorizontal( mSecondLine.setTextColor(mLabel.textColors) mLabelContainer.background = null - val allowAnimations = animationsEnabled() && paintColor != Color.TRANSPARENT + val allowAnimations = animationsEnabled() && paintColor != Color.WHITE val newColor = getCircleColor(state.state) if (allowAnimations) { animateToNewState(newColor) diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java index 3d53062d7d02..62cc9b7e3602 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java @@ -49,7 +49,7 @@ public class TileAdapterTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); TestableLooper.get(this).runWithLooper(() -> mTileAdapter = - new TileAdapter(mContext, mQSTileHost, new UiEventLoggerFake())); + new TileAdapter(mContext, mQSTileHost, new UiEventLoggerFake(), /* qsFlag */false)); } @Test diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index d1cd3be35af8..986e2acf6029 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1403,7 +1403,7 @@ public class ConnectivityService extends IConnectivityManager.Stub return null; } - private NetworkState getUnfilteredActiveNetworkState(int uid) { + private NetworkAgentInfo getNetworkAgentInfoForUid(int uid) { NetworkAgentInfo nai = getDefaultNetworkForUid(uid); final Network[] networks = getVpnUnderlyingNetworks(uid); @@ -1419,12 +1419,7 @@ public class ConnectivityService extends IConnectivityManager.Stub nai = null; } } - - if (nai != null) { - return nai.getNetworkState(); - } else { - return NetworkState.EMPTY; - } + return nai; } /** @@ -1477,24 +1472,28 @@ public class ConnectivityService extends IConnectivityManager.Stub "%s %d(%d) on netId %d", action, nri.mUid, requestId, net.getNetId())); } - private void filterNetworkInfo(@NonNull NetworkInfo networkInfo, - @NonNull NetworkCapabilities nc, int uid, boolean ignoreBlocked) { - if (isNetworkWithCapabilitiesBlocked(nc, uid, ignoreBlocked)) { - networkInfo.setDetailedState(DetailedState.BLOCKED, null, null); - } - networkInfo.setDetailedState( - getLegacyLockdownState(networkInfo.getDetailedState()), - "" /* reason */, null /* extraInfo */); - } - /** - * Apply any relevant filters to {@link NetworkState} for the given UID. For + * Apply any relevant filters to the specified {@link NetworkInfo} for the given UID. For * example, this may mark the network as {@link DetailedState#BLOCKED} based * on {@link #isNetworkWithCapabilitiesBlocked}. */ - private void filterNetworkStateForUid(NetworkState state, int uid, boolean ignoreBlocked) { - if (state == null || state.networkInfo == null || state.linkProperties == null) return; - filterNetworkInfo(state.networkInfo, state.networkCapabilities, uid, ignoreBlocked); + @NonNull + private NetworkInfo filterNetworkInfo(@NonNull NetworkInfo networkInfo, int type, + @NonNull NetworkCapabilities nc, int uid, boolean ignoreBlocked) { + NetworkInfo filtered = new NetworkInfo(networkInfo); + filtered.setType(type); + final DetailedState state = isNetworkWithCapabilitiesBlocked(nc, uid, ignoreBlocked) + ? DetailedState.BLOCKED + : filtered.getDetailedState(); + filtered.setDetailedState(getLegacyLockdownState(state), + "" /* reason */, null /* extraInfo */); + return filtered; + } + + private NetworkInfo getFilteredNetworkInfo(NetworkAgentInfo nai, int uid, + boolean ignoreBlocked) { + return filterNetworkInfo(nai.networkInfo, nai.networkInfo.getType(), + nai.networkCapabilities, uid, ignoreBlocked); } /** @@ -1508,10 +1507,11 @@ public class ConnectivityService extends IConnectivityManager.Stub public NetworkInfo getActiveNetworkInfo() { enforceAccessPermission(); final int uid = mDeps.getCallingUid(); - final NetworkState state = getUnfilteredActiveNetworkState(uid); - filterNetworkStateForUid(state, uid, false); - maybeLogBlockedNetworkInfo(state.networkInfo, uid); - return state.networkInfo; + final NetworkAgentInfo nai = getNetworkAgentInfoForUid(uid); + if (nai == null) return null; + final NetworkInfo networkInfo = getFilteredNetworkInfo(nai, uid, false); + maybeLogBlockedNetworkInfo(networkInfo, uid); + return networkInfo; } @Override @@ -1546,30 +1546,37 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) { PermissionUtils.enforceNetworkStackPermission(mContext); - final NetworkState state = getUnfilteredActiveNetworkState(uid); - filterNetworkStateForUid(state, uid, ignoreBlocked); - return state.networkInfo; + final NetworkAgentInfo nai = getNetworkAgentInfoForUid(uid); + if (nai == null) return null; + return getFilteredNetworkInfo(nai, uid, ignoreBlocked); + } + + /** Returns a NetworkInfo object for a network that doesn't exist. */ + private NetworkInfo makeFakeNetworkInfo(int networkType, int uid) { + final NetworkInfo info = new NetworkInfo(networkType, 0 /* subtype */, + getNetworkTypeName(networkType), "" /* subtypeName */); + info.setIsAvailable(true); + // For compatibility with legacy code, return BLOCKED instead of DISCONNECTED when + // background data is restricted. + final NetworkCapabilities nc = new NetworkCapabilities(); // Metered. + final DetailedState state = isNetworkWithCapabilitiesBlocked(nc, uid, false) + ? DetailedState.BLOCKED + : DetailedState.DISCONNECTED; + info.setDetailedState(getLegacyLockdownState(state), + "" /* reason */, null /* extraInfo */); + return info; } - private NetworkInfo getFilteredNetworkInfo(int networkType, int uid) { + private NetworkInfo getFilteredNetworkInfoForType(int networkType, int uid) { if (!mLegacyTypeTracker.isTypeSupported(networkType)) { return null; } final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType); - final NetworkInfo info; - final NetworkCapabilities nc; - if (nai != null) { - info = new NetworkInfo(nai.networkInfo); - info.setType(networkType); - nc = nai.networkCapabilities; - } else { - info = new NetworkInfo(networkType, 0, getNetworkTypeName(networkType), ""); - info.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null); - info.setIsAvailable(true); - nc = new NetworkCapabilities(); + if (nai == null) { + return makeFakeNetworkInfo(networkType, uid); } - filterNetworkInfo(info, nc, uid, false); - return info; + return filterNetworkInfo(nai.networkInfo, networkType, nai.networkCapabilities, uid, + false); } @Override @@ -1579,27 +1586,23 @@ public class ConnectivityService extends IConnectivityManager.Stub if (getVpnUnderlyingNetworks(uid) != null) { // A VPN is active, so we may need to return one of its underlying networks. This // information is not available in LegacyTypeTracker, so we have to get it from - // getUnfilteredActiveNetworkState. - final NetworkState state = getUnfilteredActiveNetworkState(uid); - if (state.networkInfo != null && state.networkInfo.getType() == networkType) { - filterNetworkStateForUid(state, uid, false); - return state.networkInfo; + // getNetworkAgentInfoForUid. + final NetworkAgentInfo nai = getNetworkAgentInfoForUid(uid); + if (nai == null) return null; + final NetworkInfo networkInfo = getFilteredNetworkInfo(nai, uid, false); + if (networkInfo.getType() == networkType) { + return networkInfo; } } - return getFilteredNetworkInfo(networkType, uid); + return getFilteredNetworkInfoForType(networkType, uid); } @Override public NetworkInfo getNetworkInfoForUid(Network network, int uid, boolean ignoreBlocked) { enforceAccessPermission(); final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); - if (nai != null) { - final NetworkState state = nai.getNetworkState(); - filterNetworkStateForUid(state, uid, ignoreBlocked); - return state.networkInfo; - } else { - return null; - } + if (nai == null) return null; + return getFilteredNetworkInfo(nai, uid, ignoreBlocked); } @Override @@ -1627,10 +1630,10 @@ public class ConnectivityService extends IConnectivityManager.Stub return null; } final int uid = mDeps.getCallingUid(); - if (!isNetworkWithCapabilitiesBlocked(nai.networkCapabilities, uid, false)) { - return nai.network; + if (isNetworkWithCapabilitiesBlocked(nai.networkCapabilities, uid, false)) { + return null; } - return null; + return nai.network; } @Override @@ -1719,9 +1722,9 @@ public class ConnectivityService extends IConnectivityManager.Stub public LinkProperties getActiveLinkProperties() { enforceAccessPermission(); final int uid = mDeps.getCallingUid(); - NetworkState state = getUnfilteredActiveNetworkState(uid); - if (state.linkProperties == null) return null; - return linkPropertiesRestrictedForCallerPermissions(state.linkProperties, + NetworkAgentInfo nai = getNetworkAgentInfoForUid(uid); + if (nai == null) return null; + return linkPropertiesRestrictedForCallerPermissions(nai.linkProperties, Binder.getCallingPid(), uid); } diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java index 42fcd4460386..088249e81171 100644 --- a/services/core/java/com/android/server/clipboard/ClipboardService.java +++ b/services/core/java/com/android/server/clipboard/ClipboardService.java @@ -52,6 +52,7 @@ import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; +import android.provider.DeviceConfig; import android.provider.Settings; import android.text.TextUtils; import android.util.Slog; @@ -59,6 +60,7 @@ import android.util.SparseArray; import android.view.autofill.AutofillManagerInternal; import android.widget.Toast; +import com.android.internal.annotations.GuardedBy; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.UiThread; @@ -163,6 +165,10 @@ public class ClipboardService extends SystemService { private static final boolean IS_EMULATOR = SystemProperties.getBoolean("ro.kernel.qemu", false); + // DeviceConfig properties + private static final String PROPERTY_SHOW_ACCESS_NOTIFICATIONS = "show_access_notifications"; + private static final boolean DEFAULT_SHOW_ACCESS_NOTIFICATIONS = true; + private final ActivityManagerInternal mAmInternal; private final IUriGrantsManager mUgm; private final UriGrantsManagerInternal mUgmInternal; @@ -176,8 +182,14 @@ public class ClipboardService extends SystemService { private HostClipboardMonitor mHostClipboardMonitor = null; private Thread mHostMonitorThread = null; + @GuardedBy("mLock") private final SparseArray<PerUserClipboard> mClipboards = new SparseArray<>(); + @GuardedBy("mLock") + private boolean mShowAccessNotifications = DEFAULT_SHOW_ACCESS_NOTIFICATIONS; + + private final Object mLock = new Object(); + /** * Instantiates the clipboard. */ @@ -204,7 +216,7 @@ public class ClipboardService extends SystemService { new ClipData("host clipboard", new String[]{"text/plain"}, new ClipData.Item(contents)); - synchronized(mClipboards) { + synchronized (mLock) { setPrimaryClipInternal(getClipboard(0), clip, android.os.Process.SYSTEM_UID, null); } @@ -213,6 +225,10 @@ public class ClipboardService extends SystemService { mHostMonitorThread = new Thread(mHostClipboardMonitor); mHostMonitorThread.start(); } + + updateConfig(); + DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_CLIPBOARD, + getContext().getMainExecutor(), properties -> updateConfig()); } @Override @@ -222,11 +238,18 @@ public class ClipboardService extends SystemService { @Override public void onUserStopped(@NonNull TargetUser user) { - synchronized (mClipboards) { + synchronized (mLock) { mClipboards.remove(user.getUserIdentifier()); } } + private void updateConfig() { + synchronized (mLock) { + mShowAccessNotifications = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_CLIPBOARD, + PROPERTY_SHOW_ACCESS_NOTIFICATIONS, DEFAULT_SHOW_ACCESS_NOTIFICATIONS); + } + } + private class ListenerInfo { final int mUid; final String mPackageName; @@ -472,7 +495,7 @@ public class ClipboardService extends SystemService { }; private PerUserClipboard getClipboard(@UserIdInt int userId) { - synchronized (mClipboards) { + synchronized (mLock) { PerUserClipboard puc = mClipboards.get(userId); if (puc == null) { puc = new PerUserClipboard(userId); @@ -849,9 +872,10 @@ public class ClipboardService extends SystemService { if (clipboard.primaryClip == null) { return; } - if (Settings.Global.getInt(getContext().getContentResolver(), - "clipboard_access_toast_enabled", 1) == 0) { - return; + synchronized (mLock) { + if (!mShowAccessNotifications) { + return; + } } // Don't notify if the app accessing the clipboard is the same as the current owner. if (UserHandle.isSameApp(uid, clipboard.primaryClipUid)) { diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index d41f4c76861e..c0d577cd590d 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -3536,6 +3536,20 @@ public class InputMethodManagerService extends IInputMethodManager.Stub boolean didStart = false; InputBindResult res = null; + // We shows the IME when the system allows the IME focused target window to restore the + // IME visibility (e.g. switching to the app task when last time the IME is visible). + if (isTextEditor && mWindowManagerInternal.shouldRestoreImeVisibility(windowToken)) { + if (attribute != null) { + res = startInputUncheckedLocked(cs, inputContext, missingMethods, + attribute, startInputFlags, startInputReason); + showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null, + SoftInputShowHideReason.SHOW_RESTORE_IME_VISIBILITY); + } else { + res = InputBindResult.NULL_EDITOR_INFO; + } + return res; + } + switch (softInputMode & LayoutParams.SOFT_INPUT_MASK_STATE) { case LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED: if (!sameWindowFocused && (!isTextEditor || !doAutoShow)) { diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 3a5e10ed951a..ebf1fe9d7cd0 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -379,6 +379,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { case MSG_UPDATE_IFACES: { // If no cached states, ignore. if (mLastNetworkStateSnapshots == null) break; + // TODO (b/181642673): Protect mDefaultNetworks from concurrent accessing. updateIfaces(mDefaultNetworks, mLastNetworkStateSnapshots, mActiveIface); break; } @@ -1266,7 +1267,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * they are combined under a single {@link NetworkIdentitySet}. */ @GuardedBy("mStatsLock") - private void updateIfacesLocked(@Nullable Network[] defaultNetworks, + private void updateIfacesLocked(@NonNull Network[] defaultNetworks, @NonNull NetworkStateSnapshot[] snapshots) { if (!mSystemReady) return; if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); @@ -1282,10 +1283,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Rebuild active interfaces based on connected networks mActiveIfaces.clear(); mActiveUidIfaces.clear(); - if (defaultNetworks != null) { - // Caller is ConnectivityService. Update the list of default networks. - mDefaultNetworks = defaultNetworks; - } + // Update the list of default networks. + mDefaultNetworks = defaultNetworks; mLastNetworkStateSnapshots = snapshots; diff --git a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java index b6ddd93af3b8..b2db9f5af07e 100644 --- a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java +++ b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java @@ -65,7 +65,7 @@ public class UnderlyingNetworkTracker { @NonNull private final NetworkCallback mRouteSelectionCallback = new RouteSelectionCallback(); @NonNull private TelephonySubscriptionSnapshot mLastSnapshot; - private boolean mIsRunning = true; + private boolean mIsQuitting = false; @Nullable private UnderlyingNetworkRecord mCurrentRecord; @Nullable private UnderlyingNetworkRecord.Builder mRecordInProgress; @@ -151,7 +151,7 @@ public class UnderlyingNetworkTracker { mVcnContext.ensureRunningOnLooperThread(); // Don't bother re-filing NetworkRequests if this Tracker has been torn down. - if (!mIsRunning) { + if (mIsQuitting) { return; } @@ -205,7 +205,7 @@ public class UnderlyingNetworkTracker { } mCellBringupCallbacks.clear(); - mIsRunning = false; + mIsQuitting = true; } /** Returns whether the currently selected Network matches the given network. */ diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java index 6ad30b544257..9d39c67d27fb 100644 --- a/services/core/java/com/android/server/vcn/Vcn.java +++ b/services/core/java/com/android/server/vcn/Vcn.java @@ -16,6 +16,8 @@ package com.android.server.vcn; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; + import static com.android.server.VcnManagementService.VDBG; import android.annotation.NonNull; @@ -84,6 +86,13 @@ public class Vcn extends Handler { */ private static final int MSG_EVENT_SUBSCRIPTIONS_CHANGED = MSG_EVENT_BASE + 2; + /** + * A GatewayConnection owned by this VCN quit. + * + * @param obj VcnGatewayConnectionConfig + */ + private static final int MSG_EVENT_GATEWAY_CONNECTION_QUIT = MSG_EVENT_BASE + 3; + /** Triggers an immediate teardown of the entire Vcn, including GatewayConnections. */ private static final int MSG_CMD_TEARDOWN = MSG_CMD_BASE; @@ -208,6 +217,9 @@ public class Vcn extends Handler { case MSG_EVENT_SUBSCRIPTIONS_CHANGED: handleSubscriptionsChanged((TelephonySubscriptionSnapshot) msg.obj); break; + case MSG_EVENT_GATEWAY_CONNECTION_QUIT: + handleGatewayConnectionQuit((VcnGatewayConnectionConfig) msg.obj); + break; case MSG_CMD_TEARDOWN: handleTeardown(); break; @@ -263,7 +275,7 @@ public class Vcn extends Handler { // If preexisting VcnGatewayConnection(s) satisfy request, return for (VcnGatewayConnectionConfig gatewayConnectionConfig : mVcnGatewayConnections.keySet()) { - if (requestSatisfiedByGatewayConnectionConfig(request, gatewayConnectionConfig)) { + if (isRequestSatisfiedByGatewayConnectionConfig(request, gatewayConnectionConfig)) { if (VDBG) { Slog.v( getLogTag(), @@ -278,7 +290,7 @@ public class Vcn extends Handler { // up for (VcnGatewayConnectionConfig gatewayConnectionConfig : mConfig.getGatewayConnectionConfigs()) { - if (requestSatisfiedByGatewayConnectionConfig(request, gatewayConnectionConfig)) { + if (isRequestSatisfiedByGatewayConnectionConfig(request, gatewayConnectionConfig)) { Slog.v( getLogTag(), "Bringing up new VcnGatewayConnection for request " + request.requestId); @@ -289,12 +301,21 @@ public class Vcn extends Handler { mSubscriptionGroup, mLastSnapshot, gatewayConnectionConfig, - new VcnGatewayStatusCallbackImpl()); + new VcnGatewayStatusCallbackImpl(gatewayConnectionConfig)); mVcnGatewayConnections.put(gatewayConnectionConfig, vcnGatewayConnection); } } } + private void handleGatewayConnectionQuit(VcnGatewayConnectionConfig config) { + Slog.v(getLogTag(), "VcnGatewayConnection quit: " + config); + mVcnGatewayConnections.remove(config); + + // Trigger a re-evaluation of all NetworkRequests (to make sure any that can be satisfied + // start a new GatewayConnection) + mVcnContext.getVcnNetworkProvider().resendAllRequests(mRequestListener); + } + private void handleSubscriptionsChanged(@NonNull TelephonySubscriptionSnapshot snapshot) { mLastSnapshot = snapshot; @@ -305,9 +326,10 @@ public class Vcn extends Handler { } } - private boolean requestSatisfiedByGatewayConnectionConfig( + private boolean isRequestSatisfiedByGatewayConnectionConfig( @NonNull NetworkRequest request, @NonNull VcnGatewayConnectionConfig config) { final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(); + builder.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); for (int cap : config.getAllExposedCapabilities()) { builder.addCapability(cap); } @@ -339,9 +361,23 @@ public class Vcn extends Handler { @VcnErrorCode int errorCode, @Nullable String exceptionClass, @Nullable String exceptionMessage); + + /** Called by a VcnGatewayConnection to indicate that it has fully torn down. */ + void onQuit(); } private class VcnGatewayStatusCallbackImpl implements VcnGatewayStatusCallback { + public final VcnGatewayConnectionConfig mGatewayConnectionConfig; + + VcnGatewayStatusCallbackImpl(VcnGatewayConnectionConfig gatewayConnectionConfig) { + mGatewayConnectionConfig = gatewayConnectionConfig; + } + + @Override + public void onQuit() { + sendMessage(obtainMessage(MSG_EVENT_GATEWAY_CONNECTION_QUIT, mGatewayConnectionConfig)); + } + @Override public void onEnteredSafeMode() { sendMessage(obtainMessage(MSG_CMD_ENTER_SAFE_MODE)); diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java index 06748a3aa2d1..6bc9978a0731 100644 --- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java +++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java @@ -168,6 +168,8 @@ public class VcnGatewayConnection extends StateMachine { private static final String DISCONNECT_REASON_INTERNAL_ERROR = "Uncaught exception: "; private static final String DISCONNECT_REASON_UNDERLYING_NETWORK_LOST = "Underlying Network lost"; + private static final String DISCONNECT_REASON_NETWORK_AGENT_UNWANTED = + "NetworkAgent was unwanted"; private static final String DISCONNECT_REASON_TEARDOWN = "teardown() called on VcnTunnel"; private static final int TOKEN_ALL = Integer.MIN_VALUE; @@ -379,13 +381,16 @@ public class VcnGatewayConnection extends StateMachine { /** The reason why the disconnect was requested. */ @NonNull public final String reason; - EventDisconnectRequestedInfo(@NonNull String reason) { + public final boolean shouldQuit; + + EventDisconnectRequestedInfo(@NonNull String reason, boolean shouldQuit) { this.reason = Objects.requireNonNull(reason); + this.shouldQuit = shouldQuit; } @Override public int hashCode() { - return Objects.hash(reason); + return Objects.hash(reason, shouldQuit); } @Override @@ -395,7 +400,7 @@ public class VcnGatewayConnection extends StateMachine { } final EventDisconnectRequestedInfo rhs = (EventDisconnectRequestedInfo) other; - return reason.equals(rhs.reason); + return reason.equals(rhs.reason) && shouldQuit == rhs.shouldQuit; } } @@ -488,8 +493,14 @@ public class VcnGatewayConnection extends StateMachine { */ @NonNull private final VcnWakeLock mWakeLock; - /** Running state of this VcnGatewayConnection. */ - private boolean mIsRunning = true; + /** + * Whether the VcnGatewayConnection is in the process of irreversibly quitting. + * + * <p>This variable is false for the lifecycle of the VcnGatewayConnection, until a command to + * teardown has been received. This may be flipped due to events such as the Network becoming + * unwanted, the owning VCN entering safe mode, or an irrecoverable internal failure. + */ + private boolean mIsQuitting = false; /** * The token used by the primary/current/active session. @@ -622,10 +633,8 @@ public class VcnGatewayConnection extends StateMachine { * <p>Once torn down, this VcnTunnel CANNOT be started again. */ public void teardownAsynchronously() { - sendMessageAndAcquireWakeLock( - EVENT_DISCONNECT_REQUESTED, - TOKEN_ALL, - new EventDisconnectRequestedInfo(DISCONNECT_REASON_TEARDOWN)); + sendDisconnectRequestedAndAcquireWakelock( + DISCONNECT_REASON_TEARDOWN, true /* shouldQuit */); // TODO: Notify VcnInstance (via callbacks) of permanent teardown of this tunnel, since this // is also called asynchronously when a NetworkAgent becomes unwanted @@ -646,6 +655,8 @@ public class VcnGatewayConnection extends StateMachine { cancelSafeModeAlarm(); mUnderlyingNetworkTracker.teardown(); + + mGatewayStatusCallback.onQuit(); } /** @@ -693,7 +704,7 @@ public class VcnGatewayConnection extends StateMachine { private void acquireWakeLock() { mVcnContext.ensureRunningOnLooperThread(); - if (mIsRunning) { + if (!mIsQuitting) { mWakeLock.acquire(); } } @@ -892,7 +903,7 @@ public class VcnGatewayConnection extends StateMachine { TOKEN_ALL, 0 /* arg2 */, new EventDisconnectRequestedInfo( - DISCONNECT_REASON_UNDERLYING_NETWORK_LOST)); + DISCONNECT_REASON_UNDERLYING_NETWORK_LOST, false /* shouldQuit */)); mDisconnectRequestAlarm = createScheduledAlarm( DISCONNECT_REQUEST_ALARM, @@ -909,7 +920,8 @@ public class VcnGatewayConnection extends StateMachine { // Cancel any existing disconnect due to previous loss of underlying network removeEqualMessages( EVENT_DISCONNECT_REQUESTED, - new EventDisconnectRequestedInfo(DISCONNECT_REASON_UNDERLYING_NETWORK_LOST)); + new EventDisconnectRequestedInfo( + DISCONNECT_REASON_UNDERLYING_NETWORK_LOST, false /* shouldQuit */)); } private void setRetryTimeoutAlarm(long delay) { @@ -1041,11 +1053,8 @@ public class VcnGatewayConnection extends StateMachine { enterState(); } catch (Exception e) { Slog.wtf(TAG, "Uncaught exception", e); - sendMessageAndAcquireWakeLock( - EVENT_DISCONNECT_REQUESTED, - TOKEN_ALL, - new EventDisconnectRequestedInfo( - DISCONNECT_REASON_INTERNAL_ERROR + e.toString())); + sendDisconnectRequestedAndAcquireWakelock( + DISCONNECT_REASON_INTERNAL_ERROR + e.toString(), true /* shouldQuit */); } } @@ -1083,11 +1092,8 @@ public class VcnGatewayConnection extends StateMachine { processStateMsg(msg); } catch (Exception e) { Slog.wtf(TAG, "Uncaught exception", e); - sendMessageAndAcquireWakeLock( - EVENT_DISCONNECT_REQUESTED, - TOKEN_ALL, - new EventDisconnectRequestedInfo( - DISCONNECT_REASON_INTERNAL_ERROR + e.toString())); + sendDisconnectRequestedAndAcquireWakelock( + DISCONNECT_REASON_INTERNAL_ERROR + e.toString(), true /* shouldQuit */); } // Attempt to release the WakeLock - only possible if the Handler queue is empty @@ -1104,11 +1110,8 @@ public class VcnGatewayConnection extends StateMachine { exitState(); } catch (Exception e) { Slog.wtf(TAG, "Uncaught exception", e); - sendMessageAndAcquireWakeLock( - EVENT_DISCONNECT_REQUESTED, - TOKEN_ALL, - new EventDisconnectRequestedInfo( - DISCONNECT_REASON_INTERNAL_ERROR + e.toString())); + sendDisconnectRequestedAndAcquireWakelock( + DISCONNECT_REASON_INTERNAL_ERROR + e.toString(), true /* shouldQuit */); } } @@ -1141,11 +1144,11 @@ public class VcnGatewayConnection extends StateMachine { } } - protected void handleDisconnectRequested(String msg) { + protected void handleDisconnectRequested(EventDisconnectRequestedInfo info) { // TODO(b/180526152): notify VcnStatusCallback for Network loss - Slog.v(TAG, "Tearing down. Cause: " + msg); - mIsRunning = false; + Slog.v(TAG, "Tearing down. Cause: " + info.reason); + mIsQuitting = info.shouldQuit; teardownNetwork(); @@ -1177,7 +1180,7 @@ public class VcnGatewayConnection extends StateMachine { private class DisconnectedState extends BaseState { @Override protected void enterState() { - if (!mIsRunning) { + if (mIsQuitting) { quitNow(); // Ignore all queued events; cleanup is complete. } @@ -1200,9 +1203,11 @@ public class VcnGatewayConnection extends StateMachine { } break; case EVENT_DISCONNECT_REQUESTED: - mIsRunning = false; + if (((EventDisconnectRequestedInfo) msg.obj).shouldQuit) { + mIsQuitting = true; - quitNow(); + quitNow(); + } break; default: logUnhandledMessage(msg); @@ -1284,10 +1289,11 @@ public class VcnGatewayConnection extends StateMachine { break; case EVENT_DISCONNECT_REQUESTED: + EventDisconnectRequestedInfo info = ((EventDisconnectRequestedInfo) msg.obj); + mIsQuitting = info.shouldQuit; teardownNetwork(); - String reason = ((EventDisconnectRequestedInfo) msg.obj).reason; - if (reason.equals(DISCONNECT_REASON_UNDERLYING_NETWORK_LOST)) { + if (info.reason.equals(DISCONNECT_REASON_UNDERLYING_NETWORK_LOST)) { // TODO(b/180526152): notify VcnStatusCallback for Network loss // Will trigger EVENT_SESSION_CLOSED immediately. @@ -1300,7 +1306,7 @@ public class VcnGatewayConnection extends StateMachine { case EVENT_SESSION_CLOSED: mIkeSession = null; - if (mIsRunning && mUnderlying != null) { + if (!mIsQuitting && mUnderlying != null) { transitionTo(mSkipRetryTimeout ? mConnectingState : mRetryTimeoutState); } else { teardownNetwork(); @@ -1391,7 +1397,7 @@ public class VcnGatewayConnection extends StateMachine { transitionTo(mConnectedState); break; case EVENT_DISCONNECT_REQUESTED: - handleDisconnectRequested(((EventDisconnectRequestedInfo) msg.obj).reason); + handleDisconnectRequested((EventDisconnectRequestedInfo) msg.obj); break; case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED: mGatewayStatusCallback.onEnteredSafeMode(); @@ -1438,6 +1444,7 @@ public class VcnGatewayConnection extends StateMachine { mVcnContext.getVcnNetworkProvider()) { @Override public void unwanted() { + Slog.d(TAG, "NetworkAgent was unwanted"); teardownAsynchronously(); } @@ -1471,7 +1478,7 @@ public class VcnGatewayConnection extends StateMachine { @NonNull IpSecTransform transform, int direction) { try { - // TODO(b/180163196): Set underlying network of tunnel interface + tunnelIface.setUnderlyingNetwork(underlyingNetwork); // Transforms do not need to be persisted; the IkeSession will keep them alive mIpSecManager.applyTunnelModeTransform(tunnelIface, direction, transform); @@ -1577,7 +1584,7 @@ public class VcnGatewayConnection extends StateMachine { setupInterfaceAndNetworkAgent(mCurrentToken, mTunnelIface, mChildConfig); break; case EVENT_DISCONNECT_REQUESTED: - handleDisconnectRequested(((EventDisconnectRequestedInfo) msg.obj).reason); + handleDisconnectRequested((EventDisconnectRequestedInfo) msg.obj); break; case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED: mGatewayStatusCallback.onEnteredSafeMode(); @@ -1682,7 +1689,7 @@ public class VcnGatewayConnection extends StateMachine { transitionTo(mConnectingState); break; case EVENT_DISCONNECT_REQUESTED: - handleDisconnectRequested(((EventDisconnectRequestedInfo) msg.obj).reason); + handleDisconnectRequested((EventDisconnectRequestedInfo) msg.obj); break; case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED: mGatewayStatusCallback.onEnteredSafeMode(); @@ -1905,13 +1912,13 @@ public class VcnGatewayConnection extends StateMachine { } @VisibleForTesting(visibility = Visibility.PRIVATE) - boolean isRunning() { - return mIsRunning; + boolean isQuitting() { + return mIsQuitting; } @VisibleForTesting(visibility = Visibility.PRIVATE) - void setIsRunning(boolean isRunning) { - mIsRunning = isRunning; + void setIsQuitting(boolean isQuitting) { + mIsQuitting = isQuitting; } @VisibleForTesting(visibility = Visibility.PRIVATE) @@ -1924,6 +1931,14 @@ public class VcnGatewayConnection extends StateMachine { mIkeSession = session; } + @VisibleForTesting(visibility = Visibility.PRIVATE) + void sendDisconnectRequestedAndAcquireWakelock(String reason, boolean shouldQuit) { + sendMessageAndAcquireWakeLock( + EVENT_DISCONNECT_REQUESTED, + TOKEN_ALL, + new EventDisconnectRequestedInfo(reason, shouldQuit)); + } + private IkeSessionParams buildIkeParams() { // TODO: Implement this once IkeSessionParams is persisted return null; diff --git a/services/core/java/com/android/server/vcn/VcnNetworkProvider.java b/services/core/java/com/android/server/vcn/VcnNetworkProvider.java index bfeec011a2c9..a90969599159 100644 --- a/services/core/java/com/android/server/vcn/VcnNetworkProvider.java +++ b/services/core/java/com/android/server/vcn/VcnNetworkProvider.java @@ -67,9 +67,7 @@ public class VcnNetworkProvider extends NetworkProvider { mListeners.add(listener); // Send listener all cached requests - for (NetworkRequestEntry entry : mRequests.values()) { - notifyListenerForEvent(listener, entry); - } + resendAllRequests(listener); } /** Unregisters the specified listener from receiving future NetworkRequests. */ @@ -78,6 +76,14 @@ public class VcnNetworkProvider extends NetworkProvider { mListeners.remove(listener); } + /** Sends all cached NetworkRequest(s) to the specified listener. */ + @VisibleForTesting(visibility = Visibility.PACKAGE) + public void resendAllRequests(@NonNull NetworkRequestListener listener) { + for (NetworkRequestEntry entry : mRequests.values()) { + notifyListenerForEvent(listener, entry); + } + } + private void notifyListenerForEvent( @NonNull NetworkRequestListener listener, @NonNull NetworkRequestEntry entry) { listener.onNetworkRequested(entry.mRequest, entry.mScore, entry.mProviderId); diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 33abcb478c77..dd5a19669f74 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -132,7 +132,6 @@ import static com.android.server.wm.ActivityRecordProto.CLIENT_VISIBLE; import static com.android.server.wm.ActivityRecordProto.DEFER_HIDING_CLIENT; import static com.android.server.wm.ActivityRecordProto.FILLS_PARENT; import static com.android.server.wm.ActivityRecordProto.FRONT_OF_TASK; -import static com.android.server.wm.ActivityRecordProto.FROZEN_BOUNDS; import static com.android.server.wm.ActivityRecordProto.IS_ANIMATING; import static com.android.server.wm.ActivityRecordProto.IS_WAITING_FOR_TRANSITION_START; import static com.android.server.wm.ActivityRecordProto.LAST_ALL_DRAWN; @@ -344,7 +343,6 @@ import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.lang.ref.WeakReference; -import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -732,9 +730,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // windows, where the app hasn't had time to set a value on the window. int mRotationAnimationHint = -1; - ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>(); - ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>(); - private AppSaturationInfo mLastAppSaturationInfo; private final ColorDisplayService.ColorTransformController mColorTransformController = @@ -1035,10 +1030,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A pw.println(" mVisibleSetFromTransferredStartingWindow=" + mVisibleSetFromTransferredStartingWindow); } - if (!mFrozenBounds.isEmpty()) { - pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds); - pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig); - } if (mPendingRelaunchCount != 0) { pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount); } @@ -3359,56 +3350,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return mPendingRelaunchCount > 0; } - boolean shouldFreezeBounds() { - // For freeform windows, we can't freeze the bounds at the moment because this would make - // the resizing unresponsive. - if (task == null || task.inFreeformWindowingMode()) { - return false; - } - - // We freeze the bounds while drag resizing to deal with the time between - // the divider/drag handle being released, and the handling it's new - // configuration. If we are relaunched outside of the drag resizing state, - // we need to be careful not to do this. - return task.isDragResizing(); - } - @VisibleForTesting void startRelaunching() { if (mPendingRelaunchCount == 0) { mRelaunchStartTime = SystemClock.elapsedRealtime(); } - if (shouldFreezeBounds()) { - freezeBounds(); - } - clearAllDrawn(); mPendingRelaunchCount++; } - /** - * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds - * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even - * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen - * with a queue. - */ - private void freezeBounds() { - mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds)); - - if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) { - // We didn't call prepareFreezingBounds on the task, so use the current value. - mFrozenMergedConfig.offer(new Configuration(task.getConfiguration())); - } else { - mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig)); - } - // Calling unset() to make it equal to Configuration.EMPTY. - task.mPreparedFrozenMergedConfig.unset(); - } - void finishRelaunching() { mTaskSupervisor.getActivityMetricsLogger().notifyActivityRelaunched(this); - unfreezeBounds(); if (mPendingRelaunchCount > 0) { mPendingRelaunchCount--; @@ -3430,30 +3383,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (mPendingRelaunchCount == 0) { return; } - unfreezeBounds(); mPendingRelaunchCount = 0; mRelaunchStartTime = 0; } /** - * Unfreezes the previously frozen bounds. See {@link #freezeBounds}. - */ - private void unfreezeBounds() { - if (mFrozenBounds.isEmpty()) { - return; - } - mFrozenBounds.remove(); - if (!mFrozenMergedConfig.isEmpty()) { - mFrozenMergedConfig.remove(); - } - for (int i = mChildren.size() - 1; i >= 0; i--) { - final WindowState win = mChildren.get(i); - win.onUnfreezeBounds(); - } - mWmService.mWindowPlacerLocked.performSurfacePlacement(); - } - - /** * Perform clean-up of service connections in an activity record. */ private void cleanUpActivityServices() { @@ -8214,9 +8148,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A proto.write(STARTING_MOVED, startingMoved); proto.write(VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW, mVisibleSetFromTransferredStartingWindow); - for (Rect bounds : mFrozenBounds) { - bounds.dumpDebug(proto, FROZEN_BOUNDS); - } proto.write(STATE, mState.toString()); proto.write(FRONT_OF_TASK, isRootOfTask()); diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index a874dee2c768..0c77d9f1f724 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -4042,17 +4042,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { int updateGlobalConfigurationLocked(@NonNull Configuration values, boolean initLocale, boolean persistent, int userId) { - final DisplayContent defaultDisplay = - mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY); - mTempConfig.setTo(getGlobalConfiguration()); final int changes = mTempConfig.updateFrom(values); if (changes == 0) { - // Since calling to Activity.setRequestedOrientation leads to freezing the window with - // setting WindowManagerService.mWaitingForConfig to true, it is important that we call - // performDisplayOverrideConfigUpdate in order to send the new display configuration - // (even if there are no actual changes) to unfreeze the window. - defaultDisplay.performDisplayOverrideConfigUpdate(values); return 0; } diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java index 309b5ec25f0f..62a00802896f 100644 --- a/services/core/java/com/android/server/wm/ConfigurationContainer.java +++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java @@ -141,17 +141,20 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { mChangeListeners.get(i).onMergedOverrideConfigurationChanged( mMergedOverrideConfiguration); } - dispatchConfigurationToChildren(); - } - - void dispatchConfigurationToChildren() { for (int i = getChildCount() - 1; i >= 0; --i) { - final ConfigurationContainer child = getChildAt(i); - child.onConfigurationChanged(mFullConfiguration); + dispatchConfigurationToChild(getChildAt(i), mFullConfiguration); } } /** + * Dispatches the configuration to child when {@link #onConfigurationChanged(Configuration)} is + * called. This allows the derived classes to override how to dispatch the configuration. + */ + void dispatchConfigurationToChild(E child, Configuration config) { + child.onConfigurationChanged(config); + } + + /** * Resolves the current requested override configuration into * {@link #mResolvedOverrideConfiguration} * diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index eff4ea6536bd..9d5c5bed0419 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -2943,10 +2943,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return dockFrame.bottom - imeFrame.top; } - void prepareFreezingTaskBounds() { - forAllRootTasks(Task::prepareFreezingTaskBounds); - } - void rotateBounds(@Rotation int oldRotation, @Rotation int newRotation, Rect inOutBounds) { // Get display bounds on oldRotation as parent bounds for the rotation. getBounds(mTmpRect, oldRotation); diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 3f9ea1fd2afd..0e8cadbcbcdd 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -650,28 +650,12 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } @Override - void dispatchConfigurationToChildren() { - final Configuration configuration = getConfiguration(); - for (int i = getChildCount() - 1; i >= 0; i--) { - final DisplayContent displayContent = getChildAt(i); - if (displayContent.isDefaultDisplay) { - // The global configuration is also the override configuration of default display. - displayContent.performDisplayOverrideConfigUpdate(configuration); - } else { - displayContent.onConfigurationChanged(configuration); - } - } - } - - @Override - public void onConfigurationChanged(Configuration newParentConfig) { - prepareFreezingTaskBounds(); - super.onConfigurationChanged(newParentConfig); - } - - private void prepareFreezingTaskBounds() { - for (int i = mChildren.size() - 1; i >= 0; i--) { - mChildren.get(i).prepareFreezingTaskBounds(); + void dispatchConfigurationToChild(DisplayContent child, Configuration config) { + if (child.isDefaultDisplay) { + // The global configuration is also the override configuration of default display. + child.performDisplayOverrideConfigUpdate(config); + } else { + child.onConfigurationChanged(config); } } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 68f5c58b4761..5efbb0956823 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -498,9 +498,6 @@ class Task extends WindowContainer<WindowContainer> { // TODO: Make final int mUserId; - final Rect mPreparedFrozenBounds = new Rect(); - final Configuration mPreparedFrozenMergedConfig = new Configuration(); - // Id of the previous display the root task was on. int mPrevDisplayId = INVALID_DISPLAY; @@ -1182,10 +1179,6 @@ class Task extends WindowContainer<WindowContainer> { mTaskSupervisor.mNoAnimActivities.add(topActivity); } - // We might trigger a configuration change. Save the current task bounds for freezing. - // TODO: Should this call be moved inside the resize method in WM? - toRootTask.prepareFreezingTaskBounds(); - if (toRootTaskWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && moveRootTaskMode == REPARENT_KEEP_ROOT_TASK_AT_FRONT) { // Move recents to front so it is not behind root home task when going into docked @@ -3363,15 +3356,6 @@ class Task extends WindowContainer<WindowContainer> { return isResizeable(); } - /** - * Prepares the task bounds to be frozen with the current size. See - * {@link ActivityRecord#freezeBounds}. - */ - void prepareFreezingBounds() { - mPreparedFrozenBounds.set(getBounds()); - mPreparedFrozenMergedConfig.setTo(getConfiguration()); - } - @Override void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets, Rect outSurfaceInsets) { @@ -7503,10 +7487,6 @@ class Task extends WindowContainer<WindowContainer> { }); } - void prepareFreezingTaskBounds() { - forAllLeafTasks(Task::prepareFreezingBounds, true /* traverseTopToBottom */); - } - private int setBounds(Rect existing, Rect bounds) { if (equivalentBounds(existing, bounds)) { return BOUNDS_CHANGE_NONE; diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java index e183ea0d81ab..e03198d63b4c 100644 --- a/services/core/java/com/android/server/wm/WindowManagerInternal.java +++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java @@ -667,4 +667,13 @@ public abstract class WindowManagerInternal { * Moves the {@link WindowToken} {@code binder} to the display specified by {@code displayId}. */ public abstract void moveWindowTokenToDisplay(IBinder binder, int displayId); + + /** + * Checks whether the given window should restore the last IME visibility. + * + * @param imeTargetWindowToken The token of the (IME target) window + * @return {@code true} when the system allows to restore the IME visibility, + * {@code false} otherwise. + */ + public abstract boolean shouldRestoreImeVisibility(IBinder imeTargetWindowToken); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index cec03210efeb..70b0f5888766 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -8024,6 +8024,11 @@ public class WindowManagerService extends IWindowManager.Stub return dc.getImeTarget(IME_TARGET_LAYERING).getWindow().getName(); } } + + @Override + public boolean shouldRestoreImeVisibility(IBinder imeTargetWindowToken) { + return WindowManagerService.this.shouldRestoreImeVisibility(imeTargetWindowToken); + } } void registerAppFreezeListener(AppFreezeListener listener) { @@ -8681,6 +8686,22 @@ public class WindowManagerService extends IWindowManager.Stub boundsInWindow, hashAlgorithm, callback); } + boolean shouldRestoreImeVisibility(IBinder imeTargetWindowToken) { + synchronized (mGlobalLock) { + final WindowState imeTargetWindow = mWindowMap.get(imeTargetWindowToken); + if (imeTargetWindow == null) { + return false; + } + final Task imeTargetWindowTask = imeTargetWindow.getTask(); + if (imeTargetWindowTask == null) { + return false; + } + final TaskSnapshot snapshot = mAtmService.getTaskSnapshot(imeTargetWindowTask.mTaskId, + false /* isLowResolution */); + return snapshot != null && snapshot.hasImeSurface(); + } + } + private void sendDisplayHashError(RemoteCallback callback, int errorCode) { Bundle bundle = new Bundle(); bundle.putInt(EXTRA_DISPLAY_HASH_ERROR_CODE, errorCode); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 2a9e08e90e98..a35f4dea643a 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1190,16 +1190,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP layoutYDiff = 0; } else { windowFrames.mContainingFrame.set(getBounds()); - if (mActivityRecord != null && !mActivityRecord.mFrozenBounds.isEmpty()) { - - // If the bounds are frozen, we still want to translate the window freely and only - // freeze the size. - Rect frozen = mActivityRecord.mFrozenBounds.peek(); - windowFrames.mContainingFrame.right = - windowFrames.mContainingFrame.left + frozen.width(); - windowFrames.mContainingFrame.bottom = - windowFrames.mContainingFrame.top + frozen.height(); - } // IME is up and obscuring this window. Adjust the window position so it is visible. if (isImeTarget) { if (inFreeformWindowingMode()) { @@ -2068,23 +2058,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP super.onResize(); } - void onUnfreezeBounds() { - for (int i = mChildren.size() - 1; i >= 0; --i) { - final WindowState c = mChildren.get(i); - c.onUnfreezeBounds(); - } - - if (!mHasSurface) { - return; - } - - mLayoutNeeded = true; - setDisplayLayoutNeeded(); - if (!mWmService.mResizingWindows.contains(this)) { - mWmService.mResizingWindows.add(this); - } - } - /** * If the window has moved due to its containing content frame changing, then notify the * listeners and optionally animate it. Simply checking a change of position is not enough, @@ -3579,10 +3552,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP @Override public Configuration getConfiguration() { - if (mActivityRecord != null && mActivityRecord.mFrozenMergedConfig.size() > 0) { - return mActivityRecord.mFrozenMergedConfig.peek(); - } - // If the process has not registered to any display area to listen to the configuration // change, we can simply return the mFullConfiguration as default. if (!registeredForDisplayAreaConfigChanges()) { @@ -3944,14 +3913,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return true; } - // If the bounds are currently frozen, it means that the layout size that the app sees - // and the bounds we clip this window to might be different. In order to avoid holes, we - // simulate that we are still resizing so the app fills the hole with the resizing - // background. - return (getDisplayContent().mDividerControllerLocked.isResizing() - || mActivityRecord != null && !mActivityRecord.mFrozenBounds.isEmpty()) && - !task.inFreeformWindowingMode() && !isGoneForLayout(); - + return getDisplayContent().mDividerControllerLocked.isResizing() + && !task.inFreeformWindowingMode() && !isGoneForLayout(); } void setDragResizing() { diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java index 0d878b401bee..a262939c0ef9 100644 --- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java +++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java @@ -102,7 +102,7 @@ public final class ProfcollectForwardingService extends SystemService { return false; } try { - return !mIProfcollect.GetSupportedProvider().isEmpty(); + return !mIProfcollect.get_supported_provider().isEmpty(); } catch (RemoteException e) { Log.e(LOG_TAG, e.getMessage()); return false; @@ -191,7 +191,7 @@ public final class ProfcollectForwardingService extends SystemService { } try { - sSelfService.mIProfcollect.ProcessProfile(); + sSelfService.mIProfcollect.process(false); } catch (RemoteException e) { Log.e(LOG_TAG, e.getMessage()); } @@ -234,7 +234,7 @@ public final class ProfcollectForwardingService extends SystemService { if (DEBUG) { Log.d(LOG_TAG, "Tracing on app launch event: " + packageName); } - mIProfcollect.TraceOnce("applaunch"); + mIProfcollect.trace_once("applaunch"); } catch (RemoteException e) { Log.e(LOG_TAG, e.getMessage()); } @@ -296,7 +296,7 @@ public final class ProfcollectForwardingService extends SystemService { } try { - mIProfcollect.CreateProfileReport(); + mIProfcollect.report(); } catch (RemoteException e) { Log.e(LOG_TAG, e.getMessage()); } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index f7106abb5f20..4d5cd9af17ef 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -351,6 +351,9 @@ public class ConnectivityServiceTest { private static final String TAG = "ConnectivityServiceTest"; private static final int TIMEOUT_MS = 500; + // Broadcasts can take a long time to be delivered. The test will not wait for that long unless + // there is a failure, so use a long timeout. + private static final int BROADCAST_TIMEOUT_MS = 30_000; private static final int TEST_LINGER_DELAY_MS = 400; private static final int TEST_NASCENT_DELAY_MS = 300; // Chosen to be less than the linger and nascent timeout. This ensures that we can distinguish @@ -1685,7 +1688,7 @@ public class ConnectivityServiceTest { } public Intent expectBroadcast() throws Exception { - return expectBroadcast(TIMEOUT_MS); + return expectBroadcast(BROADCAST_TIMEOUT_MS); } public void expectNoBroadcast(int timeoutMs) throws Exception { diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java index 69c21b967917..69b2fb135a8d 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java @@ -36,6 +36,7 @@ import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -143,11 +144,18 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection .onIpSecTransformsMigrated(makeDummyIpSecTransform(), makeDummyIpSecTransform()); mTestLooper.dispatchAll(); + verify(mIpSecSvc, times(2)) + .setNetworkForTunnelInterface( + eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), + eq(TEST_UNDERLYING_NETWORK_RECORD_1.network), + any()); + for (int direction : new int[] {DIRECTION_IN, DIRECTION_OUT}) { verify(mIpSecSvc) .applyTunnelModeTransform( eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(direction), anyInt(), any()); } + assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState()); } @@ -290,4 +298,22 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection verifyIkeSessionClosedExceptionalltyNotifiesStatusCallback( new TemporaryFailureException("vcn test"), VCN_ERROR_CODE_INTERNAL_ERROR); } + + @Test + public void testTeardown() throws Exception { + mGatewayConnection.teardownAsynchronously(); + mTestLooper.dispatchAll(); + + assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState()); + assertTrue(mGatewayConnection.isQuitting()); + } + + @Test + public void testNonTeardownDisconnectRequest() throws Exception { + mGatewayConnection.sendDisconnectRequestedAndAcquireWakelock("TEST", false); + mTestLooper.dispatchAll(); + + assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState()); + assertFalse(mGatewayConnection.isQuitting()); + } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java index 17ae19e086cf..d07d2cf4f1bb 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java @@ -19,6 +19,8 @@ package com.android.server.vcn; import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -111,4 +113,22 @@ public class VcnGatewayConnectionConnectingStateTest extends VcnGatewayConnectio public void testSafeModeTimeoutNotifiesCallback() { verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mConnectingState); } + + @Test + public void testTeardown() throws Exception { + mGatewayConnection.teardownAsynchronously(); + mTestLooper.dispatchAll(); + + assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState()); + assertTrue(mGatewayConnection.isQuitting()); + } + + @Test + public void testNonTeardownDisconnectRequest() throws Exception { + mGatewayConnection.sendDisconnectRequestedAndAcquireWakelock("TEST", false); + mTestLooper.dispatchAll(); + + assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState()); + assertFalse(mGatewayConnection.isQuitting()); + } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java index 9ea641f52e48..5f27fabb62b0 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java @@ -21,9 +21,12 @@ import static android.net.IpSecManager.IpSecTunnelInterface; import static com.android.server.vcn.VcnGatewayConnection.DUMMY_ADDR; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.net.IpSecManager; @@ -54,7 +57,7 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect } @Test - public void testEnterWhileNotRunningTriggersQuit() throws Exception { + public void testEnterWhileQuittingTriggersQuit() throws Exception { final VcnGatewayConnection vgc = new VcnGatewayConnection( mVcnContext, @@ -64,7 +67,7 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect mGatewayStatusCallback, mDeps); - vgc.setIsRunning(false); + vgc.setIsQuitting(true); vgc.transitionTo(vgc.mDisconnectedState); mTestLooper.dispatchAll(); @@ -101,5 +104,18 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect assertNull(mGatewayConnection.getCurrentState()); verify(mIpSecSvc).deleteTunnelInterface(eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), any()); verifySafeModeTimeoutAlarmAndGetCallback(true /* expectCanceled */); + assertTrue(mGatewayConnection.isQuitting()); + verify(mGatewayStatusCallback).onQuit(); + } + + @Test + public void testNonTeardownDisconnectRequest() throws Exception { + mGatewayConnection.sendDisconnectRequestedAndAcquireWakelock("TEST", false); + mTestLooper.dispatchAll(); + + assertEquals(mGatewayConnection.mDisconnectedState, mGatewayConnection.getCurrentState()); + assertFalse(mGatewayConnection.isQuitting()); + verify(mGatewayStatusCallback, never()).onQuit(); + // No safe mode timer changes expected. } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java index 7385204993c0..661e03af4f84 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java @@ -18,6 +18,8 @@ package com.android.server.vcn; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -79,10 +81,20 @@ public class VcnGatewayConnectionDisconnectingStateTest extends VcnGatewayConnec // Should do nothing; already tearing down. assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState()); verifyTeardownTimeoutAlarmAndGetCallback(false /* expectCanceled */); + assertTrue(mGatewayConnection.isQuitting()); } @Test public void testSafeModeTimeoutNotifiesCallback() { verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mDisconnectingState); } + + @Test + public void testNonTeardownDisconnectRequest() throws Exception { + mGatewayConnection.sendDisconnectRequestedAndAcquireWakelock("TEST", false); + mTestLooper.dispatchAll(); + + assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState()); + assertFalse(mGatewayConnection.isQuitting()); + } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java index 5b0850b03f1a..85a0277f8b48 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java @@ -17,6 +17,9 @@ package com.android.server.vcn; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -96,4 +99,22 @@ public class VcnGatewayConnectionRetryTimeoutStateTest extends VcnGatewayConnect public void testSafeModeTimeoutNotifiesCallback() { verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mRetryTimeoutState); } + + @Test + public void testTeardownDisconnectRequest() throws Exception { + mGatewayConnection.teardownAsynchronously(); + mTestLooper.dispatchAll(); + + assertNull(mGatewayConnection.getCurrentState()); + assertTrue(mGatewayConnection.isQuitting()); + } + + @Test + public void testNonTeardownDisconnectRequest() throws Exception { + mGatewayConnection.sendDisconnectRequestedAndAcquireWakelock("TEST", false); + mTestLooper.dispatchAll(); + + assertEquals(mGatewayConnection.mDisconnectedState, mGatewayConnection.getCurrentState()); + assertFalse(mGatewayConnection.isQuitting()); + } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnTest.java b/tests/vcn/java/com/android/server/vcn/VcnTest.java index 9d3368271243..3dd710afed7b 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnTest.java @@ -16,6 +16,10 @@ package com.android.server.vcn; +import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; +import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; +import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.mockito.Matchers.any; @@ -33,6 +37,7 @@ import android.net.vcn.VcnGatewayConnectionConfig; import android.net.vcn.VcnGatewayConnectionConfigTest; import android.os.ParcelUuid; import android.os.test.TestLooper; +import android.util.ArraySet; import com.android.server.VcnManagementService.VcnCallback; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; @@ -51,6 +56,11 @@ public class VcnTest { private static final ParcelUuid TEST_SUB_GROUP = new ParcelUuid(new UUID(0, 0)); private static final int NETWORK_SCORE = 0; private static final int PROVIDER_ID = 5; + private static final int[][] TEST_CAPS = + new int[][] { + new int[] {NET_CAPABILITY_INTERNET, NET_CAPABILITY_MMS}, + new int[] {NET_CAPABILITY_DUN} + }; private Context mContext; private VcnContext mVcnContext; @@ -91,13 +101,12 @@ public class VcnTest { mGatewayStatusCallbackCaptor = ArgumentCaptor.forClass(VcnGatewayStatusCallback.class); final VcnConfig.Builder configBuilder = new VcnConfig.Builder(mContext); - for (final int capability : VcnGatewayConnectionConfigTest.EXPOSED_CAPS) { + for (final int[] caps : TEST_CAPS) { configBuilder.addGatewayConnectionConfig( - VcnGatewayConnectionConfigTest.buildTestConfigWithExposedCaps(capability)); + VcnGatewayConnectionConfigTest.buildTestConfigWithExposedCaps(caps)); } - configBuilder.addGatewayConnectionConfig(VcnGatewayConnectionConfigTest.buildTestConfig()); - mConfig = configBuilder.build(); + mConfig = configBuilder.build(); mVcn = new Vcn( mVcnContext, @@ -130,8 +139,7 @@ public class VcnTest { @Test public void testSubscriptionSnapshotUpdatesVcnGatewayConnections() { final NetworkRequestListener requestListener = verifyAndGetRequestListener(); - startVcnGatewayWithCapabilities( - requestListener, VcnGatewayConnectionConfigTest.EXPOSED_CAPS); + startVcnGatewayWithCapabilities(requestListener, TEST_CAPS[0]); final Set<VcnGatewayConnection> gatewayConnections = mVcn.getVcnGatewayConnections(); assertFalse(gatewayConnections.isEmpty()); @@ -153,10 +161,19 @@ public class VcnTest { for (final int capability : VcnGatewayConnectionConfigTest.EXPOSED_CAPS) { startVcnGatewayWithCapabilities(requestListener, capability); } + } + + private void triggerVcnRequestListeners(NetworkRequestListener requestListener) { + for (final int[] caps : TEST_CAPS) { + startVcnGatewayWithCapabilities(requestListener, caps); + } + } - // Each Capability in EXPOSED_CAPS was split into a separate VcnGatewayConnection in #setUp. - // Expect one VcnGatewayConnection per capability. - final int numExpectedGateways = VcnGatewayConnectionConfigTest.EXPOSED_CAPS.length; + public Set<VcnGatewayConnection> startGatewaysAndGetGatewayConnections( + NetworkRequestListener requestListener) { + triggerVcnRequestListeners(requestListener); + + final int numExpectedGateways = TEST_CAPS.length; final Set<VcnGatewayConnection> gatewayConnections = mVcn.getVcnGatewayConnections(); assertEquals(numExpectedGateways, gatewayConnections.size()); @@ -168,7 +185,16 @@ public class VcnTest { any(), mGatewayStatusCallbackCaptor.capture()); - // Doesn't matter which callback this gets - any Gateway entering safe mode should shut down + return gatewayConnections; + } + + @Test + public void testGatewayEnteringSafemodeNotifiesVcn() { + final NetworkRequestListener requestListener = verifyAndGetRequestListener(); + final Set<VcnGatewayConnection> gatewayConnections = + startGatewaysAndGetGatewayConnections(requestListener); + + // Doesn't matter which callback this gets - any Gateway entering Safemode should shut down // all Gateways final VcnGatewayStatusCallback statusCallback = mGatewayStatusCallbackCaptor.getValue(); statusCallback.onEnteredSafeMode(); @@ -181,4 +207,31 @@ public class VcnTest { verify(mVcnNetworkProvider).unregisterListener(requestListener); verify(mVcnCallback).onEnteredSafeMode(); } + + @Test + public void testGatewayQuit() { + final NetworkRequestListener requestListener = verifyAndGetRequestListener(); + final Set<VcnGatewayConnection> gatewayConnections = + new ArraySet<>(startGatewaysAndGetGatewayConnections(requestListener)); + + final VcnGatewayStatusCallback statusCallback = mGatewayStatusCallbackCaptor.getValue(); + statusCallback.onQuit(); + mTestLooper.dispatchAll(); + + // Verify that the VCN requests the networkRequests be resent + assertEquals(1, mVcn.getVcnGatewayConnections().size()); + verify(mVcnNetworkProvider).resendAllRequests(requestListener); + + // Verify that the VcnGatewayConnection is restarted + triggerVcnRequestListeners(requestListener); + mTestLooper.dispatchAll(); + assertEquals(2, mVcn.getVcnGatewayConnections().size()); + verify(mDeps, times(gatewayConnections.size() + 1)) + .newVcnGatewayConnection( + eq(mVcnContext), + eq(TEST_SUB_GROUP), + eq(mSubscriptionSnapshot), + any(), + mGatewayStatusCallbackCaptor.capture()); + } } |