diff options
48 files changed, 571 insertions, 286 deletions
diff --git a/api/current.txt b/api/current.txt index 3246c9ff1ece..35c6f45d7eaf 100644 --- a/api/current.txt +++ b/api/current.txt @@ -52864,6 +52864,7 @@ package android.view.contentcapture { method @Nullable public final android.view.contentcapture.ContentCaptureContext getContentCaptureContext(); method @NonNull public final android.view.contentcapture.ContentCaptureSessionId getContentCaptureSessionId(); method @NonNull public android.view.autofill.AutofillId newAutofillId(@NonNull android.view.autofill.AutofillId, long); + method @NonNull public final android.view.ViewStructure newViewStructure(@NonNull android.view.View); method @NonNull public final android.view.ViewStructure newVirtualViewStructure(@NonNull android.view.autofill.AutofillId, long); method public final void notifyViewAppeared(@NonNull android.view.ViewStructure); method public final void notifyViewDisappeared(@NonNull android.view.autofill.AutofillId); diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index f5dd8523a4c2..b25cf690b159 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -364,6 +364,7 @@ message Atom { AppsOnExternalStorageInfo apps_on_external_storage_info = 10057; FaceSettings face_settings = 10058; CoolingDevice cooling_device = 10059; + AppOps app_ops = 10060; } // DO NOT USE field numbers above 100,000 in AOSP. @@ -6363,3 +6364,41 @@ message GarageModeInfo { // Whether GarageMode is entered. optional bool is_garage_mode = 1; } + +/** + * Historical app ops data per package. + */ +message AppOps { + // Uid of the package requesting the op + optional int32 uid = 1 [(is_uid) = true]; + + // Nmae of the package performing the op + optional string package_name = 2; + + // operation id; maps to the OP_* constants in AppOpsManager.java + optional int32 op_id = 3; + + // The number of times the op was granted while the app was in the + // foreground (only for trusted requests) + optional int64 trusted_foreground_granted_count = 4; + + // The number of times the op was granted while the app was in the + // background (only for trusted requests) + optional int64 trusted_background_granted_count = 5; + + // The number of times the op was rejected while the app was in the + // foreground (only for trusted requests) + optional int64 trusted_foreground_rejected_count = 6; + + // The number of times the op was rejected while the app was in the + // background (only for trusted requests) + optional int64 trusted_background_rejected_count = 7; + + // For long-running operations, total duration of the operation + // while the app was in the foreground (only for trusted requests) + optional int64 trusted_foreground_duration_millis = 8; + + // For long-running operations, total duration of the operation + // while the app was in the background (only for trusted requests) + optional int64 trusted_background_duration_millis = 9; +} diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp index 2ffe18e20c24..914d60d3daca 100644 --- a/cmds/statsd/src/external/StatsPullerManager.cpp +++ b/cmds/statsd/src/external/StatsPullerManager.cpp @@ -260,6 +260,9 @@ std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = { // Face Settings {android::util::FACE_SETTINGS, {.puller = new StatsCompanionServicePuller(android::util::FACE_SETTINGS)}}, + // App ops + {android::util::APP_OPS, + {.puller = new StatsCompanionServicePuller(android::util::APP_OPS)}}, }; StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) { diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index ee62af57b9a0..69c1295df4f9 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -248,6 +248,8 @@ public class StorageManager { public static final int FLAG_STORAGE_DE = IInstalld.FLAG_STORAGE_DE; /** {@hide} */ public static final int FLAG_STORAGE_CE = IInstalld.FLAG_STORAGE_CE; + /** {@hide} */ + public static final int FLAG_STORAGE_EXTERNAL = IInstalld.FLAG_STORAGE_EXTERNAL; /** {@hide} */ public static final int FLAG_FOR_WRITE = 1 << 8; diff --git a/core/java/android/os/storage/VolumeRecord.java b/core/java/android/os/storage/VolumeRecord.java index b6ee26114963..1a794ebf2a59 100644 --- a/core/java/android/os/storage/VolumeRecord.java +++ b/core/java/android/os/storage/VolumeRecord.java @@ -25,6 +25,7 @@ import android.util.TimeUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; +import java.util.Locale; import java.util.Objects; /** @@ -45,6 +46,7 @@ public class VolumeRecord implements Parcelable { public String nickname; public int userFlags; public long createdMillis; + public long lastSeenMillis; public long lastTrimMillis; public long lastBenchMillis; @@ -61,6 +63,7 @@ public class VolumeRecord implements Parcelable { nickname = parcel.readString(); userFlags = parcel.readInt(); createdMillis = parcel.readLong(); + lastSeenMillis = parcel.readLong(); lastTrimMillis = parcel.readLong(); lastBenchMillis = parcel.readLong(); } @@ -73,6 +76,10 @@ public class VolumeRecord implements Parcelable { return fsUuid; } + public String getNormalizedFsUuid() { + return fsUuid != null ? fsUuid.toLowerCase(Locale.US) : null; + } + public String getNickname() { return nickname; } @@ -97,6 +104,7 @@ public class VolumeRecord implements Parcelable { DebugUtils.flagsToString(VolumeRecord.class, "USER_FLAG_", userFlags)); pw.println(); pw.printPair("createdMillis", TimeUtils.formatForLogging(createdMillis)); + pw.printPair("lastSeenMillis", TimeUtils.formatForLogging(lastSeenMillis)); pw.printPair("lastTrimMillis", TimeUtils.formatForLogging(lastTrimMillis)); pw.printPair("lastBenchMillis", TimeUtils.formatForLogging(lastBenchMillis)); pw.decreaseIndent(); @@ -155,6 +163,7 @@ public class VolumeRecord implements Parcelable { parcel.writeString(nickname); parcel.writeInt(userFlags); parcel.writeLong(createdMillis); + parcel.writeLong(lastSeenMillis); parcel.writeLong(lastTrimMillis); parcel.writeLong(lastBenchMillis); } diff --git a/core/java/android/service/appprediction/AppPredictionService.java b/core/java/android/service/appprediction/AppPredictionService.java index 1391d43b00ca..be20570ef62d 100644 --- a/core/java/android/service/appprediction/AppPredictionService.java +++ b/core/java/android/service/appprediction/AppPredictionService.java @@ -39,6 +39,7 @@ import android.os.Looper; import android.os.RemoteException; import android.service.appprediction.IPredictionService.Stub; import android.util.ArrayMap; +import android.util.Log; import android.util.Slog; import java.util.ArrayList; @@ -46,7 +47,7 @@ import java.util.List; import java.util.function.Consumer; /** - * TODO(b/111701043): Add java docs + * A service used to predict app and shortcut usage. * * @hide */ @@ -58,7 +59,9 @@ public abstract class AppPredictionService extends Service { /** * The {@link Intent} that must be declared as handled by the service. - * TODO(b/111701043): Add any docs about permissions the service must hold + * + * <p>The service must also require the {@link android.permission#MANAGE_APP_PREDICTIONS} + * permission. * * @hide */ @@ -145,8 +148,11 @@ public abstract class AppPredictionService extends Service { @Override @NonNull public final IBinder onBind(@NonNull Intent intent) { - // TODO(b/111701043): Verify that the action is valid - return mInterface.asBinder(); + if (SERVICE_INTERFACE.equals(intent.getAction())) { + return mInterface.asBinder(); + } + Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent); + return null; } /** @@ -180,7 +186,6 @@ public abstract class AppPredictionService extends Service { /** * Called by the client app to request sorting of targets based on prediction rank. - * TODO(b/111701043): Implement CancellationSignal so caller can cancel a long running request */ @MainThread public abstract void onSortAppTargets(@NonNull AppPredictionSessionId sessionId, @@ -254,7 +259,6 @@ public abstract class AppPredictionService extends Service { /** * Called by the client app to request target predictions. This method is only called if there * are one or more prediction callbacks registered. - * TODO(b/111701043): Add java docs * * @see #updatePredictions(AppPredictionSessionId, List) */ diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index d67c8847f3bc..63e14853b51d 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -2660,6 +2660,9 @@ public final class SurfaceControl implements Parcelable { */ @NonNull public Transaction merge(@NonNull Transaction other) { + if (this == other) { + return this; + } mResizedSurfaces.putAll(other.mResizedSurfaces); other.mResizedSurfaces.clear(); nativeMergeTransaction(mNativeObject, other.mNativeObject); diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java index 2d292ef7b25c..9340b71a5280 100644 --- a/core/java/android/view/WindowInsets.java +++ b/core/java/android/view/WindowInsets.java @@ -156,7 +156,9 @@ public final class WindowInsets { * @param src Source to copy insets from */ public WindowInsets(WindowInsets src) { - this(src.mTypeInsetsMap, src.mTypeMaxInsetsMap, src.mTypeVisibilityMap, src.mIsRound, + this(src.mSystemWindowInsetsConsumed ? null : src.mTypeInsetsMap, + src.mStableInsetsConsumed ? null : src.mTypeMaxInsetsMap, + src.mTypeVisibilityMap, src.mIsRound, src.mAlwaysConsumeSystemBars, displayCutoutCopyConstructorArgument(src)); } diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java index abb570318e68..f9f26251b15e 100644 --- a/core/java/android/view/contentcapture/ContentCaptureSession.java +++ b/core/java/android/view/contentcapture/ContentCaptureSession.java @@ -441,7 +441,46 @@ public abstract class ContentCaptureSession implements AutoCloseable { /** * Creates a {@link ViewStructure} for a "standard" view. * - * @hide + * <p>This method should be called after a visible view is laid out; the view then must populate + * the structure and pass it to {@link #notifyViewAppeared(ViewStructure)}. + * + * <b>Note: </b>views that manage a virtual structure under this view must populate just the + * node representing this view and return right away, then asynchronously report (not + * necessarily in the UI thread) when the children nodes appear, disappear or have their text + * changed by calling {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)}, + * {@link ContentCaptureSession#notifyViewDisappeared(AutofillId)}, and + * {@link ContentCaptureSession#notifyViewTextChanged(AutofillId, CharSequence)} respectively. + * The structure for the a child must be created using + * {@link ContentCaptureSession#newVirtualViewStructure(AutofillId, long)}, and the + * {@code autofillId} for a child can be obtained either through + * {@code childStructure.getAutofillId()} or + * {@link ContentCaptureSession#newAutofillId(AutofillId, long)}. + * + * <p>When the virtual view hierarchy represents a web page, you should also: + * + * <ul> + * <li>Call {@link ContentCaptureManager#getContentCaptureConditions()} to infer content capture + * events should be generate for that URL. + * <li>Create a new {@link ContentCaptureSession} child for every HTML element that renders a + * new URL (like an {@code IFRAME}) and use that session to notify events from that subtree. + * </ul> + * + * <p><b>Note: </b>the following methods of the {@code structure} will be ignored: + * <ul> + * <li>{@link ViewStructure#setChildCount(int)} + * <li>{@link ViewStructure#addChildCount(int)} + * <li>{@link ViewStructure#getChildCount()} + * <li>{@link ViewStructure#newChild(int)} + * <li>{@link ViewStructure#asyncNewChild(int)} + * <li>{@link ViewStructure#asyncCommit()} + * <li>{@link ViewStructure#setWebDomain(String)} + * <li>{@link ViewStructure#newHtmlInfoBuilder(String)} + * <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)} + * <li>{@link ViewStructure#setDataIsSensitive(boolean)} + * <li>{@link ViewStructure#setAlpha(float)} + * <li>{@link ViewStructure#setElevation(float)} + * <li>{@link ViewStructure#setTransformation(android.graphics.Matrix)} + * </ul> */ @NonNull public final ViewStructure newViewStructure(@NonNull View view) { diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index 685e8de3c01a..efd5daf0b455 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -774,7 +774,6 @@ public class NumberPicker extends LinearLayout { mInputText.setFilters(new InputFilter[] { new InputTextFilter() }); - mInputText.setAccessibilityLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE); mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER); mInputText.setImeOptions(EditorInfo.IME_ACTION_DONE); diff --git a/packages/CaptivePortalLogin/Android.bp b/packages/CaptivePortalLogin/Android.bp index a345091aa71e..1f6c2aef657c 100644 --- a/packages/CaptivePortalLogin/Android.bp +++ b/packages/CaptivePortalLogin/Android.bp @@ -14,12 +14,11 @@ // limitations under the License. // -android_app { - name: "CaptivePortalLogin", +java_defaults { + name: "CaptivePortalLoginDefaults", srcs: ["src/**/*.java"], sdk_version: "system_current", min_sdk_version: "28", - certificate: "networkstack", static_libs: [ "androidx.legacy_legacy-support-v4", "metrics-constants-protos", @@ -27,3 +26,18 @@ android_app { ], manifest: "AndroidManifest.xml", } + +android_app { + name: "CaptivePortalLogin", + defaults: ["CaptivePortalLoginDefaults"], + certificate: "networkstack", +} + +// Alternative CaptivePortalLogin signed with the platform cert, to use +// with InProcessNetworkStack. +android_app { + name: "PlatformCaptivePortalLogin", + defaults: ["CaptivePortalLoginDefaults"], + certificate: "platform", + overrides: ["CaptivePortalLogin"], +} diff --git a/packages/NetworkPermissionConfig/Android.bp b/packages/NetworkPermissionConfig/Android.bp index d0d3276c0e32..6e50459a1dd3 100644 --- a/packages/NetworkPermissionConfig/Android.bp +++ b/packages/NetworkPermissionConfig/Android.bp @@ -14,15 +14,28 @@ // limitations under the License. // -// Stub APK to define permissions for NetworkStack -android_app { - name: "NetworkPermissionConfig", +java_defaults { + name: "NetworkPermissionConfigDefaults", // TODO: mark app as hasCode=false in manifest once soong stops complaining about apps without // a classes.dex. srcs: ["src/**/*.java"], platform_apis: true, min_sdk_version: "28", - certificate: "networkstack", privileged: true, manifest: "AndroidManifest.xml", } + +// Stub APK to define permissions for NetworkStack +android_app { + name: "NetworkPermissionConfig", + defaults: ["NetworkPermissionConfigDefaults"], + certificate: "networkstack", +} + +// Alternative stub APK signed with platform certificate. To use with InProcessNetworkStack. +android_app { + name: "PlatformNetworkPermissionConfig", + defaults: ["NetworkPermissionConfigDefaults"], + certificate: "platform", + overrides: ["NetworkPermissionConfig"], +} diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp index 64718da8333b..e15526a571f5 100644 --- a/packages/NetworkStack/Android.bp +++ b/packages/NetworkStack/Android.bp @@ -98,8 +98,6 @@ java_defaults { optimize: { proguard_flags_files: ["proguard.flags"], }, - // The permission configuration *must* be included to ensure security of the device - required: ["NetworkPermissionConfig"], } // Non-updatable network stack running in the system server process for devices not using the module @@ -110,6 +108,8 @@ android_app { manifest: "AndroidManifest_InProcess.xml", // InProcessNetworkStack is a replacement for NetworkStack overrides: ["NetworkStack"], + // The permission configuration *must* be included to ensure security of the device + required: ["PlatformNetworkPermissionConfig"], } // Updatable network stack packaged as an application @@ -119,6 +119,8 @@ android_app { certificate: "networkstack", manifest: "AndroidManifest.xml", use_embedded_native_libs: true, + // The permission configuration *must* be included to ensure security of the device + required: ["NetworkPermissionConfig"], } genrule { diff --git a/packages/NetworkStack/src/android/net/apf/ApfFilter.java b/packages/NetworkStack/src/android/net/apf/ApfFilter.java index 2e1e96e45a1d..f05431968684 100644 --- a/packages/NetworkStack/src/android/net/apf/ApfFilter.java +++ b/packages/NetworkStack/src/android/net/apf/ApfFilter.java @@ -156,8 +156,7 @@ public class ApfFilter { DROPPED_ARP_REPLY_SPA_NO_HOST, DROPPED_IPV4_KEEPALIVE_ACK, DROPPED_IPV6_KEEPALIVE_ACK, - DROPPED_IPV4_NATT_KEEPALIVE, - DROPPED_IPV6_NATT_KEEPALIVE; + DROPPED_IPV4_NATT_KEEPALIVE; // Returns the negative byte offset from the end of the APF data segment for // a given counter. @@ -873,17 +872,17 @@ public class ApfFilter { } // A class to hold NAT-T keepalive ack information. - private abstract static class NattKeepaliveAck extends KeepalivePacket { + private class NattKeepaliveResponse extends KeepalivePacket { static final int UDP_LENGTH_OFFSET = 4; static final int UDP_HEADER_LEN = 8; - protected static class NattKeepaliveAckData { + protected class NattKeepaliveResponseData { public final byte[] srcAddress; public final int srcPort; public final byte[] dstAddress; public final int dstPort; - NattKeepaliveAckData(final NattKeepalivePacketDataParcelable sentKeepalivePacket) { + NattKeepaliveResponseData(final NattKeepalivePacketDataParcelable sentKeepalivePacket) { srcAddress = sentKeepalivePacket.dstAddress; srcPort = sentKeepalivePacket.dstPort; dstAddress = sentKeepalivePacket.srcAddress; @@ -891,19 +890,19 @@ public class ApfFilter { } } - protected final NattKeepaliveAckData mPacket; + protected final NattKeepaliveResponseData mPacket; protected final byte[] mSrcDstAddr; protected final byte[] mPortFingerprint; // NAT-T keepalive packet protected final byte[] mPayload = {(byte) 0xff}; - NattKeepaliveAck(final NattKeepaliveAckData packet, final byte[] srcDstAddr) { - mPacket = packet; - mSrcDstAddr = srcDstAddr; + NattKeepaliveResponse(final NattKeepalivePacketDataParcelable sentKeepalivePacket) { + mPacket = new NattKeepaliveResponseData(sentKeepalivePacket); + mSrcDstAddr = concatArrays(mPacket.srcAddress, mPacket.dstAddress); mPortFingerprint = generatePortFingerprint(mPacket.srcPort, mPacket.dstPort); } - static byte[] generatePortFingerprint(int srcPort, int dstPort) { + byte[] generatePortFingerprint(int srcPort, int dstPort) { final ByteBuffer fp = ByteBuffer.allocate(4); fp.order(ByteOrder.BIG_ENDIAN); fp.putShort((short) srcPort); @@ -911,27 +910,6 @@ public class ApfFilter { return fp.array(); } - public String toString() { - try { - return String.format("%s -> %s", - NetworkStackUtils.addressAndPortToString( - InetAddress.getByAddress(mPacket.srcAddress), mPacket.srcPort), - NetworkStackUtils.addressAndPortToString( - InetAddress.getByAddress(mPacket.dstAddress), mPacket.dstPort)); - } catch (UnknownHostException e) { - return "Unknown host"; - } - } - } - - private class NattKeepaliveAckV4 extends NattKeepaliveAck { - NattKeepaliveAckV4(final NattKeepalivePacketDataParcelable sentKeepalivePacket) { - this(new NattKeepaliveAckData(sentKeepalivePacket)); - } - NattKeepaliveAckV4(final NattKeepaliveAckData packet) { - super(packet, concatArrays(packet.srcAddress, packet.dstAddress) /* srcDstAddr */); - } - @Override void generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException { final String nextFilterLabel = "natt_keepalive_filter" + getUniqueNumberLocked(); @@ -949,10 +927,9 @@ public class ApfFilter { gen.addAddR1(); gen.addJumpIfR0NotEquals(1, nextFilterLabel); - // R0 = R0 + R1 -> R0 contains IP header - gen.addLoadFromMemory(Register.R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT); - gen.addLoadImmediate(Register.R0, ETH_HEADER_LEN); - gen.addAddR1(); + // Check that the ports match + gen.addLoadFromMemory(Register.R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT); + gen.addAdd(ETH_HEADER_LEN); gen.addJumpIfBytesNotEqual(Register.R0, mPortFingerprint, nextFilterLabel); // Payload offset = R0 + UDP header length @@ -963,20 +940,17 @@ public class ApfFilter { gen.addJump(mCountAndDropLabel); gen.defineLabel(nextFilterLabel); } - } - - private class NattKeepaliveAckV6 extends NattKeepaliveAck { - NattKeepaliveAckV6(final NattKeepalivePacketDataParcelable sentKeepalivePacket) { - this(new NattKeepaliveAckData(sentKeepalivePacket)); - } - - NattKeepaliveAckV6(final NattKeepaliveAckData packet) { - super(packet, concatArrays(packet.srcAddress, packet.dstAddress) /* srcDstAddr */); - } - @Override - void generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException { - throw new UnsupportedOperationException("IPv6 NAT-T Keepalive is not supported yet"); + public String toString() { + try { + return String.format("%s -> %s", + NetworkStackUtils.addressAndPortToString( + InetAddress.getByAddress(mPacket.srcAddress), mPacket.srcPort), + NetworkStackUtils.addressAndPortToString( + InetAddress.getByAddress(mPacket.dstAddress), mPacket.dstPort)); + } catch (UnknownHostException e) { + return "Unknown host"; + } } } @@ -1296,6 +1270,7 @@ public class ApfFilter { gen.addJump(mCountAndDropLabel); } else { generateV4KeepaliveFilters(gen); + generateV4NattKeepaliveFilters(gen); } // Otherwise, pass @@ -1303,36 +1278,36 @@ public class ApfFilter { gen.addJump(mCountAndPassLabel); } - private void generateFilters(ApfGenerator gen, Class<?> filterType, int proto, int offset, - String label) throws IllegalInstructionException { - final boolean haveKeepaliveAcks = NetworkStackUtils.any(mKeepalivePackets, + private void generateKeepaliveFilters(ApfGenerator gen, Class<?> filterType, int proto, + int offset, String label) throws IllegalInstructionException { + final boolean haveKeepaliveResponses = NetworkStackUtils.any(mKeepalivePackets, ack -> filterType.isInstance(ack)); // If no keepalive packets of this type - if (!haveKeepaliveAcks) return; + if (!haveKeepaliveResponses) return; // If not the right proto, skip keepalive filters gen.addLoad8(Register.R0, offset); gen.addJumpIfR0NotEquals(proto, label); - // Drop Keepalive packets + // Drop Keepalive responses for (int i = 0; i < mKeepalivePackets.size(); ++i) { - final KeepalivePacket ack = mKeepalivePackets.valueAt(i); - if (filterType.isInstance(ack)) ack.generateFilterLocked(gen); + final KeepalivePacket response = mKeepalivePackets.valueAt(i); + if (filterType.isInstance(response)) response.generateFilterLocked(gen); } gen.defineLabel(label); } private void generateV4KeepaliveFilters(ApfGenerator gen) throws IllegalInstructionException { - generateFilters(gen, TcpKeepaliveAckV4.class, IPPROTO_TCP, IPV4_PROTOCOL_OFFSET, + generateKeepaliveFilters(gen, TcpKeepaliveAckV4.class, IPPROTO_TCP, IPV4_PROTOCOL_OFFSET, "skip_v4_keepalive_filter"); } private void generateV4NattKeepaliveFilters(ApfGenerator gen) throws IllegalInstructionException { - generateFilters(gen, NattKeepaliveAckV4.class, IPPROTO_UDP, IPV4_PROTOCOL_OFFSET, - "skip_v4_nattkeepalive_filter"); + generateKeepaliveFilters(gen, NattKeepaliveResponse.class, + IPPROTO_UDP, IPV4_PROTOCOL_OFFSET, "skip_v4_nattkeepalive_filter"); } /** @@ -1417,7 +1392,7 @@ public class ApfFilter { } private void generateV6KeepaliveFilters(ApfGenerator gen) throws IllegalInstructionException { - generateFilters(gen, TcpKeepaliveAckV6.class, IPPROTO_TCP, IPV6_NEXT_HEADER_OFFSET, + generateKeepaliveFilters(gen, TcpKeepaliveAckV6.class, IPPROTO_TCP, IPV6_NEXT_HEADER_OFFSET, "skip_v6_keepalive_filter"); } @@ -1819,8 +1794,8 @@ public class ApfFilter { } /** - * Add NATT keepalive packet filter. - * This will add a filter to drop NATT keepalive packet which is passed as an argument. + * Add NAT-T keepalive packet filter. + * This will add a filter to drop NAT-T keepalive packet which is passed as an argument. * * @param slot The index used to access the filter. * @param sentKeepalivePacket The attributes of the sent keepalive packet. @@ -1829,12 +1804,12 @@ public class ApfFilter { final NattKeepalivePacketDataParcelable sentKeepalivePacket) { log("Adding NAT-T keepalive packet(" + slot + ")"); if (null != mKeepalivePackets.get(slot)) { - throw new IllegalArgumentException("Natt Keepalive slot " + slot + " is occupied"); + throw new IllegalArgumentException("NAT-T Keepalive slot " + slot + " is occupied"); } - final int ipVersion = sentKeepalivePacket.srcAddress.length == 4 ? 4 : 6; - mKeepalivePackets.put(slot, (ipVersion == 4) - ? new NattKeepaliveAckV4(sentKeepalivePacket) - : new NattKeepaliveAckV6(sentKeepalivePacket)); + if (sentKeepalivePacket.srcAddress.length != 4) { + throw new IllegalArgumentException("NAT-T keepalive is only supported on IPv4"); + } + mKeepalivePackets.put(slot, new NattKeepaliveResponse(sentKeepalivePacket)); installNewProgramLocked(); } @@ -1908,7 +1883,7 @@ public class ApfFilter { if (keepalivePacket instanceof TcpKeepaliveAck) { pw.print("Slot "); pw.print(mKeepalivePackets.keyAt(i)); - pw.print(" : "); + pw.print(": "); pw.println(keepalivePacket); } } @@ -1918,10 +1893,10 @@ public class ApfFilter { pw.increaseIndent(); for (int i = 0; i < mKeepalivePackets.size(); ++i) { final KeepalivePacket keepalivePacket = mKeepalivePackets.valueAt(i); - if (keepalivePacket instanceof NattKeepaliveAck) { + if (keepalivePacket instanceof NattKeepaliveResponse) { pw.print("Slot "); pw.print(mKeepalivePackets.keyAt(i)); - pw.print(" : "); + pw.print(": "); pw.println(keepalivePacket); } } diff --git a/packages/NetworkStack/src/com/android/networkstack/util/DnsUtils.java b/packages/NetworkStack/src/com/android/networkstack/util/DnsUtils.java index 85f94e17a088..4767d5574a00 100644 --- a/packages/NetworkStack/src/com/android/networkstack/util/DnsUtils.java +++ b/packages/NetworkStack/src/com/android/networkstack/util/DnsUtils.java @@ -55,12 +55,23 @@ public class DnsUtils { throws UnknownHostException { final List<InetAddress> result = new ArrayList<InetAddress>(); - result.addAll(Arrays.asList( - getAllByName(dnsResolver, network, host, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP, - timeout))); - result.addAll(Arrays.asList( - getAllByName(dnsResolver, network, host, TYPE_A, FLAG_NO_CACHE_LOOKUP, - timeout))); + try { + result.addAll(Arrays.asList( + getAllByName(dnsResolver, network, host, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP, + timeout))); + } catch (UnknownHostException e) { + // Might happen if the host is v4-only, still need to query TYPE_A + } + try { + result.addAll(Arrays.asList( + getAllByName(dnsResolver, network, host, TYPE_A, FLAG_NO_CACHE_LOOKUP, + timeout))); + } catch (UnknownHostException e) { + // Might happen if the host is v6-only, still need to return AAAA answers + } + if (result.size() == 0) { + throw new UnknownHostException(host); + } return result.toArray(new InetAddress[0]); } diff --git a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java b/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java index 41c3fab8f0d0..8f2b96807860 100644 --- a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java +++ b/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java @@ -1734,7 +1734,8 @@ public class ApfTest { final int dstPort = 4500; final int slot1 = 1; // NAT-T keepalive - final byte[] payload = {(byte) 0xff}; + final byte[] kaPayload = {(byte) 0xff}; + final byte[] nonKaPayload = {(byte) 0xfe}; // src: 10.0.0.5, port: 1024 // dst: 10.0.0.6, port: 4500 @@ -1753,15 +1754,21 @@ public class ApfTest { // Verify IPv4 keepalive packet is dropped // src: 10.0.0.6, port: 4500 // dst: 10.0.0.5, port: 1024 - final byte[] nattKaPkt = ipv4UdpPacket(IPV4_KEEPALIVE_DST_ADDR, + byte[] pkt = ipv4UdpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR, dstPort, srcPort, 1 /* dataLength */); - System.arraycopy(payload, 0, nattKaPkt, IPV4_UDP_PAYLOAD_OFFSET, payload.length); - assertDrop(program, nattKaPkt); - // Verify IPv4 non-keepalive packet from the same source address is passed + System.arraycopy(kaPayload, 0, pkt, IPV4_UDP_PAYLOAD_OFFSET, kaPayload.length); + assertDrop(program, pkt); + + // Verify a packet with payload length 1 byte but it is not 0xff will pass the filter. + System.arraycopy(nonKaPayload, 0, pkt, IPV4_UDP_PAYLOAD_OFFSET, nonKaPayload.length); + assertPass(program, pkt); + + // Verify IPv4 non-keepalive response packet from the same source address is passed assertPass(program, ipv4UdpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR, dstPort, srcPort, 10 /* dataLength */)); - // Verify IPv4 non-keepalive packet from other source address is passed + + // Verify IPv4 non-keepalive response packet from other source address is passed assertPass(program, ipv4UdpPacket(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, dstPort, srcPort, 10 /* dataLength */)); diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java index abfb9c8ae282..832b7124dc05 100644 --- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java +++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java @@ -298,8 +298,10 @@ public class NetworkMonitorTest { setFallbackSpecs(null); // Test with no fallback spec by default when(mRandom.nextInt()).thenReturn(0); + // DNS probe timeout should not be defined more than half of HANDLER_TIMEOUT_MS. Otherwise, + // it will fail the test because of timeout expired for querying AAAA and A sequentially. when(mResources.getInteger(eq(R.integer.config_captive_portal_dns_probe_timeout))) - .thenReturn(500); + .thenReturn(200); doAnswer((invocation) -> { URL url = invocation.getArgument(0); diff --git a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java index b7bb751c1582..a150de95fcf0 100644 --- a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java +++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java @@ -662,11 +662,17 @@ public class LegacyRecentsImpl implements RecentsImplementation { public final void onBusEvent(ExpandPipEvent event) { PipUI pipUi = getComponent(PipUI.class); + if (pipUi == null) { + return; + } pipUi.expandPip(); } public final void onBusEvent(HidePipMenuEvent event) { PipUI pipUi = getComponent(PipUI.class); + if (pipUi == null) { + return; + } event.getAnimationTrigger().increment(); pipUi.hidePipMenu(() -> { event.getAnimationTrigger().increment(); diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml index cdef09d73f77..2792a019f8d8 100644 --- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml +++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml @@ -31,23 +31,36 @@ android:layout_height="wrap_content" android:layout_marginBottom="@dimen/keyguard_indication_margin_bottom" android:layout_gravity="bottom|center_horizontal" - android:orientation="vertical"> + android:orientation="horizontal"> - <com.android.systemui.statusbar.phone.KeyguardIndicationTextView - android:id="@+id/keyguard_indication_enterprise_disclosure" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:gravity="center" - android:textAppearance="@style/TextAppearance.Keyguard.BottomArea" - android:visibility="gone" /> + <include layout="@layout/left_docked_overlay" /> - <com.android.systemui.statusbar.phone.KeyguardIndicationTextView - android:id="@+id/keyguard_indication_text" - android:layout_width="match_parent" + <LinearLayout + android:layout_width="wrap_content" android:layout_height="wrap_content" - android:gravity="center" - android:textAppearance="@style/TextAppearance.Keyguard.BottomArea" - android:accessibilityLiveRegion="polite" /> + android:layout_weight="1" + android:layout_gravity="center_vertical|center_horizontal" + android:orientation="vertical"> + + <com.android.systemui.statusbar.phone.KeyguardIndicationTextView + android:id="@+id/keyguard_indication_enterprise_disclosure" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center" + android:textAppearance="@style/TextAppearance.Keyguard.BottomArea" + android:visibility="gone" /> + + <com.android.systemui.statusbar.phone.KeyguardIndicationTextView + android:id="@+id/keyguard_indication_text" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center" + android:textAppearance="@style/TextAppearance.Keyguard.BottomArea" + android:accessibilityLiveRegion="polite" /> + + </LinearLayout> + + <include layout="@layout/right_docked_overlay" /> </LinearLayout> diff --git a/packages/SystemUI/res/layout/left_docked_overlay.xml b/packages/SystemUI/res/layout/left_docked_overlay.xml new file mode 100644 index 000000000000..430143ca3bc2 --- /dev/null +++ b/packages/SystemUI/res/layout/left_docked_overlay.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<!-- empty stub --> +<merge /> diff --git a/packages/SystemUI/res/layout/right_docked_overlay.xml b/packages/SystemUI/res/layout/right_docked_overlay.xml new file mode 100644 index 000000000000..430143ca3bc2 --- /dev/null +++ b/packages/SystemUI/res/layout/right_docked_overlay.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<!-- empty stub --> +<merge /> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index dd6ccb2b3a88..ea8565e8d301 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -238,6 +238,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private boolean mIsDreaming; private final DevicePolicyManager mDevicePolicyManager; private boolean mLogoutEnabled; + // If the user long pressed the lock icon, disabling face auth for the current session. + private boolean mLockIconPressed; /** * Short delay before restarting biometric authentication after a successful try @@ -1384,6 +1386,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } private void handleScreenTurnedOff() { + mLockIconPressed = false; mHardwareFingerprintUnavailableRetryCount = 0; mHardwareFaceUnavailableRetryCount = 0; final int count = mCallbacks.size(); @@ -1625,10 +1628,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware. return (mBouncer || mAuthInterruptActive || awakeKeyguard || shouldListenForFaceAssistant()) && !mSwitchingUser && !getUserCanSkipBouncer(user) && !isFaceDisabled(user) - && !mKeyguardGoingAway && mFaceSettingEnabledForUser + && !mKeyguardGoingAway && mFaceSettingEnabledForUser && !mLockIconPressed && mUserManager.isUserUnlocked(user) && mIsPrimaryUser; } + /** + * Whenever the lock icon is long pressed, disabling trust agents. + * This means that we cannot auth passively (face) until the user presses power. + */ + public void onLockIconPressed() { + mLockIconPressed = true; + mUserFaceAuthenticated.put(getCurrentUser(), false); + updateFaceListeningState(); + } private void startListeningForFingerprint() { if (mFingerprintRunningState == BIOMETRIC_STATE_CANCELLING) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index a76c9dc9f40a..fd76a79eab2e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -189,6 +189,7 @@ public class KeyguardIndicationController implements StateListener, mLockscreenGestureLogger.write(MetricsProto.MetricsEvent.ACTION_LS_LOCK, 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */); showTransientIndication(R.string.keyguard_indication_trust_disabled); + mKeyguardUpdateMonitor.onLockIconPressed(); mLockPatternUtils.requireCredentialEntry(KeyguardUpdateMonitor.getCurrentUser()); return true; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java index 6d9a77c58227..daee55bd3d61 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java @@ -261,6 +261,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { longClickCaptor.getValue().onLongClick(mLockIcon); verify(mLockPatternUtils).requireCredentialEntry(anyInt()); + verify(mKeyguardUpdateMonitor).onLockIconPressed(); } @Test diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index c6461491b8cd..fc355b7cce2f 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -286,6 +286,7 @@ class StorageManagerService extends IStorageManager.Stub private static final String ATTR_NICKNAME = "nickname"; private static final String ATTR_USER_FLAGS = "userFlags"; private static final String ATTR_CREATED_MILLIS = "createdMillis"; + private static final String ATTR_LAST_SEEN_MILLIS = "lastSeenMillis"; private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis"; private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis"; @@ -1313,7 +1314,7 @@ class StorageManagerService extends IStorageManager.Stub private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) { // Remember that we saw this volume so we're ready to accept user // metadata, or so we can annoy them when a private volume is ejected - if (vol.isMountedReadable() && !TextUtils.isEmpty(vol.fsUuid)) { + if (!TextUtils.isEmpty(vol.fsUuid)) { VolumeRecord rec = mRecords.get(vol.fsUuid); if (rec == null) { rec = new VolumeRecord(vol.type, vol.fsUuid); @@ -1323,14 +1324,15 @@ class StorageManagerService extends IStorageManager.Stub rec.nickname = vol.disk.getDescription(); } mRecords.put(rec.fsUuid, rec); - writeSettingsLocked(); } else { // Handle upgrade case where we didn't store partition GUID if (TextUtils.isEmpty(rec.partGuid)) { rec.partGuid = vol.partGuid; - writeSettingsLocked(); } } + + rec.lastSeenMillis = System.currentTimeMillis(); + writeSettingsLocked(); } mCallbacks.notifyVolumeStateChanged(vol, oldState, newState); @@ -1731,9 +1733,10 @@ class StorageManagerService extends IStorageManager.Stub meta.partGuid = readStringAttribute(in, ATTR_PART_GUID); meta.nickname = readStringAttribute(in, ATTR_NICKNAME); meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS); - meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS); - meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS); - meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS); + meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS, 0); + meta.lastSeenMillis = readLongAttribute(in, ATTR_LAST_SEEN_MILLIS, 0); + meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS, 0); + meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS, 0); return meta; } @@ -1745,6 +1748,7 @@ class StorageManagerService extends IStorageManager.Stub writeStringAttribute(out, ATTR_NICKNAME, rec.nickname); writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags); writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis); + writeLongAttribute(out, ATTR_LAST_SEEN_MILLIS, rec.lastSeenMillis); writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis); writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis); out.endTag(null, TAG_VOLUME); diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index 88919df04f00..b9a6a1020a77 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -760,7 +760,6 @@ public class BiometricService extends SystemService { @Override // Binder call public int canAuthenticate(String opPackageName) { checkPermission(); - checkAppOp(opPackageName, Binder.getCallingUid()); final int userId = UserHandle.getCallingUserId(); final long ident = Binder.clearCallingIdentity(); @@ -833,9 +832,9 @@ public class BiometricService extends SystemService { } private void checkPermission() { - if (getContext().checkCallingPermission(USE_FINGERPRINT) + if (getContext().checkCallingOrSelfPermission(USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) { - getContext().enforceCallingPermission(USE_BIOMETRIC, + getContext().enforceCallingOrSelfPermission(USE_BIOMETRIC, "Must have USE_BIOMETRIC permission"); } } diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index c2125b0a997d..b246eb6d38bd 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -421,8 +421,9 @@ public class LockSettingsService extends ILockSettings.Stub { new PasswordSlotManager()); } - public boolean hasBiometrics() { - return BiometricManager.hasBiometrics(mContext); + public boolean hasEnrolledBiometrics() { + BiometricManager bm = mContext.getSystemService(BiometricManager.class); + return bm.canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS; } public int binderGetCallingUid() { @@ -2502,7 +2503,8 @@ public class LockSettingsService extends ILockSettings.Stub { // TODO: When lockout is handled under the HAL for all biometrics (fingerprint), // we need to generate challenge for each one, have it signed by GK and reset lockout // for each modality. - if (!hasChallenge && pm.hasSystemFeature(PackageManager.FEATURE_FACE)) { + if (!hasChallenge && pm.hasSystemFeature(PackageManager.FEATURE_FACE) + && mInjector.hasEnrolledBiometrics()) { challenge = mContext.getSystemService(FaceManager.class).generateChallenge(); } @@ -2544,8 +2546,8 @@ public class LockSettingsService extends ILockSettings.Stub { if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { notifyActivePasswordMetricsAvailable(credentialType, userCredential, userId); unlockKeystore(authResult.authToken.deriveKeyStorePassword(), userId); - // Reset lockout - if (mInjector.hasBiometrics()) { + // Reset lockout only if user has enrolled templates + if (mInjector.hasEnrolledBiometrics()) { BiometricManager bm = mContext.getSystemService(BiometricManager.class); Slog.i(TAG, "Resetting lockout, length: " + authResult.gkResponse.getPayload().length); diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java index ef94000d3a6b..388e51f203ca 100644 --- a/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java +++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java @@ -30,6 +30,7 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; +import java.security.spec.InvalidParameterSpecException; import java.util.Arrays; import javax.crypto.BadPaddingException; @@ -43,6 +44,7 @@ import javax.crypto.spec.SecretKeySpec; public class SyntheticPasswordCrypto { private static final int PROFILE_KEY_IV_SIZE = 12; + private static final int DEFAULT_TAG_LENGTH_BITS = 128; private static final int AES_KEY_LENGTH = 32; // 256-bit AES key private static final byte[] APPLICATION_ID_PERSONALIZATION = "application-id".getBytes(); // Time between the user credential is verified with GK and the decryption of synthetic password @@ -60,13 +62,14 @@ public class SyntheticPasswordCrypto { byte[] ciphertext = Arrays.copyOfRange(blob, PROFILE_KEY_IV_SIZE, blob.length); Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/" + KeyProperties.ENCRYPTION_PADDING_NONE); - cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(128, iv)); + cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(DEFAULT_TAG_LENGTH_BITS, iv)); return cipher.doFinal(ciphertext); } private static byte[] encrypt(SecretKey key, byte[] blob) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, - InvalidKeyException, IllegalBlockSizeException, BadPaddingException { + InvalidKeyException, IllegalBlockSizeException, BadPaddingException, + InvalidParameterSpecException { if (blob == null) { return null; } @@ -79,6 +82,11 @@ public class SyntheticPasswordCrypto { if (iv.length != PROFILE_KEY_IV_SIZE) { throw new RuntimeException("Invalid iv length: " + iv.length); } + final GCMParameterSpec spec = cipher.getParameters().getParameterSpec( + GCMParameterSpec.class); + if (spec.getTLen() != DEFAULT_TAG_LENGTH_BITS) { + throw new RuntimeException("Invalid tag length: " + spec.getTLen()); + } ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); outputStream.write(iv); outputStream.write(ciphertext); @@ -92,7 +100,8 @@ public class SyntheticPasswordCrypto { try { return encrypt(key, message); } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException - | IllegalBlockSizeException | BadPaddingException | IOException e) { + | IllegalBlockSizeException | BadPaddingException | IOException + | InvalidParameterSpecException e) { e.printStackTrace(); return null; } @@ -147,7 +156,7 @@ public class SyntheticPasswordCrypto { public static byte[] createBlob(String keyAlias, byte[] data, byte[] applicationId, long sid) { try { KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES); - keyGenerator.init(new SecureRandom()); + keyGenerator.init(AES_KEY_LENGTH * 8, new SecureRandom()); SecretKey secretKey = keyGenerator.generateKey(); KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); @@ -169,7 +178,8 @@ public class SyntheticPasswordCrypto { } catch (CertificateException | IOException | BadPaddingException | IllegalBlockSizeException | KeyStoreException | NoSuchPaddingException | NoSuchAlgorithmException - | InvalidKeyException e) { + | InvalidKeyException + | InvalidParameterSpecException e) { e.printStackTrace(); throw new RuntimeException("Failed to encrypt blob", e); } diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index bab612d3c092..9d115963423d 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -73,6 +73,7 @@ public class Installer extends SystemService { public static final int FLAG_STORAGE_DE = IInstalld.FLAG_STORAGE_DE; public static final int FLAG_STORAGE_CE = IInstalld.FLAG_STORAGE_CE; + public static final int FLAG_STORAGE_EXTERNAL = IInstalld.FLAG_STORAGE_EXTERNAL; public static final int FLAG_CLEAR_CACHE_ONLY = IInstalld.FLAG_CLEAR_CACHE_ONLY; public static final int FLAG_CLEAR_CODE_CACHE_ONLY = IInstalld.FLAG_CLEAR_CODE_CACHE_ONLY; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 85833ab38533..36b763734330 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -89,6 +89,7 @@ import static android.content.pm.PackageParser.isApkFile; import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; import static android.os.storage.StorageManager.FLAG_STORAGE_CE; import static android.os.storage.StorageManager.FLAG_STORAGE_DE; +import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL; import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE; import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT; @@ -3249,7 +3250,7 @@ public class PackageManagerService extends IPackageManager.Stub if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) { // No apps are running this early, so no need to freeze clearAppDataLIF(ps.pkg, UserHandle.USER_ALL, - StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE + FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); } } @@ -3501,8 +3502,8 @@ public class PackageManagerService extends IPackageManager.Stub } return false; } - clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE - | FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); + clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE + | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); mDexManager.notifyPackageUpdated(pkg.packageName, pkg.baseCodePath, pkg.splitCodePaths); } @@ -15980,6 +15981,9 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mInstallLock) { // Clean up both app data and code // All package moves are frozen until finished + + // We purposefully exclude FLAG_STORAGE_EXTERNAL here, since + // this task was only focused on moving data on internal storage. for (int userId : userIds) { try { mInstaller.destroyAppData(volumeUuid, move.packageName, userId, @@ -17080,8 +17084,8 @@ public class PackageManagerService extends IPackageManager.Stub final String packageName = pkg.packageName; prepareAppDataAfterInstallLIF(pkg); if (reconciledPkg.prepareResult.clearCodeCache) { - clearAppDataLIF(pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE - | StorageManager.FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); + clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE + | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); } if (reconciledPkg.prepareResult.replace) { mDexManager.notifyPackageUpdated(pkg.packageName, @@ -18853,7 +18857,7 @@ public class PackageManagerService extends IPackageManager.Stub resolvedPkg.setVolumeUuid(deletedPs.volumeUuid); } destroyAppDataLIF(resolvedPkg, UserHandle.USER_ALL, - StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE); + FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL); destroyAppProfilesLIF(resolvedPkg); if (outInfo != null) { outInfo.dataRemoved = true; @@ -19605,7 +19609,7 @@ public class PackageManagerService extends IPackageManager.Stub } destroyAppDataLIF(pkg, nextUserId, - StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE); + FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL); clearDefaultBrowserIfNeededForUser(ps.name, nextUserId); removeKeystoreDataIfNeeded(nextUserId, ps.appId); final SparseBooleanArray changedUsers = new SparseBooleanArray(); @@ -19741,7 +19745,7 @@ public class PackageManagerService extends IPackageManager.Stub } clearAppDataLIF(pkg, userId, - StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE); + FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL); final int appId = UserHandle.getAppId(pkg.applicationInfo.uid); removeKeystoreDataIfNeeded(userId, appId); @@ -19972,8 +19976,7 @@ public class PackageManagerService extends IPackageManager.Stub } if (doClearData) { synchronized (mInstallLock) { - final int flags = StorageManager.FLAG_STORAGE_DE - | StorageManager.FLAG_STORAGE_CE; + final int flags = FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL; // We're only clearing cache files, so we don't care if the // app is unfrozen and still able to run clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CACHE_ONLY); @@ -22521,9 +22524,8 @@ public class PackageManagerService extends IPackageManager.Stub } if (!Build.FINGERPRINT.equals(ver.fingerprint)) { - clearAppDataLIF(ps.pkg, UserHandle.USER_ALL, - StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE - | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); + clearAppDataLIF(ps.pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE + | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); } } } diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java index 1edb93a0cdb9..7d0da68a0750 100644 --- a/services/core/java/com/android/server/stats/StatsCompanionService.java +++ b/services/core/java/com/android/server/stats/StatsCompanionService.java @@ -15,6 +15,7 @@ */ package com.android.server.stats; +import static android.app.AppOpsManager.OP_FLAGS_ALL_TRUSTED; import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS; import static android.os.Process.getPidsForCommands; @@ -33,6 +34,11 @@ import android.annotation.Nullable; import android.app.ActivityManagerInternal; import android.app.AlarmManager; import android.app.AlarmManager.OnAlarmListener; +import android.app.AppOpsManager; +import android.app.AppOpsManager.HistoricalOps; +import android.app.AppOpsManager.HistoricalOpsRequest; +import android.app.AppOpsManager.HistoricalPackageOps; +import android.app.AppOpsManager.HistoricalUidOps; import android.app.ProcessMemoryHighWaterMark; import android.app.ProcessMemoryState; import android.app.StatsManager; @@ -146,6 +152,8 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; +import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -154,6 +162,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -1941,6 +1950,53 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } + private void pullAppOps(long elapsedNanos, final long wallClockNanos, + List<StatsLogEventWrapper> pulledData) { + long token = Binder.clearCallingIdentity(); + try { + AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); + + CompletableFuture<HistoricalOps> ops = new CompletableFuture<>(); + HistoricalOpsRequest histOpsRequest = + new HistoricalOpsRequest.Builder( + Instant.now().minus(1, ChronoUnit.HOURS).toEpochMilli(), + Long.MAX_VALUE).build(); + appOps.getHistoricalOps(histOpsRequest, mContext.getMainExecutor(), ops::complete); + + HistoricalOps histOps = ops.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS, + TimeUnit.MILLISECONDS); + + StatsLogEventWrapper e = new StatsLogEventWrapper(StatsLog.APP_OPS, elapsedNanos, + wallClockNanos); + + for (int uidIdx = 0; uidIdx < histOps.getUidCount(); uidIdx++) { + final HistoricalUidOps uidOps = histOps.getUidOpsAt(uidIdx); + final int uid = uidOps.getUid(); + for (int pkgIdx = 0; pkgIdx < uidOps.getPackageCount(); pkgIdx++) { + final HistoricalPackageOps packageOps = uidOps.getPackageOpsAt(pkgIdx); + for (int opIdx = 0; opIdx < packageOps.getOpCount(); opIdx++) { + final AppOpsManager.HistoricalOp op = packageOps.getOpAt(opIdx); + e.writeInt(uid); + e.writeString(packageOps.getPackageName()); + e.writeInt(op.getOpCode()); + e.writeLong(op.getForegroundAccessCount(OP_FLAGS_ALL_TRUSTED)); + e.writeLong(op.getBackgroundAccessCount(OP_FLAGS_ALL_TRUSTED)); + e.writeLong(op.getForegroundRejectCount(OP_FLAGS_ALL_TRUSTED)); + e.writeLong(op.getBackgroundRejectCount(OP_FLAGS_ALL_TRUSTED)); + e.writeLong(op.getForegroundAccessDuration(OP_FLAGS_ALL_TRUSTED)); + e.writeLong(op.getBackgroundAccessDuration(OP_FLAGS_ALL_TRUSTED)); + pulledData.add(e); + } + } + } + } catch (Throwable t) { + Log.e(TAG, "Could not read appops", t); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + /** * Add a RoleHolder atom for each package that holds a role. * @@ -2331,6 +2387,10 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { pullFaceSettings(tagId, elapsedNanos, wallClockNanos, ret); break; } + case StatsLog.APP_OPS: { + pullAppOps(elapsedNanos, wallClockNanos, ret); + break; + } default: Slog.w(TAG, "No such tagId data as " + tagId); return null; diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index fd90f0339e63..ecbecbafd3d5 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -2005,7 +2005,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } layoutLetterbox(winHint); if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) { - mLetterbox.applySurfaceChanges(mPendingTransaction); + mLetterbox.applySurfaceChanges(getPendingTransaction()); } } @@ -3059,13 +3059,13 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree if (mSurfaceControl != null) { if (show && !mLastSurfaceShowing) { - mPendingTransaction.show(mSurfaceControl); + getPendingTransaction().show(mSurfaceControl); } else if (!show && mLastSurfaceShowing) { - mPendingTransaction.hide(mSurfaceControl); + getPendingTransaction().hide(mSurfaceControl); } } if (mThumbnail != null) { - mThumbnail.setShowing(mPendingTransaction, show); + mThumbnail.setShowing(getPendingTransaction(), show); } mLastSurfaceShowing = show; super.prepareSurfaces(); @@ -3225,8 +3225,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree private void updateColorTransform() { if (mSurfaceControl != null && mLastAppSaturationInfo != null) { - mPendingTransaction.setColorTransform(mSurfaceControl, mLastAppSaturationInfo.mMatrix, - mLastAppSaturationInfo.mTranslation); + getPendingTransaction().setColorTransform(mSurfaceControl, + mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation); mWmService.scheduleAnimationLocked(); } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index a61b27e90202..6ad8ece2b612 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -1479,7 +1479,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // the top of the method, the caller is obligated to call computeNewConfigurationLocked(). // By updating the Display info here it will be available to // #computeScreenConfiguration() later. - updateDisplayAndOrientation(getConfiguration().uiMode); + updateDisplayAndOrientation(getConfiguration().uiMode, null /* outConfig */); // NOTE: We disable the rotation in the emulator because // it doesn't support hardware OpenGL emulation yet. @@ -1577,7 +1577,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo * changed. * Do not call if {@link WindowManagerService#mDisplayReady} == false. */ - private DisplayInfo updateDisplayAndOrientation(int uiMode) { + private DisplayInfo updateDisplayAndOrientation(int uiMode, Configuration outConfig) { // Use the effective "visual" dimensions based on current rotation final boolean rotated = (mRotation == ROTATION_90 || mRotation == ROTATION_270); final int dw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; @@ -1609,6 +1609,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mDisplayInfo.flags &= ~Display.FLAG_SCALING_DISABLED; } + computeSizeRangesAndScreenLayout(mDisplayInfo, rotated, uiMode, dw, dh, + mDisplayMetrics.density, outConfig); + // We usually set the override info in DisplayManager so that we get consistent display // metrics values when displays are changing and don't send out new values until WM is aware // of them. However, we don't do this for displays that serve as containers for ActivityView @@ -1657,7 +1660,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo * Do not call if mDisplayReady == false. */ void computeScreenConfiguration(Configuration config) { - final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode); + final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode, config); calculateBounds(displayInfo, mTmpBounds); config.windowConfiguration.setBounds(mTmpBounds); @@ -1687,9 +1690,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo final boolean rotated = (displayInfo.rotation == Surface.ROTATION_90 || displayInfo.rotation == Surface.ROTATION_270); - computeSizeRangesAndScreenLayout(displayInfo, rotated, config.uiMode, dw, dh, density, - config); - config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK) | ((displayInfo.flags & Display.FLAG_ROUND) != 0 ? Configuration.SCREENLAYOUT_ROUND_YES @@ -1843,6 +1843,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, uiMode, unrotDh, unrotDw); adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, uiMode, unrotDw, unrotDh); adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, uiMode, unrotDh, unrotDw); + + if (outConfig == null) { + return; + } int sl = Configuration.resetScreenLayout(outConfig.screenLayout); sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode, displayInfo.displayCutout); @@ -3339,7 +3343,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo final SurfaceControl newParent = shouldAttachToDisplay ? mWindowingLayer : computeImeParent(); if (newParent != null) { - mPendingTransaction.reparent(mImeWindowsContainers.mSurfaceControl, newParent); + getPendingTransaction().reparent(mImeWindowsContainers.mSurfaceControl, newParent); scheduleAnimation(); } } @@ -3746,7 +3750,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mPortalWindowHandle.touchableRegion.getBounds(mTmpRect); if (!mTmpBounds.equals(mTmpRect)) { mPortalWindowHandle.touchableRegion.set(mTmpBounds); - mPendingTransaction.setInputWindowInfo(mParentSurfaceControl, mPortalWindowHandle); + getPendingTransaction().setInputWindowInfo( + mParentSurfaceControl, mPortalWindowHandle); } } } @@ -4834,18 +4839,23 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo try { final ScreenRotationAnimation screenRotationAnimation = mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId); + final Transaction transaction = getPendingTransaction(); if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { screenRotationAnimation.getEnterTransformation().getMatrix().getValues(mTmpFloats); - mPendingTransaction.setMatrix(mWindowingLayer, + transaction.setMatrix(mWindowingLayer, mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y], mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]); - mPendingTransaction.setPosition(mWindowingLayer, + transaction.setPosition(mWindowingLayer, mTmpFloats[Matrix.MTRANS_X], mTmpFloats[Matrix.MTRANS_Y]); - mPendingTransaction.setAlpha(mWindowingLayer, + transaction.setAlpha(mWindowingLayer, screenRotationAnimation.getEnterTransformation().getAlpha()); } super.prepareSurfaces(); + + // TODO: Once we totally eliminate global transaction we will pass transaction in here + // rather than merging to global. + SurfaceControl.mergeToGlobalTransaction(transaction); } finally { Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } @@ -5001,7 +5011,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo if (mPortalWindowHandle == null) { mPortalWindowHandle = createPortalWindowHandle(sc.toString()); } - mPendingTransaction.setInputWindowInfo(sc, mPortalWindowHandle) + getPendingTransaction().setInputWindowInfo(sc, mPortalWindowHandle) .reparent(mWindowingLayer, sc).reparent(mOverlayLayer, sc); } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index bb7867ce53ec..38201069ebca 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -138,6 +138,7 @@ class Task extends WindowContainer<AppWindowToken> implements ConfigurationConta setOrientation(SCREEN_ORIENTATION_UNSET); } + @Override DisplayContent getDisplayContent() { return mStack != null ? mStack.getDisplayContent() : null; } diff --git a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java index 17e4b897c9da..ee4e462cb85e 100644 --- a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java +++ b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java @@ -77,7 +77,7 @@ class TaskScreenshotAnimatable implements SurfaceAnimator.Animatable { @Override public SurfaceControl.Transaction getPendingTransaction() { - return mTask.mPendingTransaction; + return mTask.getPendingTransaction(); } @Override diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 757f6a1c2f94..ab5e071f572a 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -93,10 +93,6 @@ public class TaskStack extends WindowContainer<Task> implements /** Unique identifier */ final int mStackId; - /** The display this stack sits under. */ - // TODO: Track parent marks like this in WindowContainer. - private DisplayContent mDisplayContent; - /** For comparison with DisplayContent bounds. */ private Rect mTmpRect = new Rect(); private Rect mTmpRect2 = new Rect(); @@ -177,10 +173,6 @@ public class TaskStack extends WindowContainer<Task> implements EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId); } - DisplayContent getDisplayContent() { - return mDisplayContent; - } - Task findHomeTask() { if (!isActivityTypeHome() || mChildren.isEmpty()) { return null; @@ -825,8 +817,7 @@ public class TaskStack extends WindowContainer<Task> implements throw new IllegalStateException("onDisplayChanged: Already attached"); } - final boolean movedToNewDisplay = mDisplayContent == null; - mDisplayContent = dc; + super.onDisplayChanged(dc); updateSurfaceBounds(); if (mAnimationBackgroundSurface == null) { @@ -834,8 +825,6 @@ public class TaskStack extends WindowContainer<Task> implements .setName("animation background stackId=" + mStackId) .build(); } - - super.onDisplayChanged(dc); } /** diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index d5c3e4f34c26..bbef261d17bb 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -109,14 +109,19 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< // The owner/creator for this container. No controller if null. WindowContainerController mController; + // The display this window container is on. + protected DisplayContent mDisplayContent; + protected SurfaceControl mSurfaceControl; private int mLastLayer = 0; private SurfaceControl mLastRelativeToLayer = null; + // TODO(b/132320879): Remove this from WindowContainers except DisplayContent. + private final Transaction mPendingTransaction; + /** * Applied as part of the animation pass in "prepareSurfaces". */ - protected final Transaction mPendingTransaction; protected final SurfaceAnimator mSurfaceAnimator; protected final WindowManagerService mWmService; @@ -320,12 +325,12 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } if (mSurfaceControl != null) { - mPendingTransaction.remove(mSurfaceControl); + getPendingTransaction().remove(mSurfaceControl); // Merge to parent transaction to ensure the transactions on this WindowContainer are // applied in native even if WindowContainer is removed. if (mParent != null) { - mParent.getPendingTransaction().merge(mPendingTransaction); + mParent.getPendingTransaction().merge(getPendingTransaction()); } mSurfaceControl = null; @@ -508,12 +513,20 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< * @param dc The display this container is on after changes. */ void onDisplayChanged(DisplayContent dc) { + mDisplayContent = dc; + if (dc != null && dc != this) { + dc.getPendingTransaction().merge(mPendingTransaction); + } for (int i = mChildren.size() - 1; i >= 0; --i) { final WindowContainer child = mChildren.get(i); child.onDisplayChanged(dc); } } + DisplayContent getDisplayContent() { + return mDisplayContent; + } + void setWaitingForDrawnIfResizingChanged() { for (int i = mChildren.size() - 1; i >= 0; --i) { final WindowContainer wc = mChildren.get(i); @@ -1180,13 +1193,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } } - /** - * TODO: Once we totally eliminate global transaction we will pass transaction in here - * rather than merging to global. - */ void prepareSurfaces() { - SurfaceControl.mergeToGlobalTransaction(getPendingTransaction()); - // If a leash has been set when the transaction was committed, then the leash reparent has // been committed. mCommittedReparentToAnimationLeash = mSurfaceAnimator.hasLeash(); @@ -1204,8 +1211,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } /** - * Trigger a call to prepareSurfaces from the animation thread, such that - * mPendingTransaction will be applied. + * Trigger a call to prepareSurfaces from the animation thread, such that pending transactions + * will be applied. */ void scheduleAnimation() { if (mParent != null) { @@ -1224,6 +1231,14 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< @Override public Transaction getPendingTransaction() { + final DisplayContent displayContent = getDisplayContent(); + if (displayContent != null && displayContent != this) { + return displayContent.getPendingTransaction(); + } + // This WindowContainer has not attached to a display yet or this is a DisplayContent, so we + // let the caller to save the surface operations within the local mPendingTransaction. + // If this is not a DisplayContent, we will merge it to the pending transaction of its + // display once it attaches to it. return mPendingTransaction; } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index dd3c6004dcad..5ef184adc52f 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1313,6 +1313,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mOrientationChangeTimedOut = true; } + @Override DisplayContent getDisplayContent() { return mToken.getDisplayContent(); } @@ -4602,7 +4603,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP new WindowAnimationSpec(anim, mSurfacePosition, false /* canSkipFirstFrame */, 0 /* windowCornerRadius */), mWmService.mSurfaceAnimationRunner); - startAnimation(mPendingTransaction, adapter); + startAnimation(getPendingTransaction(), adapter); commitPendingTransaction(); } diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index f0b9c62f2843..8aee0f2a8308 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -82,9 +82,6 @@ class WindowToken extends WindowContainer<WindowState> { // windows will be put to the bottom of the list. boolean sendingToBottom; - // The display this token is on. - protected DisplayContent mDisplayContent; - /** The owner has {@link android.Manifest.permission#MANAGE_APP_TOKENS} */ final boolean mOwnerCanManageAppTokens; @@ -249,10 +246,6 @@ class WindowToken extends WindowContainer<WindowState> { return null; } - DisplayContent getDisplayContent() { - return mDisplayContent; - } - @Override void removeImmediately() { if (mDisplayContent != null) { @@ -266,7 +259,6 @@ class WindowToken extends WindowContainer<WindowState> { @Override void onDisplayChanged(DisplayContent dc) { dc.reParentWindowToken(this); - mDisplayContent = dc; // TODO(b/36740756): One day this should perhaps be hooked // up with goodToGo, so we don't move a window diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index c2f699bab9d9..ea5cc211c954 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1051,12 +1051,7 @@ public final class SystemServer { mDisplayManagerService.windowManagerAndInputReady(); traceEnd(); - // Skip Bluetooth if we have an emulator kernel - // TODO: Use a more reliable check to see if this product should - // support Bluetooth - see bug 988521 - if (isEmulator) { - Slog.i(TAG, "No Bluetooth Service (emulator)"); - } else if (mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) { + if (mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) { Slog.i(TAG, "No Bluetooth Service (factory test)"); } else if (!context.getPackageManager().hasSystemFeature (PackageManager.FEATURE_BLUETOOTH)) { diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java index 09e20e04835b..1f5ebe4536d8 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java @@ -235,6 +235,10 @@ public abstract class BaseLockSettingsServiceTests extends AndroidTestCase { mPasswordSlotManager.cleanup(); } + protected void flushHandlerTasks() { + mService.mHandler.runWithScissors(() -> { }, 0 /*now*/); // Flush runnables on handler + } + protected void assertNotEquals(long expected, long actual) { assertTrue(expected != actual); } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java index 10fb3ba938d4..f85e2cc10800 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java @@ -110,7 +110,7 @@ public class LockSettingsServiceTestable extends LockSettingsService { } @Override - public boolean hasBiometrics() { + public boolean hasEnrolledBiometrics() { return false; } @@ -163,5 +163,4 @@ public class LockSettingsServiceTestable extends LockSettingsService { } return storedData; } - } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java index 0273f7651207..1cd590c39f49 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java @@ -232,7 +232,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { reset(mAuthSecretService); mService.onUnlockUser(PRIMARY_USER_ID); - mService.mHandler.runWithScissors(() -> {}, 0 /*now*/); // Flush runnables on handler + flushHandlerTasks(); verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class)); } @@ -242,7 +242,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { reset(mAuthSecretService); mService.onUnlockUser(PRIMARY_USER_ID); - mService.mHandler.runWithScissors(() -> {}, 0 /*now*/); // Flush runnables on handler + flushHandlerTasks(); verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class)); } @@ -254,7 +254,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { reset(mAuthSecretService); mService.onUnlockUser(PRIMARY_USER_ID); - mService.mHandler.runWithScissors(() -> {}, 0 /*now*/); // Flush runnables on handler + flushHandlerTasks(); verify(mAuthSecretService).primaryUserCredential(any(ArrayList.class)); } @@ -357,7 +357,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { handle, token, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID); // Verify DPM gets notified about new device lock - mService.mHandler.runWithScissors(() -> {}, 0 /*now*/); // Flush runnables on handler + flushHandlerTasks(); final PasswordMetrics metric = PasswordMetrics.computeForCredential( LockPatternUtils.CREDENTIAL_TYPE_PATTERN, pattern); verify(mDevicePolicyManager).setActivePasswordState(metric, PRIMARY_USER_ID); @@ -384,6 +384,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { mLocalService.setLockCredentialWithToken(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, handle, token, PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID); + flushHandlerTasks(); // flush the unlockUser() call before changing password again mLocalService.setLockCredentialWithToken(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, handle, token, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID); diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java index faf6ee23e208..0f3050f9e3d3 100644 --- a/services/usage/java/com/android/server/usage/StorageStatsService.java +++ b/services/usage/java/com/android/server/usage/StorageStatsService.java @@ -120,6 +120,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub { @Override public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) { switch (vol.type) { + case VolumeInfo.TYPE_PUBLIC: case VolumeInfo.TYPE_PRIVATE: case VolumeInfo.TYPE_EMULATED: if (newState == VolumeInfo.STATE_MOUNTED) { diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index b5da2eeb4c9c..addd9e0591b0 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -396,6 +396,12 @@ public class SubscriptionManager { public static final int NAME_SOURCE_USER_INPUT = 2; /** + * The name_source is carrier (carrier app, carrier config, etc.) + * @hide + */ + public static final int NAME_SOURCE_CARRIER = 3; + + /** * TelephonyProvider column name for the color of a SIM. * <P>Type: INTEGER (int)</P> */ diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java index 64c1830c5e5c..2552f045eedf 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java +++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java @@ -209,18 +209,9 @@ public final class TelephonyPermissions { context.enforcePermission( android.Manifest.permission.READ_PHONE_STATE, pid, uid, message); } catch (SecurityException phoneStateException) { - SubscriptionManager sm = (SubscriptionManager) context.getSystemService( - Context.TELEPHONY_SUBSCRIPTION_SERVICE); - int[] activeSubIds = sm.getActiveSubscriptionIdList(); - for (int activeSubId : activeSubIds) { - // If we don't have the runtime permission, but do have carrier privileges, that - // suffices for reading phone state. - if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid) - == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { - return true; - } - } - return false; + // If we don't have the runtime permission, but do have carrier privileges, that + // suffices for reading phone state. + return checkCarrierPrivilegeForAnySubId(context, telephonySupplier, uid); } } @@ -236,9 +227,9 @@ public final class TelephonyPermissions { * * <p>This method behaves in one of the following ways: * <ul> - * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission or the - * calling package passes a DevicePolicyManager Device Owner / Profile Owner device - * identifier access check, + * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling + * package passes a DevicePolicyManager Device Owner / Profile Owner device identifier + * access check, or the calling package has carrier privileges. * <li>throw SecurityException: if the caller does not meet any of the requirements and is * targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission. * <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE @@ -258,9 +249,9 @@ public final class TelephonyPermissions { * * <p>This method behaves in one of the following ways: * <ul> - * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission or the - * calling package passes a DevicePolicyManager Device Owner / Profile Owner device - * identifier access check, + * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling + * package passes a DevicePolicyManager Device Owner / Profile Owner device identifier + * access check, or the calling package has carrier privileges. * <li>throw SecurityException: if the caller does not meet any of the requirements and is * targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission * or carrier privileges. @@ -272,23 +263,8 @@ public final class TelephonyPermissions { */ public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context, int subId, String callingPackage, String message) { - int pid = Binder.getCallingPid(); - int uid = Binder.getCallingUid(); - // if the device identifier check completes successfully then grant access. - if (checkReadDeviceIdentifiers(context, pid, uid, callingPackage)) { - return true; - } - // Calling packages with carrier privileges will also have access to device identifiers, but - // this may be removed in a future release. - if (checkCarrierPrivilegeForSubId(subId)) { - return true; - } - // else the calling package is not authorized to access the device identifiers; call - // a central method to report the failure based on the target SDK and if the calling package - // has the READ_PHONE_STATE permission or carrier privileges that were previously required - // to access the identifiers. - return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, callingPackage, - message); + return checkReadDeviceIdentifiers(context, TELEPHONY_SUPPLIER, subId, + Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message); } /** @@ -298,7 +274,7 @@ public final class TelephonyPermissions { * <ul> * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling * package passes a DevicePolicyManager Device Owner / Profile Owner device identifier - * access check, or the calling package has carrier privleges. + * access check, or the calling package has carrier privileges. * <li>throw SecurityException: if the caller does not meet any of the requirements and is * targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission. * <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE @@ -309,19 +285,8 @@ public final class TelephonyPermissions { */ public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId, String callingPackage, String message) { - int pid = Binder.getCallingPid(); - int uid = Binder.getCallingUid(); - // if the device identifiers can be read then grant access to the subscriber identifiers - if (checkReadDeviceIdentifiers(context, pid, uid, callingPackage)) { - return true; - } - // If the calling package has carrier privileges then allow access to the subscriber - // identifiers. - if (checkCarrierPrivilegeForSubId(subId)) { - return true; - } - return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, callingPackage, - message); + return checkReadDeviceIdentifiers(context, TELEPHONY_SUPPLIER, subId, + Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message); } /** @@ -331,8 +296,10 @@ public final class TelephonyPermissions { * package passes a DevicePolicyManager Device Owner / Profile Owner device identifier access * check. */ - private static boolean checkReadDeviceIdentifiers(Context context, int pid, int uid, - String callingPackage) { + @VisibleForTesting + public static boolean checkReadDeviceIdentifiers(Context context, + Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid, + String callingPackage, String message) { // Allow system and root access to the device identifiers. final int appId = UserHandle.getAppId(uid); if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID) { @@ -343,31 +310,36 @@ public final class TelephonyPermissions { uid) == PackageManager.PERMISSION_GRANTED) { return true; } - // if the calling package is null then return now as there's no way to perform the - // DevicePolicyManager device / profile owner and AppOp checks - if (callingPackage == null) { - return false; + // If the calling package has carrier privileges for any subscription then allow access. + if (checkCarrierPrivilegeForAnySubId(context, telephonySupplier, uid)) { + return true; } - // Allow access to an app that has been granted the READ_DEVICE_IDENTIFIERS app op. - long token = Binder.clearCallingIdentity(); - AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService( - Context.APP_OPS_SERVICE); - try { - if (appOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, uid, - callingPackage) == AppOpsManager.MODE_ALLOWED) { + // if the calling package is not null then perform the DevicePolicyManager device / + // profile owner and Appop checks. + if (callingPackage != null) { + // Allow access to an app that has been granted the READ_DEVICE_IDENTIFIERS app op. + long token = Binder.clearCallingIdentity(); + AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService( + Context.APP_OPS_SERVICE); + try { + if (appOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, uid, + callingPackage) == AppOpsManager.MODE_ALLOWED) { + return true; + } + } finally { + Binder.restoreCallingIdentity(token); + } + // Allow access to a device / profile owner app. + DevicePolicyManager devicePolicyManager = + (DevicePolicyManager) context.getSystemService( + Context.DEVICE_POLICY_SERVICE); + if (devicePolicyManager != null && devicePolicyManager.checkDeviceIdentifierAccess( + callingPackage, pid, uid)) { return true; } - } finally { - Binder.restoreCallingIdentity(token); } - // Allow access to a device / profile owner app. - DevicePolicyManager devicePolicyManager = (DevicePolicyManager) context.getSystemService( - Context.DEVICE_POLICY_SERVICE); - if (devicePolicyManager != null && devicePolicyManager.checkDeviceIdentifierAccess( - callingPackage, pid, uid)) { - return true; - } - return false; + return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, callingPackage, + message); } /** @@ -403,10 +375,12 @@ public final class TelephonyPermissions { try { callingPackageInfo = context.getPackageManager().getApplicationInfoAsUser( callingPackage, 0, UserHandle.getUserId(uid)); - if (callingPackageInfo.isSystemApp()) { - isPreinstalled = true; - if (callingPackageInfo.isPrivilegedApp()) { - isPrivApp = true; + if (callingPackageInfo != null) { + if (callingPackageInfo.isSystemApp()) { + isPreinstalled = true; + if (callingPackageInfo.isPrivilegedApp()) { + isPrivApp = true; + } } } } catch (PackageManager.NameNotFoundException e) { @@ -651,6 +625,26 @@ public final class TelephonyPermissions { } } + /** + * Returns whether the provided uid has carrier privileges for any active subscription ID. + */ + private static boolean checkCarrierPrivilegeForAnySubId(Context context, + Supplier<ITelephony> telephonySupplier, int uid) { + SubscriptionManager sm = (SubscriptionManager) context.getSystemService( + Context.TELEPHONY_SUBSCRIPTION_SERVICE); + int[] activeSubIds = sm.getActiveSubscriptionIdList(); + if (activeSubIds != null) { + for (int activeSubId : activeSubIds) { + if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid) + == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { + return true; + } + } + } + return false; + } + + private static int getCarrierPrivilegeStatus( Supplier<ITelephony> telephonySupplier, int subId, int uid) { ITelephony telephony = telephonySupplier.get(); diff --git a/tests/net/common/Android.bp b/tests/net/common/Android.bp index 07525a6ea49c..db1ccb446ce3 100644 --- a/tests/net/common/Android.bp +++ b/tests/net/common/Android.bp @@ -24,6 +24,7 @@ java_library { "frameworks-net-testutils", "junit", "mockito-target-minus-junit4", + "platform-test-annotations", ], libs: [ "android.test.base.stubs", diff --git a/tests/net/common/java/android/net/NetworkTest.java b/tests/net/common/java/android/net/NetworkTest.java index bef66b27df62..38bc744a0a06 100644 --- a/tests/net/common/java/android/net/NetworkTest.java +++ b/tests/net/common/java/android/net/NetworkTest.java @@ -25,6 +25,7 @@ import android.net.LocalServerSocket; import android.net.LocalSocket; import android.net.LocalSocketAddress; import android.net.Network; +import android.platform.test.annotations.AppModeFull; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -74,6 +75,7 @@ public class NetworkTest { } @Test + @AppModeFull(reason = "Socket cannot bind in instant app mode") public void testBindSocketOfConnectedDatagramSocketThrows() throws Exception { final DatagramSocket mDgramSocket = new DatagramSocket(0, (InetAddress) Inet6Address.ANY); mDgramSocket.connect((InetAddress) Inet6Address.LOOPBACK, 53); |