Merge "Remove unused windowAttributes"
diff --git a/core/api/current.txt b/core/api/current.txt
index 7c92793..9e3e955 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -7335,6 +7335,7 @@
public final class UiAutomation {
method public void adoptShellPermissionIdentity();
method public void adoptShellPermissionIdentity(@Nullable java.lang.String...);
+ method public boolean clearCache();
method @Deprecated public void clearWindowAnimationFrameStats();
method public boolean clearWindowContentFrameStats(int);
method public void dropShellPermissionIdentity();
@@ -28818,24 +28819,15 @@
public final class NfcAdapter {
method public void disableForegroundDispatch(android.app.Activity);
- method @Deprecated public void disableForegroundNdefPush(android.app.Activity);
method public void disableReaderMode(android.app.Activity);
method public void enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]);
- method @Deprecated public void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage);
method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle);
method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context);
method @Nullable public android.nfc.NfcAntennaInfo getNfcAntennaInfo();
method public boolean ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler);
- method @Deprecated public boolean invokeBeam(android.app.Activity);
method public boolean isEnabled();
- method @Deprecated public boolean isNdefPushEnabled();
method public boolean isSecureNfcEnabled();
method public boolean isSecureNfcSupported();
- method @Deprecated public void setBeamPushUris(android.net.Uri[], android.app.Activity);
- method @Deprecated public void setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity);
- method @Deprecated public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...);
- method @Deprecated public void setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...);
- method @Deprecated public void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...);
field public static final String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED";
field public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
field @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static final String ACTION_PREFERRED_PAYMENT_CHANGED = "android.nfc.action.PREFERRED_PAYMENT_CHANGED";
@@ -33312,6 +33304,7 @@
field public static final int LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF = 1; // 0x1
field public static final int LOCATION_MODE_NO_CHANGE = 0; // 0x0
field public static final int LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF = 4; // 0x4
+ field public static final int LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST = 2; // 0x2
field public static final int LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION = 1; // 0x1
field public static final String LOW_POWER_STANDBY_FEATURE_WAKE_ON_LAN = "com.android.lowpowerstandby.WAKE_ON_LAN";
field public static final int ON_AFTER_RELEASE = 536870912; // 0x20000000
@@ -53956,6 +53949,7 @@
method public java.util.List<java.lang.String> getAvailableExtraData();
method @Deprecated public void getBoundsInParent(android.graphics.Rect);
method public void getBoundsInScreen(android.graphics.Rect);
+ method public void getBoundsInWindow(@NonNull android.graphics.Rect);
method public android.view.accessibility.AccessibilityNodeInfo getChild(int);
method @Nullable public android.view.accessibility.AccessibilityNodeInfo getChild(int, int);
method public int getChildCount();
@@ -54034,6 +54028,7 @@
method public void setAvailableExtraData(java.util.List<java.lang.String>);
method @Deprecated public void setBoundsInParent(android.graphics.Rect);
method public void setBoundsInScreen(android.graphics.Rect);
+ method public void setBoundsInWindow(@NonNull android.graphics.Rect);
method public void setCanOpenPopup(boolean);
method public void setCheckable(boolean);
method public void setChecked(boolean);
diff --git a/core/api/removed.txt b/core/api/removed.txt
index 1fa1e89..8b3696a 100644
--- a/core/api/removed.txt
+++ b/core/api/removed.txt
@@ -252,6 +252,22 @@
}
+package android.nfc {
+
+ public final class NfcAdapter {
+ method @Deprecated public void disableForegroundNdefPush(android.app.Activity);
+ method @Deprecated public void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage);
+ method @Deprecated public boolean invokeBeam(android.app.Activity);
+ method @Deprecated public boolean isNdefPushEnabled();
+ method @Deprecated public void setBeamPushUris(android.net.Uri[], android.app.Activity);
+ method @Deprecated public void setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity);
+ method @Deprecated public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...);
+ method @Deprecated public void setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...);
+ method @Deprecated public void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...);
+ }
+
+}
+
package android.os {
public class BatteryManager {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index fde95bd..dc7e28c 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -626,6 +626,7 @@
field public static final String OPSTR_RUN_ANY_IN_BACKGROUND = "android:run_any_in_background";
field public static final String OPSTR_RUN_IN_BACKGROUND = "android:run_in_background";
field public static final String OPSTR_START_FOREGROUND = "android:start_foreground";
+ field public static final String OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION = "android:system_exempt_from_hibernation";
field public static final String OPSTR_TAKE_AUDIO_FOCUS = "android:take_audio_focus";
field public static final String OPSTR_TAKE_MEDIA_BUTTONS = "android:take_media_buttons";
field public static final String OPSTR_TOAST_WINDOW = "android:toast_window";
@@ -10114,9 +10115,7 @@
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean addNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler, String[]);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disable();
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disable(boolean);
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disableNdefPush();
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enable();
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableNdefPush();
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableSecureNfc(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public java.util.Map<java.lang.String,java.lang.Boolean> getTagIntentAppPreferenceForUser(int);
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOn();
@@ -10125,10 +10124,8 @@
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void registerControllerAlwaysOnListener(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean removeNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler);
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean setControllerAlwaysOn(boolean);
- method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, int);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int setTagIntentAppPreferenceForUser(int, @NonNull String, boolean);
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void unregisterControllerAlwaysOnListener(@NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener);
- field public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 1; // 0x1
field public static final int TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND = -1; // 0xffffffff
field public static final int TAG_INTENT_APP_PREF_RESULT_SUCCESS = 0; // 0x0
field public static final int TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE = -2; // 0xfffffffe
diff --git a/core/api/system-removed.txt b/core/api/system-removed.txt
index 2c5acf1..1c10356 100644
--- a/core/api/system-removed.txt
+++ b/core/api/system-removed.txt
@@ -140,6 +140,17 @@
}
+package android.nfc {
+
+ public final class NfcAdapter {
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disableNdefPush();
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableNdefPush();
+ method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, int);
+ field public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 1; // 0x1
+ }
+
+}
+
package android.os {
public class Build {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 1abdbb9..c25f875 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -448,6 +448,7 @@
method @Deprecated public boolean grantRuntimePermission(String, String, android.os.UserHandle);
method public boolean injectInputEvent(@NonNull android.view.InputEvent, boolean, boolean);
method public void injectInputEventToInputFilter(@NonNull android.view.InputEvent);
+ method public boolean isNodeInCache(@NonNull android.view.accessibility.AccessibilityNodeInfo);
method @Deprecated public boolean revokeRuntimePermission(String, String, android.os.UserHandle);
method public void syncInputTransactions();
method public void syncInputTransactions(boolean);
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 8263a4e3..8a671be 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1462,9 +1462,17 @@
*/
public static final int OP_USE_FULL_SCREEN_INTENT = AppProtoEnums.APP_OP_USE_FULL_SCREEN_INTENT;
+ /**
+ * Prevent an app from being placed into hibernation.
+ *
+ * @hide
+ */
+ public static final int OP_SYSTEM_EXEMPT_FROM_HIBERNATION =
+ AppProtoEnums.APP_OP_SYSTEM_EXEMPT_FROM_HIBERNATION;
+
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int _NUM_OP = 134;
+ public static final int _NUM_OP = 135;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -2058,6 +2066,15 @@
*/
public static final String OPSTR_USE_FULL_SCREEN_INTENT = "android:use_full_screen_intent";
+ /**
+ * Prevent an app from being placed into hibernation.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION =
+ "android:system_exempt_from_hibernation";
+
/** {@link #sAppOpsToNote} not initialized yet for this op */
private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
/** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -2580,7 +2597,10 @@
.setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
new AppOpInfo.Builder(OP_USE_FULL_SCREEN_INTENT, OPSTR_USE_FULL_SCREEN_INTENT,
"USE_FULL_SCREEN_INTENT").setPermission(Manifest.permission.USE_FULL_SCREEN_INTENT)
- .build()
+ .build(),
+ new AppOpInfo.Builder(OP_SYSTEM_EXEMPT_FROM_HIBERNATION,
+ OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION,
+ "SYSTEM_EXEMPT_FROM_HIBERNATION").build()
};
// The number of longs needed to form a full bitmask of app ops
diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java
index e93ce6b..c628ec4 100644
--- a/core/java/android/app/ApplicationExitInfo.java
+++ b/core/java/android/app/ApplicationExitInfo.java
@@ -734,7 +734,22 @@
* guarantees that the format is stable across devices or Android releases.</p>
*/
public @Nullable String getDescription() {
- return mDescription;
+ final StringBuilder sb = new StringBuilder();
+
+ if (mSubReason != SUBREASON_UNKNOWN) {
+ sb.append("[");
+ sb.append(subreasonToString(mSubReason));
+ sb.append("]");
+ }
+
+ if (!TextUtils.isEmpty(mDescription)) {
+ if (sb.length() > 0) {
+ sb.append(" ");
+ }
+ sb.append(mDescription);
+ }
+
+ return sb.toString();
}
/**
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 249937a..b3b1cf8 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -17,6 +17,7 @@
package android.app;
import android.accessibilityservice.AccessibilityGestureEvent;
+import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityService.Callbacks;
import android.accessibilityservice.AccessibilityService.IAccessibilityServiceClientWrapper;
import android.accessibilityservice.AccessibilityServiceInfo;
@@ -58,6 +59,7 @@
import android.view.Window;
import android.view.WindowAnimationFrameStats;
import android.view.WindowContentFrameStats;
+import android.view.accessibility.AccessibilityCache;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityInteractionClient;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -465,6 +467,48 @@
}
/**
+ * Clears the accessibility cache.
+ *
+ * @return {@code true} if the cache was cleared
+ * @see AccessibilityService#clearCache()
+ */
+ public boolean clearCache() {
+ final int connectionId;
+ synchronized (mLock) {
+ throwIfNotConnectedLocked();
+ connectionId = mConnectionId;
+ }
+ final AccessibilityCache cache = AccessibilityInteractionClient.getCache(connectionId);
+ if (cache == null) {
+ return false;
+ }
+ cache.clear();
+ return true;
+ }
+
+ /**
+ * Checks if {@code node} is in the accessibility cache.
+ *
+ * @param node the node to check.
+ * @return {@code true} if {@code node} is in the cache.
+ * @hide
+ * @see AccessibilityService#isNodeInCache(AccessibilityNodeInfo)
+ */
+ @TestApi
+ public boolean isNodeInCache(@NonNull AccessibilityNodeInfo node) {
+ final int connectionId;
+ synchronized (mLock) {
+ throwIfNotConnectedLocked();
+ connectionId = mConnectionId;
+ }
+ final AccessibilityCache cache = AccessibilityInteractionClient.getCache(connectionId);
+ if (cache == null) {
+ return false;
+ }
+ return cache.isNodeInCache(node);
+ }
+
+ /**
* Adopt the permission identity of the shell UID for all permissions. This allows
* you to call APIs protected permissions which normal apps cannot hold but are
* granted to the shell UID. If you already adopted all shell permissions by calling
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index e7f6990..90e0318 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -4020,26 +4020,26 @@
return MTE_NOT_CONTROLLED_BY_POLICY;
}
- // TODO: Expose this as SystemAPI once we add the query API
+ // TODO: Expose this as a public API
/**
* @hide
*/
public static final String AUTO_TIMEZONE_POLICY = "autoTimezone";
- // TODO: Expose this as SystemAPI once we add the query API
+ // TODO: Expose this as a public API
/**
* @hide
*/
public static final String PERMISSION_GRANT_POLICY = "permissionGrant";
- // TODO: Expose this as SystemAPI once we add the query API
+ // TODO: Expose this as a public API
/**
* @hide
*/
public static final String LOCK_TASK_POLICY = "lockTask";
- // TODO: Expose this as SystemAPI once we add the query API
+ // TODO: Expose this as a public API
/**
* @hide
*/
@@ -4047,25 +4047,31 @@
"userControlDisabledPackages";
- // TODO: Expose this as SystemAPI once we add the query API
+ // TODO: Expose this as a public API
/**
* @hide
*/
public static final String PERSISTENT_PREFERRED_ACTIVITY_POLICY =
"persistentPreferredActivity";
- // TODO: Expose this as SystemAPI once we add the query API
+ // TODO: Expose this as a public API
/**
* @hide
*/
public static final String PACKAGE_UNINSTALL_BLOCKED_POLICY = "packageUninstallBlocked";
- // TODO: Expose this as SystemAPI once we add the query API
+ // TODO: Expose this as a public API
/**
* @hide
*/
public static final String APPLICATION_RESTRICTIONS_POLICY = "applicationRestrictions";
+ // TODO: Expose this as a public API
+ /**
+ * @hide
+ */
+ public static final String RESET_PASSWORD_TOKEN_POLICY = "resetPasswordToken";
+
/**
* This object is a single place to tack on invalidation and disable calls. All
* binder caches in this class derive from this Config, so all can be invalidated or
diff --git a/core/java/android/app/admin/LongPolicyValue.java b/core/java/android/app/admin/LongPolicyValue.java
new file mode 100644
index 0000000..b149b8a
--- /dev/null
+++ b/core/java/android/app/admin/LongPolicyValue.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.admin;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+
+import java.util.Objects;
+
+/**
+ * @hide
+ */
+public final class LongPolicyValue extends PolicyValue<Long> {
+
+ public LongPolicyValue(long value) {
+ super(value);
+ }
+
+ private LongPolicyValue(Parcel source) {
+ this(source.readLong());
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ LongPolicyValue other = (LongPolicyValue) o;
+ return Objects.equals(getValue(), other.getValue());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getValue());
+ }
+
+ @Override
+ public String toString() {
+ return "LongPolicyValue { mValue= " + getValue() + " }";
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeLong(getValue());
+ }
+
+ @NonNull
+ public static final Creator<LongPolicyValue> CREATOR =
+ new Creator<LongPolicyValue>() {
+ @Override
+ public LongPolicyValue createFromParcel(Parcel source) {
+ return new LongPolicyValue(source);
+ }
+
+ @Override
+ public LongPolicyValue[] newArray(int size) {
+ return new LongPolicyValue[size];
+ }
+ };
+}
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index 3e6b380..29e2231 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -630,9 +630,6 @@
@NonNull VirtualDisplayConfig config,
@Nullable @CallbackExecutor Executor executor,
@Nullable VirtualDisplay.Callback callback) {
- // TODO(b/205343547): Handle display groups properly instead of creating a new display
- // group for every new virtual display created using this API.
- // belongs to the same display group.
IVirtualDisplayCallback callbackWrapper =
new DisplayManagerGlobal.VirtualDisplayCallback(callback, executor);
final int displayId;
diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java
index 49d21da..90ed4ce 100644
--- a/core/java/android/content/pm/ServiceInfo.java
+++ b/core/java/android/content/pm/ServiceInfo.java
@@ -246,8 +246,17 @@
/**
* Constant corresponding to {@code mediaProjection} in
- * the {@link android.R.attr#foregroundServiceType} attribute.
- * Managing a media projection session, e.g for screen recording or taking screenshots.
+ * the {@link android.R.attr#foregroundServiceType foregroundServiceType} attribute.
+ *
+ * <p>
+ * To capture through {@link android.media.projection.MediaProjection}, an app must start a
+ * foreground service with the type corresponding to this constant. This type should only be
+ * used for {@link android.media.projection.MediaProjection}. Capturing screen contents via
+ * {@link android.media.projection.MediaProjection#createVirtualDisplay(String, int, int, int,
+ * int, android.view.Surface, android.hardware.display.VirtualDisplay.Callback,
+ * android.os.Handler) createVirtualDisplay} conveniently allows recording, presenting screen
+ * contents into a meeting, taking screenshots, or several other scenarios.
+ * </p>
*
* <p>Starting foreground service with this type from apps targeting API level
* {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and later, will require permission
diff --git a/core/java/android/nfc/BeamShareData.aidl b/core/java/android/nfc/BeamShareData.aidl
deleted file mode 100644
index a47e240..0000000
--- a/core/java/android/nfc/BeamShareData.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-parcelable BeamShareData;
diff --git a/core/java/android/nfc/BeamShareData.java b/core/java/android/nfc/BeamShareData.java
deleted file mode 100644
index 6a40f98..0000000
--- a/core/java/android/nfc/BeamShareData.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package android.nfc;
-
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.UserHandle;
-
-/**
- * Class to IPC data to be shared over Android Beam.
- * Allows bundling NdefMessage, Uris and flags in a single
- * IPC call. This is important as we want to reduce the
- * amount of IPC calls at "touch time".
- * @hide
- */
-public final class BeamShareData implements Parcelable {
- public final NdefMessage ndefMessage;
- public final Uri[] uris;
- public final UserHandle userHandle;
- public final int flags;
-
- public BeamShareData(NdefMessage msg, Uri[] uris, UserHandle userHandle, int flags) {
- this.ndefMessage = msg;
- this.uris = uris;
- this.userHandle = userHandle;
- this.flags = flags;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- int urisLength = (uris != null) ? uris.length : 0;
- dest.writeParcelable(ndefMessage, 0);
- dest.writeInt(urisLength);
- if (urisLength > 0) {
- dest.writeTypedArray(uris, 0);
- }
- dest.writeParcelable(userHandle, 0);
- dest.writeInt(this.flags);
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<BeamShareData> CREATOR =
- new Parcelable.Creator<BeamShareData>() {
- @Override
- public BeamShareData createFromParcel(Parcel source) {
- Uri[] uris = null;
- NdefMessage msg = source.readParcelable(NdefMessage.class.getClassLoader(), android.nfc.NdefMessage.class);
- int numUris = source.readInt();
- if (numUris > 0) {
- uris = new Uri[numUris];
- source.readTypedArray(uris, Uri.CREATOR);
- }
- UserHandle userHandle = source.readParcelable(UserHandle.class.getClassLoader(), android.os.UserHandle.class);
- int flags = source.readInt();
-
- return new BeamShareData(msg, uris, userHandle, flags);
- }
-
- @Override
- public BeamShareData[] newArray(int size) {
- return new BeamShareData[size];
- }
- };
-}
diff --git a/core/java/android/nfc/IAppCallback.aidl b/core/java/android/nfc/IAppCallback.aidl
index 133146d..b06bf06 100644
--- a/core/java/android/nfc/IAppCallback.aidl
+++ b/core/java/android/nfc/IAppCallback.aidl
@@ -16,7 +16,6 @@
package android.nfc;
-import android.nfc.BeamShareData;
import android.nfc.Tag;
/**
@@ -24,7 +23,5 @@
*/
interface IAppCallback
{
- BeamShareData createBeamShareData(byte peerLlcpVersion);
- oneway void onNdefPushComplete(byte peerLlcpVersion);
oneway void onTagDiscovered(in Tag tag);
}
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index 8a30ef4..a6d8caf 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -18,7 +18,6 @@
import android.app.PendingIntent;
import android.content.IntentFilter;
-import android.nfc.BeamShareData;
import android.nfc.NdefMessage;
import android.nfc.Tag;
import android.nfc.TechListParcel;
@@ -47,24 +46,18 @@
int getState();
boolean disable(boolean saveState);
boolean enable();
- boolean enableNdefPush();
- boolean disableNdefPush();
- boolean isNdefPushEnabled();
void pausePolling(int timeoutInMs);
void resumePolling();
void setForegroundDispatch(in PendingIntent intent,
in IntentFilter[] filters, in TechListParcel techLists);
void setAppCallback(in IAppCallback callback);
- oneway void invokeBeam();
- oneway void invokeBeamInternal(in BeamShareData shareData);
boolean ignore(int nativeHandle, int debounceMs, ITagRemovedCallback callback);
void dispatch(in Tag tag);
void setReaderMode (IBinder b, IAppCallback callback, int flags, in Bundle extras);
- void setP2pModes(int initatorModes, int targetModes);
void addNfcUnlockHandler(INfcUnlockHandler unlockHandler, in int[] techList);
void removeNfcUnlockHandler(INfcUnlockHandler unlockHandler);
diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java
index 911aaf3..8d75cac 100644
--- a/core/java/android/nfc/NfcActivityManager.java
+++ b/core/java/android/nfc/NfcActivityManager.java
@@ -19,9 +19,6 @@
import android.app.Activity;
import android.app.Application;
import android.compat.annotation.UnsupportedAppUsage;
-import android.content.ContentProvider;
-import android.content.Intent;
-import android.net.Uri;
import android.nfc.NfcAdapter.ReaderCallback;
import android.os.Binder;
import android.os.Bundle;
@@ -110,14 +107,8 @@
class NfcActivityState {
boolean resumed = false;
Activity activity;
- NdefMessage ndefMessage = null; // static NDEF message
- NfcAdapter.CreateNdefMessageCallback ndefMessageCallback = null;
- NfcAdapter.OnNdefPushCompleteCallback onNdefPushCompleteCallback = null;
- NfcAdapter.CreateBeamUrisCallback uriCallback = null;
- Uri[] uris = null;
- int flags = 0;
- int readerModeFlags = 0;
NfcAdapter.ReaderCallback readerCallback = null;
+ int readerModeFlags = 0;
Bundle readerModeExtras = null;
Binder token;
@@ -137,24 +128,16 @@
unregisterApplication(activity.getApplication());
resumed = false;
activity = null;
- ndefMessage = null;
- ndefMessageCallback = null;
- onNdefPushCompleteCallback = null;
- uriCallback = null;
- uris = null;
+ readerCallback = null;
readerModeFlags = 0;
+ readerModeExtras = null;
token = null;
}
@Override
public String toString() {
- StringBuilder s = new StringBuilder("[").append(" ");
- s.append(ndefMessage).append(" ").append(ndefMessageCallback).append(" ");
- s.append(uriCallback).append(" ");
- if (uris != null) {
- for (Uri uri : uris) {
- s.append(onNdefPushCompleteCallback).append(" ").append(uri).append("]");
- }
- }
+ StringBuilder s = new StringBuilder("[");
+ s.append(readerCallback);
+ s.append("]");
return s.toString();
}
}
@@ -245,92 +228,6 @@
}
}
- public void setNdefPushContentUri(Activity activity, Uri[] uris) {
- boolean isResumed;
- synchronized (NfcActivityManager.this) {
- NfcActivityState state = getActivityState(activity);
- state.uris = uris;
- isResumed = state.resumed;
- }
- if (isResumed) {
- // requestNfcServiceCallback() verifies permission also
- requestNfcServiceCallback();
- } else {
- // Crash API calls early in case NFC permission is missing
- verifyNfcPermission();
- }
- }
-
-
- public void setNdefPushContentUriCallback(Activity activity,
- NfcAdapter.CreateBeamUrisCallback callback) {
- boolean isResumed;
- synchronized (NfcActivityManager.this) {
- NfcActivityState state = getActivityState(activity);
- state.uriCallback = callback;
- isResumed = state.resumed;
- }
- if (isResumed) {
- // requestNfcServiceCallback() verifies permission also
- requestNfcServiceCallback();
- } else {
- // Crash API calls early in case NFC permission is missing
- verifyNfcPermission();
- }
- }
-
- public void setNdefPushMessage(Activity activity, NdefMessage message, int flags) {
- boolean isResumed;
- synchronized (NfcActivityManager.this) {
- NfcActivityState state = getActivityState(activity);
- state.ndefMessage = message;
- state.flags = flags;
- isResumed = state.resumed;
- }
- if (isResumed) {
- // requestNfcServiceCallback() verifies permission also
- requestNfcServiceCallback();
- } else {
- // Crash API calls early in case NFC permission is missing
- verifyNfcPermission();
- }
- }
-
- public void setNdefPushMessageCallback(Activity activity,
- NfcAdapter.CreateNdefMessageCallback callback, int flags) {
- boolean isResumed;
- synchronized (NfcActivityManager.this) {
- NfcActivityState state = getActivityState(activity);
- state.ndefMessageCallback = callback;
- state.flags = flags;
- isResumed = state.resumed;
- }
- if (isResumed) {
- // requestNfcServiceCallback() verifies permission also
- requestNfcServiceCallback();
- } else {
- // Crash API calls early in case NFC permission is missing
- verifyNfcPermission();
- }
- }
-
- public void setOnNdefPushCompleteCallback(Activity activity,
- NfcAdapter.OnNdefPushCompleteCallback callback) {
- boolean isResumed;
- synchronized (NfcActivityManager.this) {
- NfcActivityState state = getActivityState(activity);
- state.onNdefPushCompleteCallback = callback;
- isResumed = state.resumed;
- }
- if (isResumed) {
- // requestNfcServiceCallback() verifies permission also
- requestNfcServiceCallback();
- } else {
- // Crash API calls early in case NFC permission is missing
- verifyNfcPermission();
- }
- }
-
/**
* Request or unrequest NFC service callbacks.
* Makes IPC call - do not hold lock.
@@ -351,86 +248,6 @@
}
}
- /** Callback from NFC service, usually on binder thread */
- @Override
- public BeamShareData createBeamShareData(byte peerLlcpVersion) {
- NfcAdapter.CreateNdefMessageCallback ndefCallback;
- NfcAdapter.CreateBeamUrisCallback urisCallback;
- NdefMessage message;
- Activity activity;
- Uri[] uris;
- int flags;
- NfcEvent event = new NfcEvent(mAdapter, peerLlcpVersion);
- synchronized (NfcActivityManager.this) {
- NfcActivityState state = findResumedActivityState();
- if (state == null) return null;
-
- ndefCallback = state.ndefMessageCallback;
- urisCallback = state.uriCallback;
- message = state.ndefMessage;
- uris = state.uris;
- flags = state.flags;
- activity = state.activity;
- }
- final long ident = Binder.clearCallingIdentity();
- try {
- // Make callbacks without lock
- if (ndefCallback != null) {
- message = ndefCallback.createNdefMessage(event);
- }
- if (urisCallback != null) {
- uris = urisCallback.createBeamUris(event);
- if (uris != null) {
- ArrayList<Uri> validUris = new ArrayList<Uri>();
- for (Uri uri : uris) {
- if (uri == null) {
- Log.e(TAG, "Uri not allowed to be null.");
- continue;
- }
- String scheme = uri.getScheme();
- if (scheme == null || (!scheme.equalsIgnoreCase("file") &&
- !scheme.equalsIgnoreCase("content"))) {
- Log.e(TAG, "Uri needs to have " +
- "either scheme file or scheme content");
- continue;
- }
- uri = ContentProvider.maybeAddUserId(uri, activity.getUserId());
- validUris.add(uri);
- }
-
- uris = validUris.toArray(new Uri[validUris.size()]);
- }
- }
- if (uris != null && uris.length > 0) {
- for (Uri uri : uris) {
- // Grant the NFC process permission to read these URIs
- activity.grantUriPermission("com.android.nfc", uri,
- Intent.FLAG_GRANT_READ_URI_PERMISSION);
- }
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- return new BeamShareData(message, uris, activity.getUser(), flags);
- }
-
- /** Callback from NFC service, usually on binder thread */
- @Override
- public void onNdefPushComplete(byte peerLlcpVersion) {
- NfcAdapter.OnNdefPushCompleteCallback callback;
- synchronized (NfcActivityManager.this) {
- NfcActivityState state = findResumedActivityState();
- if (state == null) return;
-
- callback = state.onNdefPushCompleteCallback;
- }
- NfcEvent event = new NfcEvent(mAdapter, peerLlcpVersion);
- // Make callback without lock
- if (callback != null) {
- callback.onNdefPushComplete(event);
- }
- }
-
@Override
public void onTagDiscovered(Tag tag) throws RemoteException {
NfcAdapter.ReaderCallback callback;
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 1bb44af..4a244c0 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -343,8 +343,12 @@
*/
public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
- /** @hide */
+ /**
+ * @hide
+ * @removed
+ */
@SystemApi
+ @UnsupportedAppUsage
public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 0x1;
/** @hide */
@@ -418,7 +422,6 @@
// Guarded by NfcAdapter.class
static boolean sIsInitialized = false;
static boolean sHasNfcFeature;
- static boolean sHasBeamFeature;
// Final after first constructor, except for
// attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
@@ -483,7 +486,7 @@
* A callback to be invoked when the system successfully delivers your {@link NdefMessage}
* to another device.
* @see #setOnNdefPushCompleteCallback
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @deprecated this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -509,7 +512,7 @@
* content currently visible to the user. Alternatively, you can call {@link
* #setNdefPushMessage setNdefPushMessage()} if the {@link NdefMessage} always contains the
* same data.
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @deprecated this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -539,7 +542,7 @@
/**
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @deprecated this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -615,7 +618,6 @@
PackageManager pm;
pm = context.getPackageManager();
sHasNfcFeature = pm.hasSystemFeature(PackageManager.FEATURE_NFC);
- sHasBeamFeature = pm.hasSystemFeature(PackageManager.FEATURE_NFC_BEAM);
boolean hasHceFeature =
pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)
|| pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF);
@@ -1111,35 +1113,17 @@
* @param uris an array of Uri(s) to push over Android Beam
* @param activity activity for which the Uri(s) will be pushed
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @removed this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
+ @UnsupportedAppUsage
public void setBeamPushUris(Uri[] uris, Activity activity) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
- if (!sHasBeamFeature) {
- return;
- }
}
- if (activity == null) {
- throw new NullPointerException("activity cannot be null");
- }
- if (uris != null) {
- for (Uri uri : uris) {
- if (uri == null) throw new NullPointerException("Uri not " +
- "allowed to be null");
- String scheme = uri.getScheme();
- if (scheme == null || (!scheme.equalsIgnoreCase("file") &&
- !scheme.equalsIgnoreCase("content"))) {
- throw new IllegalArgumentException("URI needs to have " +
- "either scheme file or scheme content");
- }
- }
- }
- mNfcActivityManager.setNdefPushContentUri(activity, uris);
}
/**
@@ -1199,23 +1183,17 @@
* @param callback callback, or null to disable
* @param activity activity for which the Uri(s) will be pushed
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @removed this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
+ @UnsupportedAppUsage
public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
- if (!sHasBeamFeature) {
- return;
- }
}
- if (activity == null) {
- throw new NullPointerException("activity cannot be null");
- }
- mNfcActivityManager.setNdefPushContentUriCallback(activity, callback);
}
/**
@@ -1289,58 +1267,32 @@
* to only register one at a time, and to do so in that activity's
* {@link Activity#onCreate}
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @removed this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
+ @UnsupportedAppUsage
public void setNdefPushMessage(NdefMessage message, Activity activity,
Activity ... activities) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
- if (!sHasBeamFeature) {
- return;
- }
- }
- int targetSdkVersion = getSdkVersion();
- try {
- if (activity == null) {
- throw new NullPointerException("activity cannot be null");
- }
- mNfcActivityManager.setNdefPushMessage(activity, message, 0);
- for (Activity a : activities) {
- if (a == null) {
- throw new NullPointerException("activities cannot contain null");
- }
- mNfcActivityManager.setNdefPushMessage(a, message, 0);
- }
- } catch (IllegalStateException e) {
- if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) {
- // Less strict on old applications - just log the error
- Log.e(TAG, "Cannot call API with Activity that has already " +
- "been destroyed", e);
- } else {
- // Prevent new applications from making this mistake, re-throw
- throw(e);
- }
}
}
/**
* @hide
+ * @removed
*/
@SystemApi
+ @UnsupportedAppUsage
public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
}
- if (activity == null) {
- throw new NullPointerException("activity cannot be null");
- }
- mNfcActivityManager.setNdefPushMessage(activity, message, flags);
}
/**
@@ -1408,54 +1360,18 @@
* to only register one at a time, and to do so in that activity's
* {@link Activity#onCreate}
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @removed this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
+ @UnsupportedAppUsage
public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
Activity ... activities) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
- if (!sHasBeamFeature) {
- return;
- }
}
- int targetSdkVersion = getSdkVersion();
- try {
- if (activity == null) {
- throw new NullPointerException("activity cannot be null");
- }
- mNfcActivityManager.setNdefPushMessageCallback(activity, callback, 0);
- for (Activity a : activities) {
- if (a == null) {
- throw new NullPointerException("activities cannot contain null");
- }
- mNfcActivityManager.setNdefPushMessageCallback(a, callback, 0);
- }
- } catch (IllegalStateException e) {
- if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) {
- // Less strict on old applications - just log the error
- Log.e(TAG, "Cannot call API with Activity that has already " +
- "been destroyed", e);
- } else {
- // Prevent new applications from making this mistake, re-throw
- throw(e);
- }
- }
- }
-
- /**
- * @hide
- */
- @UnsupportedAppUsage
- public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
- int flags) {
- if (activity == null) {
- throw new NullPointerException("activity cannot be null");
- }
- mNfcActivityManager.setNdefPushMessageCallback(activity, callback, flags);
}
/**
@@ -1495,41 +1411,17 @@
* to only register one at a time, and to do so in that activity's
* {@link Activity#onCreate}
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @removed this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
+ @UnsupportedAppUsage
public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback,
Activity activity, Activity ... activities) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
- if (!sHasBeamFeature) {
- return;
- }
- }
- int targetSdkVersion = getSdkVersion();
- try {
- if (activity == null) {
- throw new NullPointerException("activity cannot be null");
- }
- mNfcActivityManager.setOnNdefPushCompleteCallback(activity, callback);
- for (Activity a : activities) {
- if (a == null) {
- throw new NullPointerException("activities cannot contain null");
- }
- mNfcActivityManager.setOnNdefPushCompleteCallback(a, callback);
- }
- } catch (IllegalStateException e) {
- if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) {
- // Less strict on old applications - just log the error
- Log.e(TAG, "Cannot call API with Activity that has already " +
- "been destroyed", e);
- } else {
- // Prevent new applications from making this mistake, re-throw
- throw(e);
- }
}
}
@@ -1712,46 +1604,18 @@
* @param activity the current foreground Activity that has registered data to share
* @return whether the Beam animation was successfully invoked
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @removed this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
+ @UnsupportedAppUsage
public boolean invokeBeam(Activity activity) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
- if (!sHasBeamFeature) {
- return false;
- }
}
- if (activity == null) {
- throw new NullPointerException("activity may not be null.");
- }
- enforceResumed(activity);
- try {
- sService.invokeBeam();
- return true;
- } catch (RemoteException e) {
- Log.e(TAG, "invokeBeam: NFC process has died.");
- attemptDeadServiceRecovery(e);
- return false;
- }
- }
-
- /**
- * @hide
- */
- public boolean invokeBeam(BeamShareData shareData) {
- try {
- Log.e(TAG, "invokeBeamInternal()");
- sService.invokeBeamInternal(shareData);
- return true;
- } catch (RemoteException e) {
- Log.e(TAG, "invokeBeam: NFC process has died.");
- attemptDeadServiceRecovery(e);
- return false;
- }
+ return false;
}
/**
@@ -1777,25 +1641,18 @@
*
* @param activity foreground activity
* @param message a NDEF Message to push over NFC
- * @throws IllegalStateException if the activity is not currently in the foreground
- * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @deprecated use {@link #setNdefPushMessage} instead
+ * @throws UnsupportedOperationException if FEATURE_NFC is unavailable
+ * @removed this feature is removed. File sharing can work using other technology like
+ * Bluetooth.
*/
@Deprecated
+ @UnsupportedAppUsage
public void enableForegroundNdefPush(Activity activity, NdefMessage message) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
- if (!sHasBeamFeature) {
- return;
- }
}
- if (activity == null || message == null) {
- throw new NullPointerException();
- }
- enforceResumed(activity);
- mNfcActivityManager.setNdefPushMessage(activity, message, 0);
}
/**
@@ -1814,27 +1671,18 @@
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param activity the Foreground activity
- * @throws IllegalStateException if the Activity has already been paused
- * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @deprecated use {@link #setNdefPushMessage} instead
+ * @throws UnsupportedOperationException if FEATURE_NFC is unavailable
+ * @removed this feature is removed. File sharing can work using other technology like
+ * Bluetooth.
*/
@Deprecated
+ @UnsupportedAppUsage
public void disableForegroundNdefPush(Activity activity) {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
- if (!sHasBeamFeature) {
- return;
- }
}
- if (activity == null) {
- throw new NullPointerException();
- }
- enforceResumed(activity);
- mNfcActivityManager.setNdefPushMessage(activity, null, 0);
- mNfcActivityManager.setNdefPushMessageCallback(activity, null, 0);
- mNfcActivityManager.setOnNdefPushCompleteCallback(activity, null);
}
/**
@@ -1959,40 +1807,26 @@
* Enable NDEF Push feature.
* <p>This API is for the Settings application.
* @hide
+ * @removed
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ @UnsupportedAppUsage
public boolean enableNdefPush() {
- if (!sHasNfcFeature) {
- throw new UnsupportedOperationException();
- }
- try {
- return sService.enableNdefPush();
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- return false;
- }
+ return false;
}
/**
* Disable NDEF Push feature.
* <p>This API is for the Settings application.
* @hide
+ * @removed
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ @UnsupportedAppUsage
public boolean disableNdefPush() {
- synchronized (NfcAdapter.class) {
- if (!sHasNfcFeature) {
- throw new UnsupportedOperationException();
- }
- }
- try {
- return sService.disableNdefPush();
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- return false;
- }
+ return false;
}
/**
@@ -2018,26 +1852,18 @@
* @see android.provider.Settings#ACTION_NFCSHARING_SETTINGS
* @return true if NDEF Push feature is enabled
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @removed this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
-
+ @UnsupportedAppUsage
public boolean isNdefPushEnabled() {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
- if (!sHasBeamFeature) {
- return false;
- }
}
- try {
- return sService.isNdefPushEnabled();
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- return false;
- }
+ return false;
}
/**
@@ -2128,17 +1954,6 @@
}
/**
- * @hide
- */
- public void setP2pModes(int initiatorModes, int targetModes) {
- try {
- sService.setP2pModes(initiatorModes, targetModes);
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- }
- }
-
- /**
* Registers a new NFC unlock handler with the NFC service.
*
* <p />NFC unlock handlers are intended to unlock the keyguard in the presence of a trusted
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 832f23c..9689be2 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -787,12 +787,9 @@
* PackageManager.setComponentEnabledSetting} will now throw an
* IllegalArgumentException if the given component class name does not
* exist in the application's manifest.
- * <li> {@link android.nfc.NfcAdapter#setNdefPushMessage
- * NfcAdapter.setNdefPushMessage},
- * {@link android.nfc.NfcAdapter#setNdefPushMessageCallback
- * NfcAdapter.setNdefPushMessageCallback} and
- * {@link android.nfc.NfcAdapter#setOnNdefPushCompleteCallback
- * NfcAdapter.setOnNdefPushCompleteCallback} will throw
+ * <li> {@code NfcAdapter.setNdefPushMessage},
+ * {@code NfcAdapter.setNdefPushMessageCallback} and
+ * {@code NfcAdapter.setOnNdefPushCompleteCallback} will throw
* IllegalStateException if called after the Activity has been destroyed.
* <li> Accessibility services must require the new
* {@link android.Manifest.permission#BIND_ACCESSIBILITY_SERVICE} permission or
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 2142c4c..13d54ef 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -2994,6 +2994,7 @@
*/
@IntDef(prefix = { "LOW_POWER_STANDBY_ALLOWED_REASON_" }, flag = true, value = {
LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION,
+ LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST,
})
@Retention(RetentionPolicy.SOURCE)
public @interface LowPowerStandbyAllowedReason {
@@ -3006,6 +3007,13 @@
*/
public static final int LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION = 1 << 0;
+ /**
+ * Exempts apps on the temporary powersave allowlist.
+ *
+ * @see #isAllowedInLowPowerStandby(int)
+ */
+ public static final int LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST = 1 << 1;
+
/** @hide */
public static String lowPowerStandbyAllowedReasonsToString(
@LowPowerStandbyAllowedReason int allowedReasons) {
@@ -3014,6 +3022,10 @@
allowedStrings.add("ALLOWED_REASON_VOICE_INTERACTION");
allowedReasons &= ~LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION;
}
+ if ((allowedReasons & LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST) != 0) {
+ allowedStrings.add("ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST");
+ allowedReasons &= ~LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST;
+ }
if (allowedReasons != 0) {
allowedStrings.add(String.valueOf(allowedReasons));
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e0c022f..563adf8 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1716,7 +1716,6 @@
* Input: Nothing.
* <p>
* Output: Nothing
- * @see android.nfc.NfcAdapter#isNdefPushEnabled()
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_NFCSHARING_SETTINGS =
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index af43222..98c0d7f 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -129,7 +129,8 @@
*
* @hide
*/
- public static final class TimeResult {
+ // Non-final for mocking frameworks
+ public static class TimeResult {
private final long mUnixEpochTimeMillis;
private final long mElapsedRealtimeMillis;
private final int mUncertaintyMillis;
diff --git a/core/java/android/util/PackageUtils.java b/core/java/android/util/PackageUtils.java
index 6f8c5db..ea7efc7 100644
--- a/core/java/android/util/PackageUtils.java
+++ b/core/java/android/util/PackageUtils.java
@@ -184,24 +184,15 @@
}
/**
- * @see #computeSha256DigestForLargeFile(String, byte[], String)
- */
- public static @Nullable String computeSha256DigestForLargeFile(@NonNull String filePath,
- @NonNull byte[] fileBuffer) {
- return computeSha256DigestForLargeFile(filePath, fileBuffer, null);
- }
-
- /**
- * Computes the SHA256 digest of large files. This is typically useful for large APEXs.
+ * Computes the SHA256 digest of a large file.
* @param filePath The path to which the file's content is to be hashed.
* @param fileBuffer A buffer to read file's content into memory. It is strongly recommended to
* make use of the {@link #createLargeFileBuffer()} method to create this
* buffer.
- * @param separator Separator between each pair of characters, such as colon, or null to omit.
- * @return The SHA256 digest or null if an error occurs.
+ * @return The byte array of SHA256 digest or null if an error occurs.
*/
- public static @Nullable String computeSha256DigestForLargeFile(@NonNull String filePath,
- @NonNull byte[] fileBuffer, @Nullable String separator) {
+ public static @Nullable byte[] computeSha256DigestForLargeFileAsBytes(@NonNull String filePath,
+ @NonNull byte[] fileBuffer) {
MessageDigest messageDigest;
try {
messageDigest = MessageDigest.getInstance("SHA256");
@@ -221,8 +212,30 @@
return null;
}
- byte[] resultBytes = messageDigest.digest();
+ return messageDigest.digest();
+ }
+ /**
+ * @see #computeSha256DigestForLargeFile(String, byte[], String)
+ */
+ public static @Nullable String computeSha256DigestForLargeFile(@NonNull String filePath,
+ @NonNull byte[] fileBuffer) {
+ return computeSha256DigestForLargeFile(filePath, fileBuffer, null);
+ }
+
+ /**
+ * Computes the SHA256 digest of a large file.
+ * @param filePath The path to which the file's content is to be hashed.
+ * @param fileBuffer A buffer to read file's content into memory. It is strongly recommended to
+ * make use of the {@link #createLargeFileBuffer()} method to create this
+ * buffer.
+ * @param separator Separator between each pair of characters, such as colon, or null to omit.
+ * @see #computeSha256DigestForLargeFile(String, byte[])
+ * @return The encoded string of SHA256 digest or null if an error occurs.
+ */
+ public static @Nullable String computeSha256DigestForLargeFile(@NonNull String filePath,
+ @NonNull byte[] fileBuffer, @Nullable String separator) {
+ byte[] resultBytes = computeSha256DigestForLargeFileAsBytes(filePath, fileBuffer);
if (separator == null) {
return HexEncoding.encodeToString(resultBytes, false);
}
diff --git a/core/java/android/view/DragEvent.java b/core/java/android/view/DragEvent.java
index bda707b..1898407 100644
--- a/core/java/android/view/DragEvent.java
+++ b/core/java/android/view/DragEvent.java
@@ -619,10 +619,11 @@
}
if (in.readInt() != 0) {
event.mDragSurface = SurfaceControl.CREATOR.createFromParcel(in);
+ event.mDragSurface.setUnreleasedWarningCallSite("DragEvent");
}
if (in.readInt() != 0) {
event.mDragAndDropPermissions =
- IDragAndDropPermissions.Stub.asInterface(in.readStrongBinder());;
+ IDragAndDropPermissions.Stub.asInterface(in.readStrongBinder());
}
return event;
}
diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java
index 8d8ddb9..5ea640c 100644
--- a/core/java/android/view/RemoteAnimationTarget.java
+++ b/core/java/android/view/RemoteAnimationTarget.java
@@ -296,6 +296,9 @@
taskId = in.readInt();
mode = in.readInt();
leash = in.readTypedObject(SurfaceControl.CREATOR);
+ if (leash != null) {
+ leash.setUnreleasedWarningCallSite("RemoteAnimationTarget[leash]");
+ }
isTranslucent = in.readBoolean();
clipRect = in.readTypedObject(Rect.CREATOR);
contentInsets = in.readTypedObject(Rect.CREATOR);
@@ -307,6 +310,9 @@
windowConfiguration = in.readTypedObject(WindowConfiguration.CREATOR);
isNotInRecents = in.readBoolean();
startLeash = in.readTypedObject(SurfaceControl.CREATOR);
+ if (startLeash != null) {
+ startLeash.setUnreleasedWarningCallSite("RemoteAnimationTarget[startLeash]");
+ }
startBounds = in.readTypedObject(Rect.CREATOR);
taskInfo = in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
allowEnterPip = in.readBoolean();
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 8e09411..c3302cb 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -1291,6 +1291,20 @@
}
/**
+ * Provides more information to show about the source of this SurfaceControl if it is finalized
+ * without being released. This is primarily intended for callers to update the call site after
+ * receiving a SurfaceControl from another process, which would otherwise get a generic default
+ * call site.
+ * @hide
+ */
+ public void setUnreleasedWarningCallSite(@NonNull String callsite) {
+ if (!isValid()) {
+ return;
+ }
+ mCloseGuard.openWithCallSite("release", callsite);
+ }
+
+ /**
* Checks whether two {@link SurfaceControl} objects represent the same surface.
*
* @param other The other object to check
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index f7bdd09..52b96de 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -170,6 +170,7 @@
private SurfacePackage(Parcel in) {
mSurfaceControl = new SurfaceControl();
mSurfaceControl.readFromParcel(in);
+ mSurfaceControl.setUnreleasedWarningCallSite("SurfacePackage(Parcel)");
mAccessibilityEmbeddedConnection = IAccessibilityEmbeddedConnection.Stub.asInterface(
in.readStrongBinder());
mInputToken = in.readStrongBinder();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index cecfc8a..241ee5a 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8945,11 +8945,33 @@
outRect.set(position.left, position.top, position.right, position.bottom);
}
+ /**
+ * Gets the location of this view in window coordinates.
+ *
+ * @param outRect The output location
+ * @param clipToParent Whether to clip child bounds to the parent ones.
+ * @hide
+ */
+ public void getBoundsInWindow(Rect outRect, boolean clipToParent) {
+ if (mAttachInfo == null) {
+ return;
+ }
+ RectF position = mAttachInfo.mTmpTransformRect;
+ getBoundsToWindowInternal(position, clipToParent);
+ outRect.set(Math.round(position.left), Math.round(position.top),
+ Math.round(position.right), Math.round(position.bottom));
+ }
+
private void getBoundsToScreenInternal(RectF position, boolean clipToParent) {
position.set(0, 0, mRight - mLeft, mBottom - mTop);
mapRectFromViewToScreenCoords(position, clipToParent);
}
+ private void getBoundsToWindowInternal(RectF position, boolean clipToParent) {
+ position.set(0, 0, mRight - mLeft, mBottom - mTop);
+ mapRectFromViewToWindowCoords(position, clipToParent);
+ }
+
/**
* Map a rectangle from view-relative coordinates to screen-relative coordinates
*
@@ -8958,6 +8980,18 @@
* @hide
*/
public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
+ mapRectFromViewToWindowCoords(rect, clipToParent);
+ rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
+ }
+
+ /**
+ * Map a rectangle from view-relative coordinates to window-relative coordinates
+ *
+ * @param rect The rectangle to be mapped
+ * @param clipToParent Whether to clip child bounds to the parent ones.
+ * @hide
+ */
+ public void mapRectFromViewToWindowCoords(RectF rect, boolean clipToParent) {
if (!hasIdentityMatrix()) {
getMatrix().mapRect(rect);
}
@@ -8990,8 +9024,6 @@
ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
rect.offset(0, -viewRootImpl.mCurScrollY);
}
-
- rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
}
/**
@@ -10578,6 +10610,8 @@
getBoundsOnScreen(bounds, true);
info.setBoundsInScreen(bounds);
+ getBoundsInWindow(bounds, true);
+ info.setBoundsInWindow(bounds);
ViewParent parent = getParentForAccessibility();
if (parent instanceof View) {
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index d88cdf1..4576d62 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -906,6 +906,7 @@
private int mBooleanProperties;
private final Rect mBoundsInParent = new Rect();
private final Rect mBoundsInScreen = new Rect();
+ private final Rect mBoundsInWindow = new Rect();
private int mDrawingOrderInParent;
private CharSequence mPackageName;
@@ -2156,6 +2157,49 @@
}
/**
+ * Gets the node bounds in window coordinates.
+ * <p>
+ * When magnification is enabled, the bounds in window are scaled up by magnification scale
+ * and the positions are also adjusted according to the offset of magnification viewport.
+ * For example, it returns Rect(-180, -180, 0, 0) for original bounds Rect(10, 10, 100, 100),
+ * when the magnification scale is 2 and offsets for X and Y are both 200.
+ * <p/>
+ *
+ * @param outBounds The output node bounds.
+ */
+ public void getBoundsInWindow(@NonNull Rect outBounds) {
+ outBounds.set(mBoundsInWindow.left, mBoundsInWindow.top,
+ mBoundsInWindow.right, mBoundsInWindow.bottom);
+ }
+
+ /**
+ * Returns the actual rect containing the node bounds in window coordinates.
+ *
+ * @hide Not safe to expose outside the framework.
+ */
+ @NonNull
+ public Rect getBoundsInWindow() {
+ return mBoundsInWindow;
+ }
+
+ /**
+ * Sets the node bounds in window coordinates.
+ * <p>
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
+ * This class is made immutable before being delivered to an AccessibilityService.
+ * </p>
+ *
+ * @param bounds The node bounds.
+ *
+ * @throws IllegalStateException If called from an AccessibilityService.
+ */
+ public void setBoundsInWindow(@NonNull Rect bounds) {
+ enforceNotSealed();
+ mBoundsInWindow.set(bounds);
+ }
+
+ /**
* Gets whether this node is checkable.
*
* @return True if the node is checkable.
@@ -4054,6 +4098,11 @@
nonDefaultFields |= bitAt(fieldIndex);
}
fieldIndex++;
+ if (!Objects.equals(mBoundsInWindow, DEFAULT.mBoundsInWindow)) {
+ nonDefaultFields |= bitAt(fieldIndex);
+ }
+ fieldIndex++;
+
if (!Objects.equals(mActions, DEFAULT.mActions)) nonDefaultFields |= bitAt(fieldIndex);
fieldIndex++;
if (mMaxTextLength != DEFAULT.mMaxTextLength) nonDefaultFields |= bitAt(fieldIndex);
@@ -4203,6 +4252,13 @@
}
if (isBitSet(nonDefaultFields, fieldIndex++)) {
+ parcel.writeInt(mBoundsInWindow.top);
+ parcel.writeInt(mBoundsInWindow.bottom);
+ parcel.writeInt(mBoundsInWindow.left);
+ parcel.writeInt(mBoundsInWindow.right);
+ }
+
+ if (isBitSet(nonDefaultFields, fieldIndex++)) {
if (mActions != null && !mActions.isEmpty()) {
final int actionCount = mActions.size();
@@ -4333,6 +4389,7 @@
mUniqueId = other.mUniqueId;
mBoundsInParent.set(other.mBoundsInParent);
mBoundsInScreen.set(other.mBoundsInScreen);
+ mBoundsInWindow.set(other.mBoundsInWindow);
mPackageName = other.mPackageName;
mClassName = other.mClassName;
mText = other.mText;
@@ -4465,6 +4522,13 @@
}
if (isBitSet(nonDefaultFields, fieldIndex++)) {
+ mBoundsInWindow.top = parcel.readInt();
+ mBoundsInWindow.bottom = parcel.readInt();
+ mBoundsInWindow.left = parcel.readInt();
+ mBoundsInWindow.right = parcel.readInt();
+ }
+
+ if (isBitSet(nonDefaultFields, fieldIndex++)) {
final long standardActions = parcel.readLong();
addStandardActions(standardActions);
final int nonStandardActionCount = parcel.readInt();
@@ -4815,6 +4879,7 @@
builder.append("; boundsInParent: ").append(mBoundsInParent);
builder.append("; boundsInScreen: ").append(mBoundsInScreen);
+ builder.append("; boundsInWindow: ").append(mBoundsInScreen);
builder.append("; packageName: ").append(mPackageName);
builder.append("; className: ").append(mClassName);
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index c8a69e2..e277b49 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -198,6 +198,7 @@
in.readTypedList(mChanges, Change.CREATOR);
mRootLeash = new SurfaceControl();
mRootLeash.readFromParcel(in);
+ mRootLeash.setUnreleasedWarningCallSite("TransitionInfo");
mRootOffset.readFromParcel(in);
mOptions = in.readTypedObject(AnimationOptions.CREATOR);
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index b79c540..b4599c8 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -332,7 +332,6 @@
"libdl",
"libdl_android",
"libtimeinstate",
- "libtflite",
"server_configurable_flags",
"libimage_io",
"libjpegdecoder",
diff --git a/core/proto/android/nfc/nfc_service.proto b/core/proto/android/nfc/nfc_service.proto
index 2df1d5d..1dcd5cc 100644
--- a/core/proto/android/nfc/nfc_service.proto
+++ b/core/proto/android/nfc/nfc_service.proto
@@ -60,7 +60,7 @@
optional bool secure_nfc_capable = 13;
optional bool vr_mode_enabled = 14;
optional DiscoveryParamsProto discovery_params = 15;
- optional P2pLinkManagerProto p2p_link_manager = 16;
+ reserved 16;
optional com.android.nfc.cardemulation.CardEmulationManagerProto card_emulation_manager = 17;
optional NfcDispatcherProto nfc_dispatcher = 18;
optional string native_crash_logs = 19 [(.android.privacy).dest = DEST_EXPLICIT];
@@ -77,38 +77,6 @@
optional bool enable_p2p = 5;
}
-// Debugging information for com.android.nfc.P2pLinkManager
-message P2pLinkManagerProto {
- option (.android.msg_privacy).dest = DEST_AUTOMATIC;
-
- enum LinkState {
- LINK_STATE_UNKNOWN = 0;
- LINK_STATE_DOWN = 1;
- LINK_STATE_DEBOUNCE = 2;
- LINK_STATE_UP = 3;
- }
-
- enum SendState {
- SEND_STATE_UNKNOWN = 0;
- SEND_STATE_NOTHING_TO_SEND = 1;
- SEND_STATE_NEED_CONFIRMATION = 2;
- SEND_STATE_SENDING = 3;
- SEND_STATE_COMPLETE = 4;
- SEND_STATE_CANCELED = 5;
- }
-
- optional int32 default_miu = 1;
- optional int32 default_rw_size = 2;
- optional LinkState link_state = 3;
- optional SendState send_state = 4;
- optional int32 send_flags = 5;
- optional bool send_enabled = 6;
- optional bool receive_enabled = 7;
- optional string callback_ndef = 8 [(.android.privacy).dest = DEST_EXPLICIT];
- optional .android.nfc.NdefMessageProto message_to_send = 9;
- repeated string uris_to_send = 10 [(.android.privacy).dest = DEST_EXPLICIT];
-}
-
// Debugging information for com.android.nfc.NfcDispatcher
message NfcDispatcherProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f937390..bb3fc01 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -176,6 +176,7 @@
<protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST" />
<protected-broadcast android:name="android.bluetooth.device.action.SDP_RECORD" />
<protected-broadcast android:name="android.bluetooth.device.action.BATTERY_LEVEL_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.REMOTE_ISSUE_OCCURRED" />
<protected-broadcast android:name="android.bluetooth.devicepicker.action.LAUNCH" />
<protected-broadcast android:name="android.bluetooth.devicepicker.action.DEVICE_SELECTED" />
<protected-broadcast
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 11a4ed7..d2ee5de 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1648,14 +1648,25 @@
or has been granted the access to one of the attached USB devices/accessories.
-->
<flag name="connectedDevice" value="0x10" />
- <!-- Managing a media projection session, e.g, for screen recording or taking
- screenshots.
+ <!-- Managing a {@link android.media.projection.MediaProjection MediaProjection} session,
+ e.g., for screen recording or takingscreenshots.
- <p>For apps with <code>targetSdkVersion</code>
- {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and above, starting a foreground
- service with this type will require permission
- {@link android.Manifest.permission#FOREGROUND_SERVICE_MEDIA_PROJECTION}, and the user
- must have allowed the screen capture request from this app.
+ <p>
+ To capture through {@link android.media.projection.MediaProjection}, an app must start
+ a foreground service with the type corresponding to this constant. This type should
+ only be used for {@link android.media.projection.MediaProjection}. Capturing screen
+ contents via
+ {@link android.media.projection.MediaProjection#createVirtualDisplay(String, int, int,
+ int, int, android.view.Surface, android.hardware.display.VirtualDisplay.Callback,
+ android.os.Handler) createVirtualDisplay} conveniently allows recording, presenting
+ screen contents into a meeting, taking screenshots, or several other scenarios.
+ </p>
+
+ <p>For apps with <code>targetSdkVersion</code>
+ {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and above, starting a
+ foreground service with this type will require permission
+ {@link android.Manifest.permission#FOREGROUND_SERVICE_MEDIA_PROJECTION}, and the user
+ must have allowed the screen capture request from this app.
-->
<flag name="mediaProjection" value="0x20" />
<!-- Use the camera device or record video.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index c75ee93..8e5ae9c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2997,6 +2997,12 @@
<string name="config_customAdbWifiNetworkConfirmationSecondaryUserComponent"
>com.android.systemui/com.android.systemui.wifi.WifiDebuggingSecondaryUserActivity</string>
+ <!-- Package name of the system service that implements the shared connectivity service -->
+ <string translatable="false" name="shared_connectivity_service_package"></string>
+
+ <!-- Intent action used when binding to the shared connectivity service -->
+ <string translatable="false" name="shared_connectivity_service_intent_action"></string>
+
<!-- Component name of the activity that shows the usb containment status. -->
<string name="config_usbContaminantActivity" translatable="false"
>com.android.systemui/com.android.systemui.usb.UsbContaminantActivity</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d7cdf73..91d5692 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4938,6 +4938,9 @@
<java-symbol type="bool" name="config_stopSystemPackagesByDefault"/>
<java-symbol type="string" name="config_wearServiceComponent" />
+ <java-symbol type="string" name="shared_connectivity_service_package" />
+ <java-symbol type="string" name="shared_connectivity_service_intent_action" />
+
<!-- Whether to show weather on the lockscreen by default. -->
<java-symbol type="bool" name="config_lockscreenWeatherEnabledByDefault" />
</resources>
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
index 248420f..0d7c8b8 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
@@ -46,7 +46,7 @@
// The number of fields tested in the corresponding CTS AccessibilityNodeInfoTest:
// See fullyPopulateAccessibilityNodeInfo, assertEqualsAccessibilityNodeInfo,
// and assertAccessibilityNodeInfoCleared in that class.
- private static final int NUM_MARSHALLED_PROPERTIES = 42;
+ private static final int NUM_MARSHALLED_PROPERTIES = 43;
/**
* The number of properties that are purposely not marshalled
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/RootDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/RootDisplayAreaOrganizer.java
index b085b73..34bf9e0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/RootDisplayAreaOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/RootDisplayAreaOrganizer.java
@@ -76,6 +76,7 @@
+ " mDisplayAreasInfo.get():" + mDisplayAreasInfo.get(displayId));
}
+ leash.setUnreleasedWarningCallSite("RootDisplayAreaOrganizer.onDisplayAreaAppeared");
mDisplayAreasInfo.put(displayId, displayAreaInfo);
mLeashes.put(displayId, leash);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
index ca977ed..544d757 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
@@ -122,6 +122,8 @@
+ " mDisplayAreasInfo.get():" + mDisplayAreasInfo.get(displayId));
}
+ leash.setUnreleasedWarningCallSite(
+ "RootTaskDisplayAreaOrganizer.onDisplayAreaAppeared");
mDisplayAreasInfo.put(displayId, displayAreaInfo);
mLeashes.put(displayId, leash);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index b5ef72a..585f81c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -464,6 +464,9 @@
@Override
public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
+ if (leash != null) {
+ leash.setUnreleasedWarningCallSite("ShellTaskOrganizer.onTaskAppeared");
+ }
synchronized (mLock) {
onTaskAppeared(new TaskAppearedInfo(taskInfo, leash));
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java
index f376e1f..32894cd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java
@@ -117,6 +117,7 @@
@Override
public void onDisplayAreaAppeared(@NonNull DisplayAreaInfo displayAreaInfo,
@NonNull SurfaceControl leash) {
+ leash.setUnreleasedWarningCallSite("HideDisplayCutoutOrganizer.onDisplayAreaAppeared");
if (!addDisplayAreaInfoAndLeashToMap(displayAreaInfo, leash)) {
return;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
index 451afa0..38ce164 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
@@ -154,6 +154,8 @@
@Override
public void onDisplayAreaAppeared(@NonNull DisplayAreaInfo displayAreaInfo,
@NonNull SurfaceControl leash) {
+ leash.setUnreleasedWarningCallSite(
+ "OneHandedSiaplyAreaOrganizer.onDisplayAreaAppeared");
mDisplayAreaTokenMap.put(displayAreaInfo.token, leash);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index ec34f73..00ed094 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -1215,6 +1215,9 @@
@Override
public void stopSwipePipToHome(int taskId, ComponentName componentName,
Rect destinationBounds, SurfaceControl overlay) {
+ if (overlay != null) {
+ overlay.setUnreleasedWarningCallSite("PipController.stopSwipePipToHome");
+ }
executeRemoteCallWithTaskPermission(mController, "stopSwipePipToHome",
(controller) -> {
controller.stopSwipePipToHome(taskId, componentName, destinationBounds,
diff --git a/libs/hwui/pipeline/skia/ShaderCache.cpp b/libs/hwui/pipeline/skia/ShaderCache.cpp
index a55de95..c1bcb55 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.cpp
+++ b/libs/hwui/pipeline/skia/ShaderCache.cpp
@@ -33,7 +33,8 @@
// Cache size limits.
static const size_t maxKeySize = 1024;
static const size_t maxValueSize = 2 * 1024 * 1024;
-static const size_t maxTotalSize = 1024 * 1024;
+static const size_t maxTotalSize = 4 * 1024 * 1024;
+static_assert(maxKeySize + maxValueSize < maxTotalSize);
ShaderCache::ShaderCache() {
// There is an "incomplete FileBlobCache type" compilation error, if ctor is moved to header.
diff --git a/media/java/android/media/projection/MediaProjectionManager.java b/media/java/android/media/projection/MediaProjectionManager.java
index 6d65c26..f327e4e 100644
--- a/media/java/android/media/projection/MediaProjectionManager.java
+++ b/media/java/android/media/projection/MediaProjectionManager.java
@@ -29,6 +29,7 @@
import android.os.ServiceManager;
import android.util.ArrayMap;
import android.util.Log;
+import android.view.Surface;
import java.util.Map;
@@ -74,8 +75,9 @@
* Returns an {@link Intent} that <b>must</b> be passed to
* {@link Activity#startActivityForResult(Intent, int)} (or similar) in order to start screen
* capture. The activity will prompt the user whether to allow screen capture. The result of
- * this activity (received by overriding {@link Activity#onActivityResult(int, int, Intent)}
- * should be passed to {@link #getMediaProjection(int, Intent)}.
+ * this activity (received by overriding {@link Activity#onActivityResult(int, int, Intent)
+ * onActivityResult(int, int, Intent)}) should be passed to
+ * {@link #getMediaProjection(int, Intent)}.
* <p>
* Identical to calling {@link #createScreenCaptureIntent(MediaProjectionConfig)} with
* a {@link MediaProjectionConfig#createConfigForUserChoice()}.
@@ -102,8 +104,8 @@
* capture. Customizes the activity and resulting {@link MediaProjection} session based up
* the provided {@code config}. The activity will prompt the user whether to allow screen
* capture. The result of this activity (received by overriding
- * {@link Activity#onActivityResult(int, int, Intent)}) should be passed to
- * {@link #getMediaProjection(int, Intent)}.
+ * {@link Activity#onActivityResult(int, int, Intent) onActivityResult(int, int, Intent)})
+ * should be passed to {@link #getMediaProjection(int, Intent)}.
*
* <p>
* If {@link MediaProjectionConfig} was created from:
@@ -146,47 +148,48 @@
/**
* Retrieves the {@link MediaProjection} obtained from a successful screen
- * capture request. The result code and data from the request are provided
- * by overriding {@link Activity#onActivityResult(int, int, Intent)
- * onActivityResult(int, int, Intent)}, which is called after starting an
- * activity using {@link #createScreenCaptureIntent()}.
- *
- * <p>Starting from Android {@link android.os.Build.VERSION_CODES#R}, if
- * your application requests the
- * {@link android.Manifest.permission#SYSTEM_ALERT_WINDOW
- * SYSTEM_ALERT_WINDOW} permission, and the user has not explicitly denied
- * it, the permission will be automatically granted until the projection is
- * stopped. The permission allows your app to display user controls on top
- * of the screen being captured.
- *
- * <p>Apps targeting SDK version {@link android.os.Build.VERSION_CODES#Q} or
- * later must set the
- * {@link android.R.attr#foregroundServiceType foregroundServiceType}
- * attribute to {@code mediaProjection} in the
- * <a href="/guide/topics/manifest/service-element">
- * <code><service></code></a> element of the app's manifest file;
- * {@code mediaProjection} is equivalent to
+ * capture request. The result code and data from the request are provided by overriding
+ * {@link Activity#onActivityResult(int, int, Intent) onActivityResult(int, int, Intent)},
+ * which is called after starting an activity using {@link #createScreenCaptureIntent()}.
+ * <p>
+ * Starting from Android {@link android.os.Build.VERSION_CODES#R R}, if your application
+ * requests the {@link android.Manifest.permission#SYSTEM_ALERT_WINDOW SYSTEM_ALERT_WINDOW}
+ * permission, and the user has not explicitly denied it, the permission will be automatically
+ * granted until the projection is stopped. The permission allows your app to display user
+ * controls on top of the screen being captured.
+ * </p>
+ * <p>
+ * An app targeting SDK version {@link android.os.Build.VERSION_CODES#Q Q} or later must
+ * invoke {@code getMediaProjection} and maintain the capture session
+ * ({@link MediaProjection#createVirtualDisplay(String, int, int, int, int, Surface,
+ * android.hardware.display.VirtualDisplay.Callback, Handler)
+ * MediaProjection#createVirtualDisplay}) while running a foreground service. The app must set
+ * the {@link android.R.attr#foregroundServiceType foregroundServiceType} attribute to
* {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
- * FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION}.
+ * FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION} in the
+ * <a href="/guide/topics/manifest/service-element"><code><service></code></a> element of
+ * the app's manifest file.
+ * </p>
*
- * @see <a href="/guide/components/foreground-services">
- * Foreground services developer guide</a>
- * @see <a href="/guide/topics/large-screens/media-projection">
- * Media projection developer guide</a>
- *
- * @param resultCode The result code from
- * {@link android.app.Activity#onActivityResult(int, int, android.content.Intent)
- * onActivityResult(int, int, Intent)}.
- * @param resultData The result data from
- * {@link android.app.Activity#onActivityResult(int, int, android.content.Intent)
- * onActivityResult(int, int, Intent)}.
- * @return The media projection obtained from a successful screen capture
- * request, or null if the result of the screen capture request is not
- * {@link Activity#RESULT_OK RESULT_OK}.
+ * @param resultCode The result code from {@link Activity#onActivityResult(int, int, Intent)
+ * onActivityResult(int, int, Intent)}.
+ * @param resultData The result data from {@link Activity#onActivityResult(int, int, Intent)
+ * onActivityResult(int, int, Intent)}.
+ * @return The media projection obtained from a successful screen capture request, or null if
+ * the result of the screen capture request is not {@link Activity#RESULT_OK RESULT_OK}.
* @throws IllegalStateException On
- * pre-{@link android.os.Build.VERSION_CODES#Q Q} devices if a
- * previously obtained {@code MediaProjection} from the same
- * {@code resultData} has not yet been stopped.
+ * pre-{@link android.os.Build.VERSION_CODES#Q Q} devices if a
+ * previously obtained {@code MediaProjection} from the same
+ * {@code resultData} has not yet been stopped.
+ * @throws SecurityException On {@link android.os.Build.VERSION_CODES#Q Q}+ devices if not
+ * invoked from a foreground service with type
+ * {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
+ * FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION}, unless caller is a
+ * privileged app.
+ * @see <a href="/guide/components/foreground-services">
+ * Foreground services developer guide</a>
+ * @see <a href="/guide/topics/large-screens/media-projection">
+ * Media projection developer guide</a>
*/
public MediaProjection getMediaProjection(int resultCode, @NonNull Intent resultData) {
if (resultCode != Activity.RESULT_OK || resultData == null) {
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index 00a58f2..7306a1f 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -116,6 +116,36 @@
<item>full</item>
</string-array>
+ <!-- Titles for Bluetooth HCI Snoop Filtered Logging -->
+ <string-array name="bt_hci_snoop_log_filters_entries">
+ <item>Headers Filtered</item>
+ <item>A2DP Media Packets Filtered</item>
+ <item>RFCOMM Channel Filtered</item>
+ </string-array>
+
+ <!-- Values for Bluetooth HCI Snoop Filtered Logging -->
+ <string-array name="bt_hci_snoop_log_filters_values" translatable="false">
+ <item>headers</item>
+ <item>profiles.a2dp</item>
+ <item>profiles.rfcomm</item>
+ </string-array>
+
+ <!-- Titles for Bluetooth HCI Snoop Filtered Logging -->
+ <string-array name="bt_hci_snoop_log_profile_filter_entries">
+ <item>Disabled</item>
+ <item>Magic</item>
+ <item>Header</item>
+ <item>Full Filter</item>
+ </string-array>
+
+ <!-- Values for Bluetooth HCI Snoop Filtered Logging -->
+ <string-array name="bt_hci_snoop_log_profile_filter_values" translatable="false">
+ <item>disabled</item>
+ <item>magic</item>
+ <item>header</item>
+ <item>fullfilter</item>
+ </string-array>
+
<!-- Titles for Bluetooth AVRCP Versions -->
<string-array name="bluetooth_avrcp_versions">
<item>AVRCP 1.5 (Default)</item>
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableImageView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt
similarity index 93%
rename from packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableImageView.kt
rename to packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt
index 7bbfec7..a1d9d90 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableImageView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt
@@ -15,7 +15,7 @@
*
*/
-package com.android.systemui.common.ui.view
+package com.android.systemui.animation.view
import android.content.Context
import android.util.AttributeSet
@@ -23,6 +23,7 @@
import com.android.systemui.animation.LaunchableView
import com.android.systemui.animation.LaunchableViewDelegate
+/** An [ImageView] that also implements [LaunchableView]. */
class LaunchableImageView : ImageView, LaunchableView {
private val delegate =
LaunchableViewDelegate(
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableLinearLayout.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableLinearLayout.kt
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableLinearLayout.kt
rename to packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableLinearLayout.kt
index 2edac52..bce2622 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableLinearLayout.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableLinearLayout.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.common.ui.view
+package com.android.systemui.animation.view
import android.content.Context
import android.util.AttributeSet
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableImageView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt
similarity index 78%
copy from packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableImageView.kt
copy to packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt
index 7bbfec7..286996d 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableImageView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,15 +15,16 @@
*
*/
-package com.android.systemui.common.ui.view
+package com.android.systemui.animation.view
import android.content.Context
import android.util.AttributeSet
-import android.widget.ImageView
+import android.widget.TextView
import com.android.systemui.animation.LaunchableView
import com.android.systemui.animation.LaunchableViewDelegate
-class LaunchableImageView : ImageView, LaunchableView {
+/** A [TextView] that also implements [LaunchableView]. */
+class LaunchableTextView : TextView, LaunchableView {
private val delegate =
LaunchableViewDelegate(
this,
@@ -38,13 +39,6 @@
defStyleAttr: Int,
) : super(context, attrs, defStyleAttr)
- constructor(
- context: Context?,
- attrs: AttributeSet?,
- defStyleAttr: Int,
- defStyleRes: Int,
- ) : super(context, attrs, defStyleAttr, defStyleRes)
-
override fun setShouldBlockVisibilityChanges(block: Boolean) {
delegate.setShouldBlockVisibilityChanges(block)
}
diff --git a/packages/SystemUI/res-keyguard/layout/footer_actions_text_button.xml b/packages/SystemUI/res-keyguard/layout/footer_actions_text_button.xml
index fc18132..6fe7d39 100644
--- a/packages/SystemUI/res-keyguard/layout/footer_actions_text_button.xml
+++ b/packages/SystemUI/res-keyguard/layout/footer_actions_text_button.xml
@@ -14,7 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<com.android.systemui.common.ui.view.LaunchableLinearLayout
+<com.android.systemui.animation.view.LaunchableLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="@dimen/qs_security_footer_single_line_height"
@@ -63,4 +63,4 @@
android:src="@*android:drawable/ic_chevron_end"
android:autoMirrored="true"
android:tint="?android:attr/textColorSecondary" />
-</com.android.systemui.common.ui.view.LaunchableLinearLayout>
\ No newline at end of file
+</com.android.systemui.animation.view.LaunchableLinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/dream_overlay_home_controls_chip.xml b/packages/SystemUI/res/layout/dream_overlay_home_controls_chip.xml
index 446bb01..fb78b49 100644
--- a/packages/SystemUI/res/layout/dream_overlay_home_controls_chip.xml
+++ b/packages/SystemUI/res/layout/dream_overlay_home_controls_chip.xml
@@ -20,7 +20,7 @@
android:layout_width="wrap_content"
android:paddingVertical="@dimen/dream_overlay_complication_home_controls_padding">
- <com.android.systemui.common.ui.view.LaunchableImageView
+ <com.android.systemui.animation.view.LaunchableImageView
android:id="@+id/home_controls_chip"
android:layout_height="@dimen/keyguard_affordance_fixed_height"
android:layout_width="@dimen/keyguard_affordance_fixed_width"
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 3f95515..2871cdf 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -59,7 +59,7 @@
</LinearLayout>
- <com.android.systemui.common.ui.view.LaunchableImageView
+ <com.android.systemui.animation.view.LaunchableImageView
android:id="@+id/start_button"
android:layout_height="@dimen/keyguard_affordance_fixed_height"
android:layout_width="@dimen/keyguard_affordance_fixed_width"
@@ -72,7 +72,7 @@
android:layout_marginBottom="@dimen/keyguard_affordance_vertical_offset"
android:visibility="gone" />
- <com.android.systemui.common.ui.view.LaunchableImageView
+ <com.android.systemui.animation.view.LaunchableImageView
android:id="@+id/end_button"
android:layout_height="@dimen/keyguard_affordance_fixed_height"
android:layout_width="@dimen/keyguard_affordance_fixed_width"
diff --git a/packages/SystemUI/res/layout/media_session_view.xml b/packages/SystemUI/res/layout/media_session_view.xml
index f2e114b..9d91419 100644
--- a/packages/SystemUI/res/layout/media_session_view.xml
+++ b/packages/SystemUI/res/layout/media_session_view.xml
@@ -106,7 +106,7 @@
app:layout_constrainedWidth="true"
app:layout_constraintWidth_min="@dimen/min_clickable_item_size"
app:layout_constraintHeight_min="@dimen/min_clickable_item_size">
- <com.android.systemui.common.ui.view.LaunchableLinearLayout
+ <com.android.systemui.animation.view.LaunchableLinearLayout
android:id="@+id/media_seamless_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -135,7 +135,7 @@
android:textDirection="locale"
android:textSize="12sp"
android:lineHeight="16sp" />
- </com.android.systemui.common.ui.view.LaunchableLinearLayout>
+ </com.android.systemui.animation.view.LaunchableLinearLayout>
</LinearLayout>
<!-- Song name -->
diff --git a/packages/SystemUI/res/layout/ongoing_call_chip.xml b/packages/SystemUI/res/layout/ongoing_call_chip.xml
index 18d231c..238fc84 100644
--- a/packages/SystemUI/res/layout/ongoing_call_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_call_chip.xml
@@ -23,7 +23,7 @@
android:layout_gravity="center_vertical|start"
android:layout_marginStart="5dp"
>
- <com.android.systemui.common.ui.view.LaunchableLinearLayout
+ <com.android.systemui.animation.view.LaunchableLinearLayout
android:id="@+id/ongoing_call_chip_background"
android:layout_width="wrap_content"
android:layout_height="@dimen/ongoing_appops_chip_height"
@@ -55,5 +55,5 @@
android:textColor="?android:attr/colorPrimary"
/>
- </com.android.systemui.common.ui.view.LaunchableLinearLayout>
+ </com.android.systemui.animation.view.LaunchableLinearLayout>
</FrameLayout>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
index 13b3aca..27fe747 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
@@ -70,7 +70,15 @@
buffer.log(TAG, DEBUG, {
str1 = entry.logKey
}, {
- "No alerting: snoozed package: $str1"
+ "No heads up: snoozed package: $str1"
+ })
+ }
+
+ fun logHeadsUpPackageSnoozeBypassedHasFsi(entry: NotificationEntry) {
+ buffer.log(TAG, DEBUG, {
+ str1 = entry.logKey
+ }, {
+ "Heads up: package snooze bypassed because notification has full-screen intent: $str1"
})
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
index 9bcf92d..afeb72f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
@@ -19,6 +19,7 @@
import static com.android.systemui.statusbar.StatusBarState.SHADE;
import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD;
import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.FSI_SUPPRESSED_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR;
+import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.HUN_SNOOZE_BYPASSED_POTENTIALLY_SUPPRESSED_FSI;
import android.app.Notification;
import android.app.NotificationManager;
@@ -87,7 +88,10 @@
FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD(1236),
@UiEvent(doc = "HUN suppressed for old when")
- HUN_SUPPRESSED_OLD_WHEN(1237);
+ HUN_SUPPRESSED_OLD_WHEN(1237),
+
+ @UiEvent(doc = "HUN snooze bypassed for potentially suppressed FSI")
+ HUN_SNOOZE_BYPASSED_POTENTIALLY_SUPPRESSED_FSI(1269);
private final int mId;
@@ -409,7 +413,15 @@
return false;
}
- if (isSnoozedPackage(sbn)) {
+ final boolean isSnoozedPackage = isSnoozedPackage(sbn);
+ final boolean fsiRequiresKeyguard = mFlags.fullScreenIntentRequiresKeyguard();
+ final boolean hasFsi = sbn.getNotification().fullScreenIntent != null;
+
+ // Assume any notification with an FSI is time-sensitive (like an alarm or incoming call)
+ // and ignore whether HUNs have been snoozed for the package.
+ final boolean shouldBypassSnooze = fsiRequiresKeyguard && hasFsi;
+
+ if (isSnoozedPackage && !shouldBypassSnooze) {
if (log) mLogger.logNoHeadsUpPackageSnoozed(entry);
return false;
}
@@ -447,6 +459,19 @@
return false;
}
}
+
+ if (isSnoozedPackage) {
+ if (log) {
+ mLogger.logHeadsUpPackageSnoozeBypassedHasFsi(entry);
+ final int uid = entry.getSbn().getUid();
+ final String packageName = entry.getSbn().getPackageName();
+ mUiEventLogger.log(HUN_SNOOZE_BYPASSED_POTENTIALLY_SUPPRESSED_FSI, uid,
+ packageName);
+ }
+
+ return true;
+ }
+
if (log) mLogger.logHeadsUp(entry);
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherContainer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherContainer.kt
index 2d80edb..270c592 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherContainer.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherContainer.kt
@@ -21,7 +21,7 @@
import android.widget.ImageView
import android.widget.TextView
import com.android.systemui.R
-import com.android.systemui.common.ui.view.LaunchableLinearLayout
+import com.android.systemui.animation.view.LaunchableLinearLayout
class StatusBarUserSwitcherContainer(
context: Context?,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamHomeControlsComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamHomeControlsComplicationTest.java
index fc1d38b..8534d4f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamHomeControlsComplicationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamHomeControlsComplicationTest.java
@@ -37,7 +37,7 @@
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.common.ui.view.LaunchableImageView;
+import com.android.systemui.animation.view.LaunchableImageView;
import com.android.systemui.controls.ControlsServiceInfo;
import com.android.systemui.controls.controller.ControlsController;
import com.android.systemui.controls.controller.StructureInfo;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
index 831d07f..07d0dbd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
@@ -741,7 +741,7 @@
}
@Test
- public void testShouldFullScreen_snoozed_occluding_withStrictRules() throws Exception {
+ public void testShouldNotFullScreen_snoozed_occluding_withStrictRules() throws Exception {
when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true);
NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
when(mPowerManager.isInteractive()).thenReturn(true);
@@ -753,16 +753,41 @@
when(mKeyguardStateController.isOccluded()).thenReturn(true);
assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry))
- .isEqualTo(FullScreenIntentDecision.FSI_KEYGUARD_OCCLUDED);
+ .isEqualTo(FullScreenIntentDecision.NO_FSI_EXPECTED_TO_HUN);
assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
- .isTrue();
- verify(mLogger, never()).logNoFullscreen(any(), any());
+ .isFalse();
+ verify(mLogger).logNoFullscreen(entry, "Expected to HUN");
verify(mLogger, never()).logNoFullscreenWarning(any(), any());
- verify(mLogger).logFullscreen(entry, "Expected not to HUN while keyguard occluded");
+ verify(mLogger, never()).logFullscreen(any(), any());
}
@Test
- public void testShouldFullScreen_snoozed_lockedShade_withStrictRules() throws Exception {
+ public void testShouldHeadsUp_snoozed_occluding_withStrictRules() throws Exception {
+ when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true);
+ NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
+ when(mPowerManager.isInteractive()).thenReturn(true);
+ when(mPowerManager.isScreenOn()).thenReturn(true);
+ when(mDreamManager.isDreaming()).thenReturn(false);
+ when(mStatusBarStateController.getState()).thenReturn(SHADE);
+ when(mHeadsUpManager.isSnoozed("a")).thenReturn(true);
+ when(mKeyguardStateController.isShowing()).thenReturn(true);
+ when(mKeyguardStateController.isOccluded()).thenReturn(true);
+
+ assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isTrue();
+
+ verify(mLogger).logHeadsUpPackageSnoozeBypassedHasFsi(entry);
+ verify(mLogger, never()).logHeadsUp(any());
+
+ assertThat(mUiEventLoggerFake.numLogs()).isEqualTo(1);
+ UiEventLoggerFake.FakeUiEvent fakeUiEvent = mUiEventLoggerFake.get(0);
+ assertThat(fakeUiEvent.eventId).isEqualTo(
+ NotificationInterruptEvent.HUN_SNOOZE_BYPASSED_POTENTIALLY_SUPPRESSED_FSI.getId());
+ assertThat(fakeUiEvent.uid).isEqualTo(entry.getSbn().getUid());
+ assertThat(fakeUiEvent.packageName).isEqualTo(entry.getSbn().getPackageName());
+ }
+
+ @Test
+ public void testShouldNotFullScreen_snoozed_lockedShade_withStrictRules() throws Exception {
when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true);
NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
when(mPowerManager.isInteractive()).thenReturn(true);
@@ -774,12 +799,37 @@
when(mKeyguardStateController.isOccluded()).thenReturn(false);
assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry))
- .isEqualTo(FullScreenIntentDecision.FSI_LOCKED_SHADE);
+ .isEqualTo(FullScreenIntentDecision.NO_FSI_EXPECTED_TO_HUN);
assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
- .isTrue();
- verify(mLogger, never()).logNoFullscreen(any(), any());
+ .isFalse();
+ verify(mLogger).logNoFullscreen(entry, "Expected to HUN");
verify(mLogger, never()).logNoFullscreenWarning(any(), any());
- verify(mLogger).logFullscreen(entry, "Keyguard is showing and not occluded");
+ verify(mLogger, never()).logFullscreen(any(), any());
+ }
+
+ @Test
+ public void testShouldHeadsUp_snoozed_lockedShade_withStrictRules() throws Exception {
+ when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true);
+ NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
+ when(mPowerManager.isInteractive()).thenReturn(true);
+ when(mPowerManager.isScreenOn()).thenReturn(true);
+ when(mDreamManager.isDreaming()).thenReturn(false);
+ when(mStatusBarStateController.getState()).thenReturn(SHADE_LOCKED);
+ when(mHeadsUpManager.isSnoozed("a")).thenReturn(true);
+ when(mKeyguardStateController.isShowing()).thenReturn(true);
+ when(mKeyguardStateController.isOccluded()).thenReturn(false);
+
+ assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isTrue();
+
+ verify(mLogger).logHeadsUpPackageSnoozeBypassedHasFsi(entry);
+ verify(mLogger, never()).logHeadsUp(any());
+
+ assertThat(mUiEventLoggerFake.numLogs()).isEqualTo(1);
+ UiEventLoggerFake.FakeUiEvent fakeUiEvent = mUiEventLoggerFake.get(0);
+ assertThat(fakeUiEvent.eventId).isEqualTo(
+ NotificationInterruptEvent.HUN_SNOOZE_BYPASSED_POTENTIALLY_SUPPRESSED_FSI.getId());
+ assertThat(fakeUiEvent.uid).isEqualTo(entry.getSbn().getUid());
+ assertThat(fakeUiEvent.packageName).isEqualTo(entry.getSbn().getPackageName());
}
@Test
@@ -795,21 +845,41 @@
when(mKeyguardStateController.isOccluded()).thenReturn(false);
assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry))
- .isEqualTo(FullScreenIntentDecision.NO_FSI_NO_HUN_OR_KEYGUARD);
+ .isEqualTo(FullScreenIntentDecision.NO_FSI_EXPECTED_TO_HUN);
assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
.isFalse();
- verify(mLogger, never()).logNoFullscreen(any(), any());
- verify(mLogger).logNoFullscreenWarning(entry, "Expected not to HUN while not on keyguard");
+ verify(mLogger).logNoFullscreen(entry, "Expected to HUN");
+ verify(mLogger, never()).logNoFullscreenWarning(any(), any());
verify(mLogger, never()).logFullscreen(any(), any());
+ }
+
+ @Test
+ public void testShouldHeadsUp_snoozed_unlocked_withStrictRules() throws Exception {
+ when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true);
+ NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
+ when(mPowerManager.isInteractive()).thenReturn(true);
+ when(mPowerManager.isScreenOn()).thenReturn(true);
+ when(mDreamManager.isDreaming()).thenReturn(false);
+ when(mStatusBarStateController.getState()).thenReturn(SHADE);
+ when(mHeadsUpManager.isSnoozed("a")).thenReturn(true);
+ when(mKeyguardStateController.isShowing()).thenReturn(false);
+ when(mKeyguardStateController.isOccluded()).thenReturn(false);
+
+ assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isTrue();
+
+ verify(mLogger).logHeadsUpPackageSnoozeBypassedHasFsi(entry);
+ verify(mLogger, never()).logHeadsUp(any());
assertThat(mUiEventLoggerFake.numLogs()).isEqualTo(1);
UiEventLoggerFake.FakeUiEvent fakeUiEvent = mUiEventLoggerFake.get(0);
assertThat(fakeUiEvent.eventId).isEqualTo(
- NotificationInterruptEvent.FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD.getId());
+ NotificationInterruptEvent.HUN_SNOOZE_BYPASSED_POTENTIALLY_SUPPRESSED_FSI.getId());
assertThat(fakeUiEvent.uid).isEqualTo(entry.getSbn().getUid());
assertThat(fakeUiEvent.packageName).isEqualTo(entry.getSbn().getPackageName());
}
+ /* TODO: Verify the FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD UiEvent some other way. */
+
/**
* Bubbles can happen.
*/
diff --git a/services/core/java/com/android/server/BinaryTransparencyService.java b/services/core/java/com/android/server/BinaryTransparencyService.java
index eafd3e0..9d07365 100644
--- a/services/core/java/com/android/server/BinaryTransparencyService.java
+++ b/services/core/java/com/android/server/BinaryTransparencyService.java
@@ -263,26 +263,26 @@
Map<Integer, byte[]> contentDigests = computeApkContentDigest(apkPath);
if (contentDigests == null) {
Slog.d(TAG, "Failed to compute content digest for " + apkPath);
- return new Checksum(0, new byte[] { -1 });
- }
-
- // in this iteration, we'll be supporting only 2 types of digests:
- // CHUNKED_SHA256 and CHUNKED_SHA512.
- // And only one of them will be available per package.
- if (contentDigests.containsKey(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256)) {
- return new Checksum(
- Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256,
- contentDigests.get(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256));
- } else if (contentDigests.containsKey(
- ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512)) {
- return new Checksum(
- Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512,
- contentDigests.get(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512));
} else {
- // TODO(b/259423111): considering putting the raw values for the algorithm & digest
- // into the bundle to track potential other digest algorithms that may be in use
- return new Checksum(0, new byte[] { -1 });
+ // in this iteration, we'll be supporting only 2 types of digests:
+ // CHUNKED_SHA256 and CHUNKED_SHA512.
+ // And only one of them will be available per package.
+ if (contentDigests.containsKey(
+ ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256)) {
+ return new Checksum(
+ Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256,
+ contentDigests.get(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256));
+ } else if (contentDigests.containsKey(
+ ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512)) {
+ return new Checksum(
+ Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512,
+ contentDigests.get(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512));
+ }
}
+ // When something went wrong, fall back to simple sha256.
+ byte[] digest = PackageUtils.computeSha256DigestForLargeFileAsBytes(apkPath,
+ PackageUtils.createLargeFileBuffer());
+ return new Checksum(Checksum.TYPE_WHOLE_SHA256, digest);
}
@@ -1199,7 +1199,7 @@
}
/**
- * JobService to measure all covered binaries and record result to Westworld.
+ * JobService to measure all covered binaries and record results to statsd.
*/
public static class UpdateMeasurementsJobService extends JobService {
private static long sTimeLastRanMs = 0;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1fe097e..b7985a5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -13692,6 +13692,17 @@
// not be used generally, so we will be marking them as exported by default
boolean requireExplicitFlagForDynamicReceivers = CompatChanges.isChangeEnabled(
DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED, callingUid);
+
+ // A receiver that is visible to instant apps must also be exported.
+ final boolean unexportedReceiverVisibleToInstantApps =
+ ((flags & Context.RECEIVER_VISIBLE_TO_INSTANT_APPS) != 0) && (
+ (flags & Context.RECEIVER_NOT_EXPORTED) != 0);
+ if (unexportedReceiverVisibleToInstantApps && requireExplicitFlagForDynamicReceivers) {
+ throw new IllegalArgumentException(
+ "Receiver can't specify both RECEIVER_VISIBLE_TO_INSTANT_APPS and "
+ + "RECEIVER_NOT_EXPORTED flag");
+ }
+
// STOPSHIP(b/259139792): Allow apps that are currently targeting U and in process of
// updating their receivers to be exempt from this requirement until their receivers
// are flagged.
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 14ecf9f..8b34fe0 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -376,7 +376,7 @@
return DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_WINDOW_MANAGER,
ENABLE_DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_SENDER,
- false); // assume false if the property is unknown
+ true);
}
/**
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 3f2083f..6032fec 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -167,10 +167,10 @@
);
/**
- * User restrictions that cannot be set by profile owners of secondary users. When set by DO
- * they will be applied to all users.
+ * User restrictions that can only be set by profile owners on the main user, or by device
+ * owners. When set by DO they will be applied to all users.
*/
- private static final Set<String> PRIMARY_USER_ONLY_RESTRICTIONS = Sets.newArraySet(
+ private static final Set<String> MAIN_USER_ONLY_RESTRICTIONS = Sets.newArraySet(
UserManager.DISALLOW_BLUETOOTH,
UserManager.DISALLOW_USB_FILE_TRANSFER,
UserManager.DISALLOW_CONFIG_TETHERING,
@@ -454,14 +454,14 @@
}
/**
- * @return true if a restriction is settable by profile owner. Note it takes a user ID because
- * some restrictions can be changed by PO only when it's running on the system user.
+ * @return true if a restriction is settable by profile owner. Note it takes a boolean to say
+ * if the relevant user is the {@link UserManager#isMainUser() MainUser}, because some
+ * restrictions can be changed by PO only when it's running on the main user.
*/
- public static boolean canProfileOwnerChange(String restriction, int userId) {
+ public static boolean canProfileOwnerChange(String restriction, boolean isMainUser) {
return !IMMUTABLE_BY_OWNERS.contains(restriction)
&& !DEVICE_OWNER_ONLY_RESTRICTIONS.contains(restriction)
- && !(userId != UserHandle.USER_SYSTEM
- && PRIMARY_USER_ONLY_RESTRICTIONS.contains(restriction));
+ && !(!isMainUser && MAIN_USER_ONLY_RESTRICTIONS.contains(restriction));
}
/**
@@ -494,7 +494,7 @@
public static boolean isGlobal(@UserManagerInternal.OwnerType int restrictionOwnerType,
String key) {
return ((restrictionOwnerType == UserManagerInternal.OWNER_TYPE_DEVICE_OWNER) && (
- PRIMARY_USER_ONLY_RESTRICTIONS.contains(key) || GLOBAL_RESTRICTIONS.contains(key)))
+ MAIN_USER_ONLY_RESTRICTIONS.contains(key) || GLOBAL_RESTRICTIONS.contains(key)))
|| ((restrictionOwnerType
== UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE)
&& PROFILE_OWNER_ORGANIZATION_OWNED_GLOBAL_RESTRICTIONS.contains(key))
diff --git a/services/core/java/com/android/server/power/LowPowerStandbyController.java b/services/core/java/com/android/server/power/LowPowerStandbyController.java
index 223bd55..0dc5f76 100644
--- a/services/core/java/com/android/server/power/LowPowerStandbyController.java
+++ b/services/core/java/com/android/server/power/LowPowerStandbyController.java
@@ -16,6 +16,7 @@
package com.android.server.power;
+import static android.os.PowerManager.LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST;
import static android.os.PowerManager.lowPowerStandbyAllowedReasonsToString;
import android.Manifest;
@@ -59,6 +60,7 @@
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
import com.android.server.LocalServices;
+import com.android.server.PowerAllowlistInternal;
import com.android.server.net.NetworkPolicyManagerInternal;
import org.xmlpull.v1.XmlPullParser;
@@ -134,7 +136,7 @@
@GuardedBy("mLock")
private boolean mEnableCustomPolicy;
- private final BroadcastReceiver mIdleBroadcastReceiver = new BroadcastReceiver() {
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
@@ -150,6 +152,8 @@
}
}
};
+ private final TempAllowlistChangeListener mTempAllowlistChangeListener =
+ new TempAllowlistChangeListener();
private final BroadcastReceiver mPackageBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -318,7 +322,7 @@
updateSettingsLocked();
if (mIsEnabled) {
- registerBroadcastReceiver();
+ registerListeners();
}
}
@@ -594,7 +598,7 @@
onNonInteractive();
}
- registerBroadcastReceiver();
+ registerListeners();
}
@GuardedBy("mLock")
@@ -604,7 +608,7 @@
}
cancelStandbyTimeoutAlarmLocked();
- unregisterBroadcastReceiver();
+ unregisterListeners();
updateActiveLocked();
}
@@ -629,13 +633,13 @@
}
}
- private void registerBroadcastReceiver() {
+ private void registerListeners() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
- mContext.registerReceiver(mIdleBroadcastReceiver, intentFilter);
+ mContext.registerReceiver(mBroadcastReceiver, intentFilter);
IntentFilter packageFilter = new IntentFilter();
packageFilter.addDataScheme(IntentFilter.SCHEME_PACKAGE);
@@ -648,12 +652,18 @@
userFilter.addAction(Intent.ACTION_USER_ADDED);
userFilter.addAction(Intent.ACTION_USER_REMOVED);
mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
+
+ PowerAllowlistInternal pai = LocalServices.getService(PowerAllowlistInternal.class);
+ pai.registerTempAllowlistChangeListener(mTempAllowlistChangeListener);
}
- private void unregisterBroadcastReceiver() {
- mContext.unregisterReceiver(mIdleBroadcastReceiver);
+ private void unregisterListeners() {
+ mContext.unregisterReceiver(mBroadcastReceiver);
mContext.unregisterReceiver(mPackageBroadcastReceiver);
mContext.unregisterReceiver(mUserReceiver);
+
+ PowerAllowlistInternal pai = LocalServices.getService(PowerAllowlistInternal.class);
+ pai.unregisterTempAllowlistChangeListener(mTempAllowlistChangeListener);
}
@GuardedBy("mLock")
@@ -1197,4 +1207,18 @@
onSettingsChanged();
}
}
+
+ final class TempAllowlistChangeListener implements
+ PowerAllowlistInternal.TempAllowlistChangeListener {
+ @Override
+ public void onAppAdded(int uid) {
+ addToAllowlistInternal(uid, LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST);
+ }
+
+ @Override
+ public void onAppRemoved(int uid) {
+ removeFromAllowlistInternal(uid,
+ LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST);
+ }
+ }
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
index 71764dc..8f16737 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
@@ -555,8 +555,9 @@
if (!hasLocalPolicyLocked(policyDefinition, userId)) {
return null;
}
- return getLocalPolicyStateLocked(policyDefinition, userId)
- .getPoliciesSetByAdmins().get(enforcingAdmin).getValue();
+ PolicyValue<V> value = getLocalPolicyStateLocked(policyDefinition, userId)
+ .getPoliciesSetByAdmins().get(enforcingAdmin);
+ return value == null ? null : value.getValue();
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f5a1b80..d6dc5d2 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -235,6 +235,7 @@
import android.app.admin.IntegerPolicyValue;
import android.app.admin.IntentFilterPolicyKey;
import android.app.admin.LockTaskPolicy;
+import android.app.admin.LongPolicyValue;
import android.app.admin.ManagedProfileProvisioningParams;
import android.app.admin.ManagedSubscriptionsPolicy;
import android.app.admin.NetworkEvent;
@@ -9038,12 +9039,12 @@
}
private @UserIdInt int getMainUserId() {
- UserHandle mainUser = mUserManager.getMainUser();
- if (mainUser == null) {
+ int mainUserId = mUserManagerInternal.getMainUserId();
+ if (mainUserId == UserHandle.USER_NULL) {
Slogf.d(LOG_TAG, "getMainUserId(): no main user, returning USER_SYSTEM");
return UserHandle.USER_SYSTEM;
}
- return mainUser.getIdentifier();
+ return mainUserId;
}
// TODO(b/240562946): Remove api as owner name is not used.
@@ -12019,10 +12020,10 @@
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
}
- int userHandle = caller.getUserId();
+ int userId = caller.getUserId();
synchronized (getLockObject()) {
final ActiveAdmin activeAdmin = getParentOfAdminIfRequired(
- getProfileOwnerOrDeviceOwnerLocked(userHandle), parent);
+ getProfileOwnerOrDeviceOwnerLocked(userId), parent);
if (isDefaultDeviceOwner(caller)) {
if (!UserRestrictionsUtils.canDeviceOwnerChange(key)) {
@@ -12039,7 +12040,8 @@
"Cannot use the parent instance in Financed Device Owner mode");
} else {
boolean profileOwnerCanChangeOnItself = !parent
- && UserRestrictionsUtils.canProfileOwnerChange(key, userHandle);
+ && UserRestrictionsUtils.canProfileOwnerChange(
+ key, userId == getMainUserId());
boolean orgOwnedProfileOwnerCanChangesGlobally = parent
&& isProfileOwnerOfOrganizationOwnedDevice(caller)
&& UserRestrictionsUtils.canProfileOwnerOfOrganizationOwnedDeviceChange(
@@ -12058,7 +12060,7 @@
} else {
restrictions.remove(key);
}
- saveUserRestrictionsLocked(userHandle);
+ saveUserRestrictionsLocked(userId);
}
final int eventId = enabledFromThisOwner
? DevicePolicyEnums.ADD_USER_RESTRICTION
@@ -12072,7 +12074,7 @@
final int eventTag = enabledFromThisOwner
? SecurityLog.TAG_USER_RESTRICTION_ADDED
: SecurityLog.TAG_USER_RESTRICTION_REMOVED;
- SecurityLog.writeEvent(eventTag, who.getPackageName(), userHandle, key);
+ SecurityLog.writeEvent(eventTag, who.getPackageName(), userId, key);
}
}
@@ -16996,23 +16998,52 @@
final CallerIdentity caller = getCallerIdentity(admin);
Preconditions.checkCallAuthorization(
isProfileOwner(caller) || isDefaultDeviceOwner(caller));
+ final int userId = caller.getUserId();
- synchronized (getLockObject()) {
- final int userHandle = caller.getUserId();
-
- DevicePolicyData policy = getUserData(userHandle);
- return mInjector.binderWithCleanCallingIdentity(() -> {
- if (policy.mPasswordTokenHandle != 0) {
- mLockPatternUtils.removeEscrowToken(policy.mPasswordTokenHandle, userHandle);
- }
- policy.mPasswordTokenHandle = mLockPatternUtils.addEscrowToken(token,
- userHandle, /*EscrowTokenStateChangeCallback*/ null);
- saveSettingsLocked(userHandle);
+ if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
+ EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
+ admin, userId);
+ Long currentTokenHandle = mDevicePolicyEngine.getLocalPolicySetByAdmin(
+ PolicyDefinition.RESET_PASSWORD_TOKEN,
+ enforcingAdmin,
+ userId);
+ long tokenHandle = addEscrowToken(
+ token, currentTokenHandle == null ? 0 : currentTokenHandle, userId);
+ if (tokenHandle == 0) {
+ return false;
+ }
+ mDevicePolicyEngine.setLocalPolicy(
+ PolicyDefinition.RESET_PASSWORD_TOKEN,
+ enforcingAdmin,
+ new LongPolicyValue(tokenHandle),
+ userId);
+ return true;
+ } else {
+ synchronized (getLockObject()) {
+ DevicePolicyData policy = getUserData(userId);
+ policy.mPasswordTokenHandle = addEscrowToken(
+ token, policy.mPasswordTokenHandle, userId);
+ saveSettingsLocked(userId);
return policy.mPasswordTokenHandle != 0;
- });
+ }
}
}
+ private long addEscrowToken(byte[] token, long currentPasswordTokenHandle, int userId) {
+ resetEscrowToken(currentPasswordTokenHandle, userId);
+ return mInjector.binderWithCleanCallingIdentity(() -> mLockPatternUtils.addEscrowToken(
+ token, userId, /* EscrowTokenStateChangeCallback= */ null));
+ }
+
+ private boolean resetEscrowToken(long tokenHandle, int userId) {
+ return mInjector.binderWithCleanCallingIdentity(() -> {
+ if (tokenHandle != 0) {
+ return mLockPatternUtils.removeEscrowToken(tokenHandle, userId);
+ }
+ return false;
+ });
+ }
+
@Override
public boolean clearResetPasswordToken(ComponentName admin) {
if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
@@ -17021,22 +17052,34 @@
final CallerIdentity caller = getCallerIdentity(admin);
Preconditions.checkCallAuthorization(
isProfileOwner(caller) || isDefaultDeviceOwner(caller));
+ final int userId = caller.getUserId();
+ boolean result = false;
- synchronized (getLockObject()) {
- final int userHandle = caller.getUserId();
-
- DevicePolicyData policy = getUserData(userHandle);
- if (policy.mPasswordTokenHandle != 0) {
- return mInjector.binderWithCleanCallingIdentity(() -> {
- boolean result = mLockPatternUtils.removeEscrowToken(
- policy.mPasswordTokenHandle, userHandle);
+ if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
+ EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
+ admin, userId);
+ Long currentTokenHandle = mDevicePolicyEngine.getLocalPolicySetByAdmin(
+ PolicyDefinition.RESET_PASSWORD_TOKEN,
+ enforcingAdmin,
+ userId);
+ if (currentTokenHandle != null) {
+ result = resetEscrowToken(currentTokenHandle, userId);
+ mDevicePolicyEngine.removeLocalPolicy(
+ PolicyDefinition.RESET_PASSWORD_TOKEN,
+ enforcingAdmin,
+ userId);
+ }
+ } else {
+ synchronized (getLockObject()) {
+ DevicePolicyData policy = getUserData(userId);
+ if (policy.mPasswordTokenHandle != 0) {
+ result = resetEscrowToken(policy.mPasswordTokenHandle, userId);
policy.mPasswordTokenHandle = 0;
- saveSettingsLocked(userHandle);
- return result;
- });
+ saveSettingsLocked(userId);
+ }
}
}
- return false;
+ return result;
}
@Override
@@ -17048,16 +17091,30 @@
Preconditions.checkCallAuthorization(
isProfileOwner(caller) || isDefaultDeviceOwner(caller));
- synchronized (getLockObject()) {
- return isResetPasswordTokenActiveForUserLocked(caller.getUserId());
+ int userId = caller.getUserId();
+
+ if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
+ EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
+ admin, userId);
+ Long currentTokenHandle = mDevicePolicyEngine.getLocalPolicySetByAdmin(
+ PolicyDefinition.RESET_PASSWORD_TOKEN,
+ enforcingAdmin,
+ userId);
+ return isResetPasswordTokenActiveForUserLocked(
+ currentTokenHandle == null ? 0 : currentTokenHandle, userId);
+ } else {
+ synchronized (getLockObject()) {
+ DevicePolicyData policy = getUserData(userId);
+ return isResetPasswordTokenActiveForUserLocked(policy.mPasswordTokenHandle, userId);
+ }
}
}
- private boolean isResetPasswordTokenActiveForUserLocked(int userHandle) {
- DevicePolicyData policy = getUserData(userHandle);
- if (policy.mPasswordTokenHandle != 0) {
+ private boolean isResetPasswordTokenActiveForUserLocked(
+ long passwordTokenHandle, int userHandle) {
+ if (passwordTokenHandle != 0) {
return mInjector.binderWithCleanCallingIdentity(() ->
- mLockPatternUtils.isEscrowTokenActive(policy.mPasswordTokenHandle, userHandle));
+ mLockPatternUtils.isEscrowTokenActive(passwordTokenHandle, userHandle));
}
return false;
}
@@ -17074,24 +17131,41 @@
Preconditions.checkCallAuthorization(
isProfileOwner(caller) || isDefaultDeviceOwner(caller));
- synchronized (getLockObject()) {
- DevicePolicyData policy = getUserData(caller.getUserId());
- if (policy.mPasswordTokenHandle != 0) {
- final String password = passwordOrNull != null ? passwordOrNull : "";
- final boolean result = resetPasswordInternal(password, policy.mPasswordTokenHandle,
- token, flags, caller);
- if (result) {
- DevicePolicyEventLogger
- .createEvent(DevicePolicyEnums.RESET_PASSWORD_WITH_TOKEN)
- .setAdmin(caller.getComponentName())
- .write();
- }
- return result;
+ int userId = caller.getUserId();
+ boolean result = false;
+ final String password = passwordOrNull != null ? passwordOrNull : "";
+
+ if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
+ EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
+ admin, userId);
+ Long currentTokenHandle = mDevicePolicyEngine.getLocalPolicySetByAdmin(
+ PolicyDefinition.RESET_PASSWORD_TOKEN,
+ enforcingAdmin,
+ userId);
+ if (currentTokenHandle != null && currentTokenHandle != 0) {
+ result = resetPasswordInternal(password, currentTokenHandle, token, flags, caller);
} else {
Slogf.w(LOG_TAG, "No saved token handle");
}
+ } else {
+ synchronized (getLockObject()) {
+ DevicePolicyData policy = getUserData(userId);
+ if (policy.mPasswordTokenHandle != 0) {
+ result = resetPasswordInternal(
+ password, policy.mPasswordTokenHandle, token, flags, caller);
+ } else {
+ Slogf.w(LOG_TAG, "No saved token handle");
+ }
+ }
}
- return false;
+
+ if (result) {
+ DevicePolicyEventLogger
+ .createEvent(DevicePolicyEnums.RESET_PASSWORD_WITH_TOKEN)
+ .setAdmin(caller.getComponentName())
+ .write();
+ }
+ return result;
}
@Override
@@ -18784,9 +18858,11 @@
"call canProfileOwnerResetPasswordWhenLocked"));
synchronized (getLockObject()) {
final ActiveAdmin poAdmin = getProfileOwnerAdminLocked(userId);
+ DevicePolicyData policy = getUserData(userId);
if (poAdmin == null
|| getEncryptionStatus() != ENCRYPTION_STATUS_ACTIVE_PER_USER
- || !isResetPasswordTokenActiveForUserLocked(userId)) {
+ || !isResetPasswordTokenActiveForUserLocked(
+ policy.mPasswordTokenHandle, userId)) {
return false;
}
final ApplicationInfo poAppInfo;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/LongPolicySerializer.java b/services/devicepolicy/java/com/android/server/devicepolicy/LongPolicySerializer.java
new file mode 100644
index 0000000..f77d051
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/LongPolicySerializer.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.devicepolicy;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.admin.LongPolicyValue;
+import android.app.admin.PolicyKey;
+import android.util.Log;
+
+import com.android.modules.utils.TypedXmlPullParser;
+import com.android.modules.utils.TypedXmlSerializer;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.Objects;
+
+final class LongPolicySerializer extends PolicySerializer<Long> {
+
+ @Override
+ void saveToXml(PolicyKey policyKey, TypedXmlSerializer serializer, String attributeName,
+ @NonNull Long value) throws IOException {
+ Objects.requireNonNull(value);
+ serializer.attributeLong(/* namespace= */ null, attributeName, value);
+ }
+
+ @Nullable
+ @Override
+ LongPolicyValue readFromXml(TypedXmlPullParser parser, String attributeName) {
+ try {
+ return new LongPolicyValue(
+ parser.getAttributeLong(/* namespace= */ null, attributeName));
+ } catch (XmlPullParserException e) {
+ Log.e(DevicePolicyEngine.TAG, "Error parsing Long policy value", e);
+ return null;
+ }
+ }
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
index ab6f732..9e0da26 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
@@ -199,6 +199,8 @@
new PolicyDefinition<>(
new PackagePolicyKey(
DevicePolicyManager.APPLICATION_RESTRICTIONS_POLICY),
+ // Don't need to take in a resolution mechanism since its never used, but might
+ // need some refactoring to not always assume a non-null mechanism.
new MostRecent<>(),
POLICY_FLAG_LOCAL_ONLY_POLICY | POLICY_FLAG_NON_COEXISTABLE_POLICY,
// Application restrictions are now stored and retrieved from DPMS, so no
@@ -221,6 +223,16 @@
DevicePolicyManager.APPLICATION_RESTRICTIONS_POLICY, packageName));
}
+ static PolicyDefinition<Long> RESET_PASSWORD_TOKEN = new PolicyDefinition<>(
+ new NoArgsPolicyKey(DevicePolicyManager.RESET_PASSWORD_TOKEN_POLICY),
+ // Don't need to take in a resolution mechanism since its never used, but might
+ // need some refactoring to not always assume a non-null mechanism.
+ new MostRecent<>(),
+ POLICY_FLAG_LOCAL_ONLY_POLICY | POLICY_FLAG_NON_COEXISTABLE_POLICY,
+ // DevicePolicyManagerService handles the enforcement, this just takes care of storage
+ (Long value, Context context, Integer userId, PolicyKey policyKey) -> true,
+ new LongPolicySerializer());
+
private static final Map<String, PolicyDefinition<?>> sPolicyDefinitions = Map.of(
DevicePolicyManager.AUTO_TIMEZONE_POLICY, AUTO_TIMEZONE,
DevicePolicyManager.PERMISSION_GRANT_POLICY, GENERIC_PERMISSION_GRANT,
@@ -230,7 +242,8 @@
DevicePolicyManager.PERSISTENT_PREFERRED_ACTIVITY_POLICY,
GENERIC_PERSISTENT_PREFERRED_ACTIVITY,
DevicePolicyManager.PACKAGE_UNINSTALL_BLOCKED_POLICY, GENERIC_PACKAGE_UNINSTALL_BLOCKED,
- DevicePolicyManager.APPLICATION_RESTRICTIONS_POLICY, GENERIC_APPLICATION_RESTRICTIONS
+ DevicePolicyManager.APPLICATION_RESTRICTIONS_POLICY, GENERIC_APPLICATION_RESTRICTIONS,
+ DevicePolicyManager.RESET_PASSWORD_TOKEN_POLICY, RESET_PASSWORD_TOKEN
);
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
index 419351d4..9263bff 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
@@ -711,8 +711,6 @@
null); // description
// Case 8: App1 gets "remove task"
- final String app1Description = "remove task";
-
sleep(1);
final int app1IsolatedUidUser2 = 1099002; // isolated uid
final long app1Pss4 = 34343;
@@ -739,7 +737,7 @@
mAppExitInfoTracker.mIsolatedUidRecords.addIsolatedUid(app1IsolatedUidUser2, app1UidUser2);
noteAppKill(app, ApplicationExitInfo.REASON_OTHER,
- ApplicationExitInfo.SUBREASON_UNKNOWN, app1Description, now8);
+ ApplicationExitInfo.SUBREASON_REMOVE_TASK, null, now8);
updateExitInfo(app, now8);
list.clear();
@@ -749,21 +747,21 @@
info = list.get(0);
verifyApplicationExitInfo(
- info, // info
- now8, // timestamp
- app1PidUser2, // pid
- app1IsolatedUidUser2, // uid
- app1UidUser2, // packageUid
- null, // definingUid
- app1ProcessName, // processName
- 0, // connectionGroup
- ApplicationExitInfo.REASON_OTHER, // reason
- ApplicationExitInfo.SUBREASON_UNKNOWN, // subReason
- 0, // status
- app1Pss4, // pss
- app1Rss4, // rss
- IMPORTANCE_CACHED, // importance
- app1Description); // description
+ info, // info
+ now8, // timestamp
+ app1PidUser2, // pid
+ app1IsolatedUidUser2, // uid
+ app1UidUser2, // packageUid
+ null, // definingUid
+ app1ProcessName, // processName
+ 0, // connectionGroup
+ ApplicationExitInfo.REASON_OTHER, // reason
+ ApplicationExitInfo.SUBREASON_REMOVE_TASK, // subReason
+ 0, // status
+ app1Pss4, // pss
+ app1Rss4, // rss
+ IMPORTANCE_CACHED, // importance
+ null); // description
// App1 gets "too many empty"
final String app1Description2 = "too many empty";
@@ -1058,7 +1056,18 @@
if (importance != null) {
assertEquals(importance.intValue(), info.getImportance());
}
- if (description != null) {
+
+ // info.getDescription returns a combination of subReason & description
+ if ((subReason != null) && (subReason != ApplicationExitInfo.SUBREASON_UNKNOWN)
+ && (description != null)) {
+ assertTrue(TextUtils.equals(
+ "[" + info.subreasonToString(subReason) + "] " + description,
+ info.getDescription()));
+ } else if ((subReason != null) && (subReason != ApplicationExitInfo.SUBREASON_UNKNOWN)) {
+ assertTrue(TextUtils.equals(
+ "[" + info.subreasonToString(subReason) + "]",
+ info.getDescription()));
+ } else if (description != null) {
assertTrue(TextUtils.equals(description, info.getDescription()));
}
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
index 07a5303..a387d4a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
@@ -20,7 +20,6 @@
import static com.android.server.devicepolicy.DpmTestUtils.newRestrictions;
import android.os.Bundle;
-import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
import android.test.AndroidTestCase;
@@ -77,30 +76,30 @@
assertTrue(UserRestrictionsUtils.canDeviceOwnerChange(UserManager.DISALLOW_USER_SWITCH));
}
- public void testCanProfileOwnerChange() {
- int user = UserHandle.USER_SYSTEM;
+ public void testCanProfileOwnerChange_mainUser() {
assertFalse(UserRestrictionsUtils.canProfileOwnerChange(
- UserManager.DISALLOW_RECORD_AUDIO, user));
+ UserManager.DISALLOW_RECORD_AUDIO, true));
assertFalse(UserRestrictionsUtils.canProfileOwnerChange(
- UserManager.DISALLOW_WALLPAPER, user));
+ UserManager.DISALLOW_WALLPAPER, true));
assertFalse(UserRestrictionsUtils.canProfileOwnerChange(
- UserManager.DISALLOW_USER_SWITCH, user));
+ UserManager.DISALLOW_USER_SWITCH, true));
assertTrue(UserRestrictionsUtils.canProfileOwnerChange(
- UserManager.DISALLOW_ADD_USER, user));
+ UserManager.DISALLOW_ADD_USER, true));
assertTrue(UserRestrictionsUtils.canProfileOwnerChange(
- UserManager.DISALLOW_ADJUST_VOLUME, user));
+ UserManager.DISALLOW_ADJUST_VOLUME, true));
+ }
- user = 10;
+ public void testCanProfileOwnerChange_notMainUser() {
assertFalse(UserRestrictionsUtils.canProfileOwnerChange(
- UserManager.DISALLOW_RECORD_AUDIO, user));
+ UserManager.DISALLOW_RECORD_AUDIO, false));
assertFalse(UserRestrictionsUtils.canProfileOwnerChange(
- UserManager.DISALLOW_WALLPAPER, user));
+ UserManager.DISALLOW_WALLPAPER, false));
assertFalse(UserRestrictionsUtils.canProfileOwnerChange(
- UserManager.DISALLOW_ADD_USER, user));
+ UserManager.DISALLOW_ADD_USER, false));
assertFalse(UserRestrictionsUtils.canProfileOwnerChange(
- UserManager.DISALLOW_USER_SWITCH, user));
+ UserManager.DISALLOW_USER_SWITCH, false));
assertTrue(UserRestrictionsUtils.canProfileOwnerChange(
- UserManager.DISALLOW_ADJUST_VOLUME, user));
+ UserManager.DISALLOW_ADJUST_VOLUME, false));
}
public void testMoveRestriction() {
diff --git a/services/tests/servicestests/src/com/android/server/power/LowPowerStandbyControllerTest.java b/services/tests/servicestests/src/com/android/server/power/LowPowerStandbyControllerTest.java
index 6553ea9..454d3f3 100644
--- a/services/tests/servicestests/src/com/android/server/power/LowPowerStandbyControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/LowPowerStandbyControllerTest.java
@@ -16,6 +16,7 @@
package com.android.server.power;
+import static android.os.PowerManager.LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST;
import static android.os.PowerManager.LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION;
import static android.os.PowerManager.LOW_POWER_STANDBY_FEATURE_WAKE_ON_LAN;
@@ -62,6 +63,8 @@
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.LocalServices;
+import com.android.server.PowerAllowlistInternal;
+import com.android.server.PowerAllowlistInternal.TempAllowlistChangeListener;
import com.android.server.net.NetworkPolicyManagerInternal;
import com.android.server.power.LowPowerStandbyController.DeviceConfigWrapper;
import com.android.server.testutils.OffsettableClock;
@@ -117,6 +120,8 @@
private PowerManagerInternal mPowerManagerInternalMock;
@Mock
private NetworkPolicyManagerInternal mNetworkPolicyManagerInternalMock;
+ @Mock
+ private PowerAllowlistInternal mPowerAllowlistInternalMock;
@Before
public void setUp() throws Exception {
@@ -130,6 +135,7 @@
when(mContextSpy.getSystemService(PowerManager.class)).thenReturn(powerManager);
addLocalServiceMock(PowerManagerInternal.class, mPowerManagerInternalMock);
addLocalServiceMock(NetworkPolicyManagerInternal.class, mNetworkPolicyManagerInternalMock);
+ addLocalServiceMock(PowerAllowlistInternal.class, mPowerAllowlistInternalMock);
when(mIPowerManagerMock.isInteractive()).thenReturn(true);
@@ -169,6 +175,7 @@
LocalServices.removeServiceForTest(PowerManagerInternal.class);
LocalServices.removeServiceForTest(LowPowerStandbyControllerInternal.class);
LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
+ LocalServices.removeServiceForTest(PowerAllowlistInternal.class);
mTestPolicyFile.delete();
}
@@ -614,7 +621,7 @@
InOrder inOrder = inOrder(mPowerManagerInternalMock);
- inOrder.verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[] {
+ inOrder.verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{
UserHandle.getUid(USER_ID_1, TEST_PKG1_APP_ID),
UserHandle.getUid(USER_ID_2, TEST_PKG1_APP_ID),
});
@@ -626,7 +633,7 @@
mContextSpy.sendBroadcast(intent);
mTestLooper.dispatchAll();
- inOrder.verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[] {
+ inOrder.verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{
UserHandle.getUid(USER_ID_1, TEST_PKG1_APP_ID)
});
inOrder.verifyNoMoreInteractions();
@@ -663,6 +670,39 @@
assertFalse(mController.isPackageExempt(TEST_PKG1_APP_ID));
}
+ @Test
+ public void testAllowReason_tempPowerSaveAllowlist() throws Exception {
+ mController.systemReady();
+ mController.setEnabled(true);
+ mController.setPolicy(policyWithAllowedReasons(
+ LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST));
+ mTestLooper.dispatchAll();
+
+ ArgumentCaptor<TempAllowlistChangeListener> tempAllowlistChangeListenerArgumentCaptor =
+ ArgumentCaptor.forClass(TempAllowlistChangeListener.class);
+ verify(mPowerAllowlistInternalMock).registerTempAllowlistChangeListener(
+ tempAllowlistChangeListenerArgumentCaptor.capture());
+ TempAllowlistChangeListener tempAllowlistChangeListener =
+ tempAllowlistChangeListenerArgumentCaptor.getValue();
+
+ tempAllowlistChangeListener.onAppAdded(TEST_PKG1_APP_ID);
+ mTestLooper.dispatchAll();
+ verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{TEST_PKG1_APP_ID});
+
+ tempAllowlistChangeListener.onAppAdded(TEST_PKG2_APP_ID);
+ mTestLooper.dispatchAll();
+ verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(
+ new int[]{TEST_PKG1_APP_ID, TEST_PKG2_APP_ID});
+
+ tempAllowlistChangeListener.onAppRemoved(TEST_PKG1_APP_ID);
+ mTestLooper.dispatchAll();
+ verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[]{TEST_PKG2_APP_ID});
+
+ mController.setPolicy(EMPTY_POLICY);
+ mTestLooper.dispatchAll();
+ verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[0]);
+ }
+
private void setInteractive() throws Exception {
when(mIPowerManagerMock.isInteractive()).thenReturn(true);
mContextSpy.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON));
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityInterceptorCallbackTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityInterceptorCallbackTest.java
new file mode 100644
index 0000000..ff0591b
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityInterceptorCallbackTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.ActivityOptions;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ResolveInfo;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.MediumTest;
+
+import org.junit.Test;
+
+@Presubmit
+@MediumTest
+public class ActivityInterceptorCallbackTest {
+
+ @Test
+ public void testBuildActivityInterceptorCallback() {
+ int callingUid = 10;
+ int callingPid = 100;
+ int realCallingUid = 20;
+ int realCallingPid = 200;
+ int userId = 1;
+ Intent intent = new Intent();
+ ResolveInfo resolveInfo = new ResolveInfo();
+ ActivityInfo activityInfo = new ActivityInfo();
+ String resolveType = "resolveType";
+ String callingPackage = "callingPackage";
+ String callingFeatureId = "callingFeatureId";
+ ActivityOptions activityOptions = ActivityOptions.makeBasic();
+ Runnable clearOptionsAnimation = () -> {};
+
+ ActivityInterceptorCallback.ActivityInterceptorInfo activityInterceptorInfo =
+ new ActivityInterceptorCallback.ActivityInterceptorInfo.Builder(callingUid,
+ callingPid, realCallingUid, realCallingPid, userId, intent, resolveInfo,
+ activityInfo)
+ .setResolvedType(resolveType)
+ .setCallingPackage(callingPackage)
+ .setCallingFeatureId(callingFeatureId)
+ .setCheckedOptions(activityOptions)
+ .setClearOptionsAnimationRunnable(clearOptionsAnimation)
+ .build();
+
+ assertThat(activityInterceptorInfo.getCallingUid()).isEqualTo(callingUid);
+ assertThat(activityInterceptorInfo.getCallingPid()).isEqualTo(callingPid);
+ assertThat(activityInterceptorInfo.getRealCallingUid()).isEqualTo(realCallingUid);
+ assertThat(activityInterceptorInfo.getRealCallingPid()).isEqualTo(realCallingPid);
+ assertThat(activityInterceptorInfo.getUserId()).isEqualTo(userId);
+ assertThat(activityInterceptorInfo.getIntent()).isEqualTo(intent);
+ assertThat(activityInterceptorInfo.getResolveInfo()).isEqualTo(resolveInfo);
+ assertThat(activityInterceptorInfo.getActivityInfo()).isEqualTo(activityInfo);
+ assertThat(activityInterceptorInfo.getResolvedType()).isEqualTo(resolveType);
+ assertThat(activityInterceptorInfo.getCallingPackage()).isEqualTo(callingPackage);
+ assertThat(activityInterceptorInfo.getCallingFeatureId()).isEqualTo(callingFeatureId);
+ assertThat(activityInterceptorInfo.getCheckedOptions()).isEqualTo(activityOptions);
+ assertThat(activityInterceptorInfo.getClearOptionsAnimationRunnable())
+ .isEqualTo(clearOptionsAnimation);
+ }
+
+ @Test
+ public void testActivityInterceptResult() {
+ Intent intent = new Intent();
+ ActivityOptions activityOptions = ActivityOptions.makeBasic();
+ boolean isActivityResolved = true;
+
+ ActivityInterceptorCallback.ActivityInterceptResult result =
+ new ActivityInterceptorCallback.ActivityInterceptResult(intent, activityOptions);
+ assertThat(result.getIntent()).isEqualTo(intent);
+ assertThat(result.getActivityOptions()).isEqualTo(activityOptions);
+ assertThat(result.isActivityResolved()).isFalse();
+
+ result = new ActivityInterceptorCallback.ActivityInterceptResult(
+ intent, activityOptions, isActivityResolved);
+ assertThat(result.getIntent()).isEqualTo(intent);
+ assertThat(result.getActivityOptions()).isEqualTo(activityOptions);
+ assertThat(result.isActivityResolved()).isTrue();
+ }
+}
diff --git a/telephony/java/android/telephony/satellite/ISatelliteCapabilitiesConsumer.aidl b/telephony/java/android/telephony/satellite/ISatelliteCapabilitiesConsumer.aidl
deleted file mode 100644
index f3ae245..0000000
--- a/telephony/java/android/telephony/satellite/ISatelliteCapabilitiesConsumer.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.satellite;
-
-import android.telephony.satellite.SatelliteCapabilities;
-
-/**
- * Consumer for a SatelliteCapabilities result from the satellite service.
- * @hide
- */
-oneway interface ISatelliteCapabilitiesConsumer {
- void accept(in SatelliteCapabilities result);
-}
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index a818b63..129d4ca 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -26,15 +26,15 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
+import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.ICancellationSignal;
+import android.os.OutcomeReceiver;
import android.os.RemoteException;
+import android.os.ResultReceiver;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyFrameworkInitializer;
-import android.telephony.satellite.stub.SatelliteImplBase;
-import com.android.internal.telephony.IBooleanConsumer;
-import com.android.internal.telephony.IIntArrayConsumer;
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.ITelephony;
import com.android.telephony.Rlog;
@@ -72,16 +72,6 @@
}
/**
- * Create a new SatelliteManager associated with the given subscription ID.
- *
- * @param subId The subscription ID to create the SatelliteManager with.
- * @return A SatelliteManager that uses the given subscription ID for all calls.
- */
- @NonNull public SatelliteManager createForSubscriptionId(int subId) {
- return new SatelliteManager(mContext, subId);
- }
-
- /**
* Create an instance of the SatelliteManager associated with a particular subscription.
*
* @param context The context the SatelliteManager belongs to.
@@ -93,6 +83,67 @@
}
/**
+ * Exception from the satellite service containing the {@link SatelliteError} error code.
+ */
+ public static class SatelliteException extends Exception {
+ @SatelliteError private final int mErrorCode;
+
+ /**
+ * Create a SatelliteException with a given error code.
+ *
+ * @param errorCode The {@link SatelliteError}.
+ */
+ public SatelliteException(@SatelliteError int errorCode) {
+ mErrorCode = errorCode;
+ }
+
+ /**
+ * Get the error code returned from the satellite service.
+ *
+ * @return The {@link SatelliteError}.
+ */
+ @SatelliteError public int getErrorCode() {
+ return mErrorCode;
+ }
+ }
+
+ /**
+ * Bundle key to get the response from
+ * {@link #requestIsSatelliteEnabled(Executor, OutcomeReceiver)}.
+ * @hide
+ */
+ public static final String KEY_SATELLITE_ENABLED = "satellite_enabled";
+
+ /**
+ * Bundle key to get the response from
+ * {@link #requestIsSatelliteSupported(Executor, OutcomeReceiver)}.
+ * @hide
+ */
+ public static final String KEY_SATELLITE_SUPPORTED = "satellite_supported";
+
+ /**
+ * Bundle key to get the response from
+ * {@link #requestSatelliteCapabilities(Executor, OutcomeReceiver)}.
+ * @hide
+ */
+ public static final String KEY_SATELLITE_CAPABILITIES = "satellite_capabilities";
+
+ /**
+ * Bundle key to get the response from
+ * {@link #requestMaxCharactersPerSatelliteTextMessage(Executor, OutcomeReceiver)}.
+ * @hide
+ */
+ public static final String KEY_MAX_CHARACTERS_PER_SATELLITE_TEXT =
+ "max_characters_per_satellite_text";
+
+ /**
+ * Bundle key to get the response from
+ * {@link #requestIsSatelliteProvisioned(Executor, OutcomeReceiver)}.
+ * @hide
+ */
+ public static final String KEY_SATELLITE_PROVISIONED = "satellite_provisioned";
+
+ /**
* The request was successfully processed.
*/
public static final int SATELLITE_ERROR_NONE = 0;
@@ -133,8 +184,8 @@
*/
public static final int SATELLITE_INVALID_ARGUMENTS = 8;
/**
- * Telephony framework failed to send a request to the vendor service or the satellite
- * modem due to internal error.
+ * Telephony framework failed to send a request or receive a response from the vendor service
+ * or satellite modem due to internal error.
*/
public static final int SATELLITE_REQUEST_FAILED = 9;
/**
@@ -211,158 +262,201 @@
public @interface SatelliteError {}
/**
- * Power on or off the satellite modem.
+ * Enable or disable the satellite modem. If the satellite modem is enabled, this will also
+ * disable the cellular modem, and if the satellite modem is disabled, this will also re-enable
+ * the cellular modem.
*
- * @param powerOn {@code true} to power on the satellite modem and {@code false} to power off.
+ * @param enable {@code true} to enable the satellite modem and {@code false} to disable.
+ * @param executor The executor on which the error code listener will be called.
+ * @param errorCodeListener Listener for the {@link SatelliteError} result of the operation.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
- *
- * @return The result of the operation.
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @SatelliteError public int setSatellitePower(boolean powerOn) {
+ public void setSatelliteEnabled(boolean enable, @NonNull @CallbackExecutor Executor executor,
+ @NonNull Consumer<Integer> errorCodeListener) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(errorCodeListener);
+
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.setSatellitePower(mSubId, powerOn);
+ IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() -> Binder.withCleanCallingIdentity(
+ () -> errorCodeListener.accept(result)));
+ }
+ };
+ telephony.setSatelliteEnabled(mSubId, enable, errorCallback);
} else {
throw new IllegalStateException("telephony service is null.");
}
} catch (RemoteException ex) {
- Rlog.e(TAG, "setSatellitePower RemoteException", ex);
+ Rlog.e(TAG, "setSatelliteEnabled RemoteException: ", ex);
ex.rethrowFromSystemServer();
}
- return SATELLITE_REQUEST_FAILED;
}
/**
- * Check whether the satellite modem is powered on.
+ * Request to get whether the satellite modem is enabled.
*
- * @param executor The executor on which the result listener will be called.
- * @param resultListener Listener with the result if the operation is successful.
- * If this method returns {@link #SATELLITE_ERROR_NONE}, the result
- * listener will return {@code true} if the satellite modem is powered on
- * and {@code false} otherwise.
+ * @param executor The executor on which the callback will be called.
+ * @param callback The callback object to which the result will be delivered.
+ * If the request is successful, {@link OutcomeReceiver#onResult(Object)}
+ * will return a {@code boolean} with value {@code true} if the satellite modem
+ * is powered on and {@code false} otherwise.
+ * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
+ * will return a {@link SatelliteException} with the {@link SatelliteError}.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
- *
- * @return The result of the operation.
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @SatelliteError public int isSatellitePowerOn(
- @NonNull @CallbackExecutor Executor executor,
- @NonNull Consumer<Boolean> resultListener) {
+ public void requestIsSatelliteEnabled(@NonNull @CallbackExecutor Executor executor,
+ @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) {
Objects.requireNonNull(executor);
- Objects.requireNonNull(resultListener);
+ Objects.requireNonNull(callback);
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- IBooleanConsumer internalCallback = new IBooleanConsumer.Stub() {
+ ResultReceiver receiver = new ResultReceiver(null) {
@Override
- public void accept(boolean result) {
- executor.execute(() -> Binder.withCleanCallingIdentity(
- () -> resultListener.accept(result)));
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ if (resultCode == SATELLITE_ERROR_NONE) {
+ if (resultData.containsKey(KEY_SATELLITE_ENABLED)) {
+ boolean isSatelliteEnabled =
+ resultData.getBoolean(KEY_SATELLITE_ENABLED);
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onResult(isSatelliteEnabled)));
+ } else {
+ loge("KEY_SATELLITE_ENABLED does not exist.");
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onError(
+ new SatelliteException(SATELLITE_REQUEST_FAILED))));
+ }
+ } else {
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onError(new SatelliteException(resultCode))));
+ }
}
};
-
- return telephony.isSatellitePowerOn(mSubId, internalCallback);
+ telephony.requestIsSatelliteEnabled(mSubId, receiver);
} else {
throw new IllegalStateException("telephony service is null.");
}
} catch (RemoteException ex) {
- loge("isSatellitePowerOn() RemoteException:" + ex);
+ loge("requestIsSatelliteEnabled() RemoteException: " + ex);
ex.rethrowFromSystemServer();
}
- return SATELLITE_REQUEST_FAILED;
}
/**
- * Check whether the satellite service is supported on the device.
+ * Request to get whether the satellite service is supported on the device.
*
- * @param executor The executor on which the result listener will be called.
- * @param resultListener Listener with the result if the operation is successful.
- * If this method returns {@link #SATELLITE_ERROR_NONE}, the result
- * listener will return {@code true} if the satellite service is supported
- * and {@code false} otherwise.
+ * @param executor The executor on which the callback will be called.
+ * @param callback The callback object to which the result will be delivered.
+ * If the request is successful, {@link OutcomeReceiver#onResult(Object)}
+ * will return a {@code boolean} with value {@code true} if the satellite
+ * service is supported on the device and {@code false} otherwise.
+ * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
+ * will return a {@link SatelliteException} with the {@link SatelliteError}.
*
- * @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
- *
- * @return The result of the operation.
*/
- @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @SatelliteError public int isSatelliteSupported(
- @NonNull @CallbackExecutor Executor executor,
- @NonNull Consumer<Boolean> resultListener) {
+ public void requestIsSatelliteSupported(@NonNull @CallbackExecutor Executor executor,
+ @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) {
Objects.requireNonNull(executor);
- Objects.requireNonNull(resultListener);
+ Objects.requireNonNull(callback);
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- IBooleanConsumer internalCallback = new IBooleanConsumer.Stub() {
+ ResultReceiver receiver = new ResultReceiver(null) {
@Override
- public void accept(boolean result) {
- executor.execute(() -> Binder.withCleanCallingIdentity(
- () -> resultListener.accept(result)));
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ if (resultCode == SATELLITE_ERROR_NONE) {
+ if (resultData.containsKey(KEY_SATELLITE_SUPPORTED)) {
+ boolean isSatelliteSupported =
+ resultData.getBoolean(KEY_SATELLITE_SUPPORTED);
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onResult(isSatelliteSupported)));
+ } else {
+ loge("KEY_SATELLITE_SUPPORTED does not exist.");
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onError(
+ new SatelliteException(SATELLITE_REQUEST_FAILED))));
+ }
+ } else {
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onError(new SatelliteException(resultCode))));
+ }
}
};
-
- return telephony.isSatelliteSupported(mSubId, internalCallback);
+ telephony.requestIsSatelliteSupported(mSubId, receiver);
} else {
throw new IllegalStateException("telephony service is null.");
}
} catch (RemoteException ex) {
- loge("isSatelliteSupported() RemoteException:" + ex);
+ loge("requestIsSatelliteSupported() RemoteException: " + ex);
ex.rethrowFromSystemServer();
}
- return SATELLITE_REQUEST_FAILED;
}
/**
- * Get the {@link SatelliteCapabilities} with all capabilities of the satellite service.
+ * Request to get the {@link SatelliteCapabilities} of the satellite service.
*
- * @param executor The executor on which the result listener will be called.
- * @param resultListener Listener with the result if the operation is successful.
- * If this method returns {@link #SATELLITE_ERROR_NONE}, the result
- * listener will return the current {@link SatelliteCapabilities}.
+ * @param executor The executor on which the callback will be called.
+ * @param callback The callback object to which the result will be delivered.
+ * If the request is successful, {@link OutcomeReceiver#onResult(Object)}
+ * will return the {@link SatelliteCapabilities} of the satellite service.
+ * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
+ * will return a {@link SatelliteException} with the {@link SatelliteError}.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
- *
- * @return The result of the operation.
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @SatelliteError public int getSatelliteCapabilities(
- @NonNull @CallbackExecutor Executor executor,
- @NonNull Consumer<SatelliteCapabilities> resultListener) {
+ public void requestSatelliteCapabilities(@NonNull @CallbackExecutor Executor executor,
+ @NonNull OutcomeReceiver<SatelliteCapabilities, SatelliteException> callback) {
Objects.requireNonNull(executor);
- Objects.requireNonNull(resultListener);
+ Objects.requireNonNull(callback);
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- ISatelliteCapabilitiesConsumer internalCallback =
- new ISatelliteCapabilitiesConsumer.Stub() {
+ ResultReceiver receiver = new ResultReceiver(null) {
@Override
- public void accept(SatelliteCapabilities result) {
- executor.execute(() -> Binder.withCleanCallingIdentity(
- () -> resultListener.accept(result)));
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ if (resultCode == SATELLITE_ERROR_NONE) {
+ if (resultData.containsKey(KEY_SATELLITE_CAPABILITIES)) {
+ SatelliteCapabilities capabilities =
+ resultData.getParcelable(KEY_SATELLITE_CAPABILITIES,
+ SatelliteCapabilities.class);
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onResult(capabilities)));
+ } else {
+ loge("KEY_SATELLITE_CAPABILITIES does not exist.");
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onError(
+ new SatelliteException(SATELLITE_REQUEST_FAILED))));
+ }
+ } else {
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onError(new SatelliteException(resultCode))));
+ }
}
};
-
- return telephony.getSatelliteCapabilities(mSubId, internalCallback);
+ telephony.requestSatelliteCapabilities(mSubId, receiver);
} else {
throw new IllegalStateException("telephony service is null.");
}
} catch (RemoteException ex) {
- loge("getSatelliteCapabilities() RemoteException:" + ex);
+ loge("requestSatelliteCapabilities() RemoteException: " + ex);
ex.rethrowFromSystemServer();
}
- return SATELLITE_REQUEST_FAILED;
}
/**
@@ -403,28 +497,35 @@
* Satellite position updates are started only on {@link #SATELLITE_ERROR_NONE}.
* All other results indicate that this operation failed.
*
- * @param executor The executor on which the callback will be called.
+ * @param executor The executor on which the callback and error code listener will be called.
+ * @param errorCodeListener Listener for the {@link SatelliteError} result of the operation.
* @param callback The callback to notify of changes in satellite position. This
* SatelliteCallback should implement the interface
* {@link SatelliteCallback.SatellitePositionUpdateListener}.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
- *
- * @return The result of the operation.
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @SatelliteError
- public int startSatellitePositionUpdates(
- @NonNull Executor executor, @NonNull SatelliteCallback callback) {
+ public void startSatellitePositionUpdates(@NonNull @CallbackExecutor Executor executor,
+ @NonNull Consumer<Integer> errorCodeListener, @NonNull SatelliteCallback callback) {
Objects.requireNonNull(executor);
+ Objects.requireNonNull(errorCodeListener);
Objects.requireNonNull(callback);
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
callback.init(executor);
- return telephony.startSatellitePositionUpdates(mSubId, callback.getCallbackStub());
+ IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() -> Binder.withCleanCallingIdentity(
+ () -> errorCodeListener.accept(result)));
+ }
+ };
+ telephony.startSatellitePositionUpdates(mSubId, errorCallback,
+ callback.getCallbackStub());
} else {
throw new IllegalStateException("telephony service is null.");
}
@@ -432,7 +533,6 @@
loge("startSatellitePositionUpdates RemoteException: " + ex);
ex.rethrowFromSystemServer();
}
- return SATELLITE_REQUEST_FAILED;
}
/**
@@ -441,25 +541,35 @@
* Satellite position updates are stopped only on {@link #SATELLITE_ERROR_NONE}.
* All other results indicate that this operation failed.
*
- * @param callback The callback that was passed in {@link
- * #startSatellitePositionUpdates(Executor, SatelliteCallback)}.
+ * @param callback The callback that was passed to
+ * {@link #startSatellitePositionUpdates(Executor, Consumer, SatelliteCallback)}.
+ * @param executor The executor on which the error code listener will be called.
+ * @param errorCodeListener Listener for the {@link SatelliteError} result of the operation.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalArgumentException if the callback is invalid.
* @throws IllegalStateException if the Telephony process is not currently available.
- *
- * @return The result of the operation.
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @SatelliteError
- public int stopSatellitePositionUpdates(
- @NonNull SatelliteCallback callback) {
+ public void stopSatellitePositionUpdates(@NonNull SatelliteCallback callback,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull Consumer<Integer> errorCodeListener) {
Objects.requireNonNull(callback);
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(errorCodeListener);
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.stopSatellitePositionUpdates(mSubId, callback.getCallbackStub());
+ IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() -> Binder.withCleanCallingIdentity(
+ () -> errorCodeListener.accept(result)));
+ }
+ };
+ telephony.stopSatellitePositionUpdates(mSubId, errorCallback,
+ callback.getCallbackStub());
// TODO: Notify SmsHandler that pointing UI stopped
} else {
throw new IllegalStateException("telephony service is null.");
@@ -468,89 +578,97 @@
loge("stopSatellitePositionUpdates RemoteException: " + ex);
ex.rethrowFromSystemServer();
}
- return SATELLITE_REQUEST_FAILED;
}
/**
- * Get maximum number of characters per text message on satellite.
- * @param executor - The executor on which the result listener will be called.
- * @param resultListener - Listener that will be called when the operation is successful.
- * If this method returns {@link #SATELLITE_ERROR_NONE}, listener
- * will be called with maximum characters limit.
+ * Request to get the maximum number of characters per text message on satellite.
+ *
+ * @param executor The executor on which the callback will be called.
+ * @param callback The callback object to which the result will be delivered.
+ * If the request is successful, {@link OutcomeReceiver#onResult(Object)}
+ * will return the maximum number of characters per text message on satellite.
+ * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
- *
- * @return The result of the operation.
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @SatelliteError
- public int getMaxCharactersPerSatelliteTextMessage(@NonNull @CallbackExecutor Executor executor,
- @NonNull Consumer<Integer> resultListener) {
+ public void requestMaxCharactersPerSatelliteTextMessage(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OutcomeReceiver<Integer, SatelliteException> callback) {
Objects.requireNonNull(executor);
- Objects.requireNonNull(resultListener);
+ Objects.requireNonNull(callback);
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() {
+ ResultReceiver receiver = new ResultReceiver(null) {
@Override
- public void accept(int result) {
- executor.execute(() -> Binder.withCleanCallingIdentity(
- () -> resultListener.accept(result)));
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ if (resultCode == SATELLITE_ERROR_NONE) {
+ if (resultData.containsKey(KEY_MAX_CHARACTERS_PER_SATELLITE_TEXT)) {
+ int maxCharacters =
+ resultData.getInt(KEY_MAX_CHARACTERS_PER_SATELLITE_TEXT);
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onResult(maxCharacters)));
+ } else {
+ loge("KEY_MAX_CHARACTERS_PER_SATELLITE_TEXT does not exist.");
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onError(
+ new SatelliteException(SATELLITE_REQUEST_FAILED))));
+ }
+ } else {
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onError(new SatelliteException(resultCode))));
+ }
}
};
-
- return telephony.getMaxCharactersPerSatelliteTextMessage(mSubId, internalCallback);
+ telephony.requestMaxCharactersPerSatelliteTextMessage(mSubId, receiver);
} else {
throw new IllegalStateException("telephony service is null.");
}
} catch (RemoteException ex) {
- loge("getMaxCharactersPerSatelliteTextMessage() RemoteException:" + ex);
+ loge("requestMaxCharactersPerSatelliteTextMessage() RemoteException: " + ex);
ex.rethrowFromSystemServer();
}
- return SATELLITE_REQUEST_FAILED;
}
/**
- * Register the subscription with a satellite provider. This is needed if the provider allows
- * dynamic registration.
+ * Provision the device with a satellite provider.
+ * This is needed if the provider allows dynamic registration.
*
- * @param features List of features to be provisioned.
- * @param executor The optional executor to run callbacks on.
- * @param callback The optional callback to get the error code of the request.
+ * @param token The security token of the device/subscription to be provisioned.
* @param cancellationSignal The optional signal used by the caller to cancel the provision
* request. Even when the cancellation is signaled, Telephony will
* still trigger the callback to return the result of this request.
+ * @param executor The executor on which the error code listener will be called.
+ * @param errorCodeListener Listener for the {@link SatelliteError} result of the operation.
+ *
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- public void provisionSatelliteService(
- @NonNull @SatelliteImplBase.Feature int[] features,
- @Nullable @CallbackExecutor Executor executor,
- @SatelliteError @Nullable Consumer<Integer> callback,
- @Nullable CancellationSignal cancellationSignal) {
- Objects.requireNonNull(features);
+ public void provisionSatelliteService(@NonNull String token,
+ @Nullable CancellationSignal cancellationSignal,
+ @NonNull @CallbackExecutor Executor executor,
+ @SatelliteError @NonNull Consumer<Integer> errorCodeListener) {
+ Objects.requireNonNull(token);
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(errorCodeListener);
ICancellationSignal cancelRemote = null;
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- IIntegerConsumer callbackStub = new IIntegerConsumer.Stub() {
+ IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
@Override
public void accept(int result) {
- if (executor == null || callback == null) {
- logd("provisionSatelliteService: executor and/or callback is null");
- return;
- }
- Binder.withCleanCallingIdentity(() -> {
- executor.execute(() -> callback.accept(result));
- });
+ executor.execute(() -> Binder.withCleanCallingIdentity(
+ () -> errorCodeListener.accept(result)));
}
};
- cancelRemote = telephony.provisionSatelliteService(mSubId, features, callbackStub);
+ cancelRemote = telephony.provisionSatelliteService(mSubId, token, errorCallback);
} else {
throw new IllegalStateException("telephony service is null.");
}
@@ -566,27 +684,36 @@
/**
* Register for the satellite provision state change.
*
- * @param executor - The executor on which the callback will be called.
+ * @param executor The executor on which the callback and error code listener will be called.
+ * @param errorCodeListener Listener for the {@link SatelliteError} result of the operation.
* @param callback The callback to handle the satellite provision state changed event. This
* SatelliteCallback should implement the interface
* {@link SatelliteCallback.SatelliteProvisionStateListener}.
- * @return The error code of the request.
+ *
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @SatelliteError
- public int registerForSatelliteProvisionStateChanged(
- @NonNull Executor executor, @NonNull SatelliteCallback callback) {
+ public void registerForSatelliteProvisionStateChanged(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull Consumer<Integer> errorCodeListener, @NonNull SatelliteCallback callback) {
Objects.requireNonNull(executor);
+ Objects.requireNonNull(errorCodeListener);
Objects.requireNonNull(callback);
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
callback.init(executor);
- return telephony.registerForSatelliteProvisionStateChanged(
- mSubId, callback.getCallbackStub());
+ IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() -> Binder.withCleanCallingIdentity(
+ () -> errorCodeListener.accept(result)));
+ }
+ };
+ telephony.registerForSatelliteProvisionStateChanged(
+ mSubId, errorCallback, callback.getCallbackStub());
} else {
throw new IllegalStateException("telephony service is null.");
}
@@ -594,33 +721,46 @@
loge("registerForSatelliteProvisionStateChanged RemoteException: " + ex);
ex.rethrowFromSystemServer();
}
- return SATELLITE_REQUEST_FAILED;
}
/**
* Unregister for the satellite provision state change.
*
* @param callback The callback that was passed to
- * {@link #registerForSatelliteProvisionStateChanged(Executor, SatelliteCallback)}
- * @return The error code of the request.
+ * {@link #registerForSatelliteProvisionStateChanged(Executor, Consumer, SatelliteCallback)}.
+ * @param executor The executor on which the error code listener will be called.
+ * @param errorCodeListener Listener for the {@link SatelliteError} result of the operation.
+ *
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @SatelliteError
- public int unregisterForSatelliteProvisionStateChanged(@NonNull SatelliteCallback callback) {
+ public void unregisterForSatelliteProvisionStateChanged(@NonNull SatelliteCallback callback,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull Consumer<Integer> errorCodeListener) {
Objects.requireNonNull(callback);
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(errorCodeListener);
if (callback.getCallbackStub() == null) {
loge("unregisterForSatelliteProvisionStateChanged: callbackStub is null");
- return SATELLITE_INVALID_ARGUMENTS;
+ executor.execute(() -> Binder.withCleanCallingIdentity(
+ () -> errorCodeListener.accept(SATELLITE_INVALID_ARGUMENTS)));
+ return;
}
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.unregisterForSatelliteProvisionStateChanged(
- mSubId, callback.getCallbackStub());
+ IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() -> Binder.withCleanCallingIdentity(
+ () -> errorCodeListener.accept(result)));
+ }
+ };
+ telephony.unregisterForSatelliteProvisionStateChanged(mSubId, errorCallback,
+ callback.getCallbackStub());
} else {
throw new IllegalStateException("telephony service is null.");
}
@@ -628,46 +768,60 @@
loge("unregisterForSatelliteProvisionStateChanged RemoteException: " + ex);
ex.rethrowFromSystemServer();
}
- return SATELLITE_REQUEST_FAILED;
}
/**
- * Get the list of provisioned satellite features.
+ * Request to get whether this device is provisioned with a satellite provider.
*
- * @param executor The executor to run callbacks on.
- * @param resultListener The callback to get the list of provisioned features when the request
- * returns success result.
- * @return The error code of the request.
+ * @param executor The executor on which the callback will be called.
+ * @param callback The callback object to which the result will be delivered.
+ * If the request is successful, {@link OutcomeReceiver#onResult(Object)}
+ * will return a {@code boolean} with value {@code true} if the device is
+ * provisioned with a satellite provider and {@code false} otherwise.
+ * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
+ * will return a {@link SatelliteException} with the {@link SatelliteError}.
+ *
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @SatelliteError
- public int getProvisionedSatelliteFeatures(
- @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<int[]> resultListener) {
- Objects.requireNonNull(resultListener);
+ public void requestIsSatelliteProvisioned(@NonNull @CallbackExecutor Executor executor,
+ @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) {
Objects.requireNonNull(executor);
+ Objects.requireNonNull(callback);
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- IIntArrayConsumer callbackStub = new IIntArrayConsumer.Stub() {
+ ResultReceiver receiver = new ResultReceiver(null) {
@Override
- public void accept(int[] result) {
- Binder.withCleanCallingIdentity(() -> {
- executor.execute(() -> resultListener.accept(result));
- });
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ if (resultCode == SATELLITE_ERROR_NONE) {
+ if (resultData.containsKey(KEY_SATELLITE_PROVISIONED)) {
+ boolean isSatelliteProvisioned =
+ resultData.getBoolean(KEY_SATELLITE_PROVISIONED);
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onResult(isSatelliteProvisioned)));
+ } else {
+ loge("KEY_SATELLITE_PROVISIONED does not exist.");
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onError(
+ new SatelliteException(SATELLITE_REQUEST_FAILED))));
+ }
+ } else {
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onError(new SatelliteException(resultCode))));
+ }
}
};
- return telephony.getProvisionedSatelliteFeatures(mSubId, callbackStub);
+ telephony.requestIsSatelliteProvisioned(mSubId, receiver);
} else {
throw new IllegalStateException("telephony service is null.");
}
} catch (RemoteException ex) {
- loge("getProvisionedSatelliteFeatures() RemoteException:" + ex);
+ loge("requestIsSatelliteProvisioned() RemoteException: " + ex);
ex.rethrowFromSystemServer();
}
- return SATELLITE_REQUEST_FAILED;
}
private static ITelephony getITelephony() {
diff --git a/telephony/java/com/android/internal/telephony/IIntArrayConsumer.aidl b/telephony/java/com/android/internal/telephony/IIntArrayConsumer.aidl
deleted file mode 100644
index c208755..0000000
--- a/telephony/java/com/android/internal/telephony/IIntArrayConsumer.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony;
-
-// Copies consumer pattern for an operation that requires an int array result from another
-// process to finish.
-oneway interface IIntArrayConsumer {
- void accept(in int[] result);
-}
\ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index baf45cd..07deead 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -68,7 +68,6 @@
import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.telephony.ims.aidl.IRcsConfigCallback;
import android.telephony.satellite.ISatelliteStateListener;
-import android.telephony.satellite.ISatelliteCapabilitiesConsumer;
import android.telephony.satellite.SatelliteCapabilities;
import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.telephony.CellNetworkScanResult;
@@ -76,7 +75,6 @@
import com.android.internal.telephony.ICallForwardingInfoCallback;
import com.android.internal.telephony.IccLogicalChannelRequest;
import com.android.internal.telephony.IImsStateCallback;
-import com.android.internal.telephony.IIntArrayConsumer;
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.INumberVerificationCallback;
import com.android.internal.telephony.OperatorInfo;
@@ -2704,74 +2702,129 @@
void getCarrierRestrictionStatus(IIntegerConsumer internalCallback, String packageName);
/**
- * Power on or off the satellite modem.
+ * Enable or disable the satellite modem.
+ *
+ * @param subId The subId of the subscription to enable or disable the satellite modem for.
+ * @param enable True to enable the satellite modem and false to disable.
+ * @param callback The callback to get the error code of the request.
*/
- int setSatellitePower(int subId, boolean powerOn);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ void setSatelliteEnabled(int subId, boolean enable, in IIntegerConsumer callback);
/**
- * Check whether the satellite modem is powered on.
+ * Request to get whether the satellite modem is enabled.
+ *
+ * @param subId The subId of the subscription to request whether satellite is enabled for.
+ * @param receiver Result receiver to get the error code of the request and whether the
+ * satellite modem is enabled.
*/
- int isSatellitePowerOn(int subId, IBooleanConsumer internalCallback);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ void requestIsSatelliteEnabled(int subId, in ResultReceiver receiver);
/**
- * Check whether the satellite service is supported on the device.
+ * Request to get whether the satellite service is supported on the device.
+ *
+ * @param subId The subId of the subscription to check whether satellite is supported for.
+ * @param receiver Result receiver to get the error code of the request and whether the
+ * satellite service is supported on the device.
*/
- int isSatelliteSupported(int subId, IBooleanConsumer internalCallback);
+ void requestIsSatelliteSupported(int subId, in ResultReceiver receiver);
/**
- * Get the capabilities of the satellite service.
+ * Request to get the capabilities of the satellite service.
+ *
+ * @param subId The subId of the subscription to get the capabilities for.
+ * @param receiver Result receiver to get the error code of the request and the requested
+ * capabilities of the satellite service.
*/
- int getSatelliteCapabilities(int subId, ISatelliteCapabilitiesConsumer internalCallback);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ void requestSatelliteCapabilities(int subId, in ResultReceiver receiver);
/**
* Start receiving satellite pointing updates.
+ *
+ * @param subId The subId of the subscription to stop satellite position updates for.
+ * @param errorCallback The callback to get the error code of the request.
+ * @param callback The callback to handle position updates.
*/
- int startSatellitePositionUpdates(int subId, in ISatelliteStateListener callback);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ void startSatellitePositionUpdates(int subId, in IIntegerConsumer errorCallback,
+ in ISatelliteStateListener callback);
/**
* Stop receiving satellite pointing updates.
+ *
+ * @param subId The subId of the subscritpion to stop satellite position updates for.
+ * @param errorCallback The callback to get the error code of the request.
+ * @param callback The callback that was passed to startSatellitePositionUpdates.
*/
- int stopSatellitePositionUpdates(int subId, ISatelliteStateListener callback);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ void stopSatellitePositionUpdates(int subId, in IIntegerConsumer errorCallback,
+ in ISatelliteStateListener callback);
/**
- * Get maximum number of characters per text message on satellite.
+ * Request to get the maximum number of characters per text message on satellite.
+ *
+ * @param subId The subId to get the maximum number of characters for.
+ * @param receiver Result receiver to get the error code of the request and the requested
+ * maximum number of characters per text message on satellite.
*/
- int getMaxCharactersPerSatelliteTextMessage(int subId, IIntegerConsumer internalCallback);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ void requestMaxCharactersPerSatelliteTextMessage(int subId, in ResultReceiver receiver);
/**
* Register the subscription with a satellite provider.
* This is needed to register the subscription if the provider allows dynamic registration.
*
* @param subId The subId of the subscription to be provisioned.
- * @param features List of features to be provisioned.
+ * @param token The security token of the device/subscription to be provisioned.
* @param callback The callback to get the error code of the request.
+ *
* @return The signal transport used by callers to cancel the provision request.
*/
- ICancellationSignal provisionSatelliteService(int subId, in int[] features,
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ ICancellationSignal provisionSatelliteService(int subId, in String token,
in IIntegerConsumer callback);
/**
* Register for the satellite provision state change.
*
- * @param subId The subId of the subscription to be provisioned.
+ * @param subId The subId of the subscription to register for provision state changes for.
+ * @param errorCallback The callback to get the error code of the request.
* @param callback The callback to handle the satellite provision state changed event.
*/
- int registerForSatelliteProvisionStateChanged(int subId, ISatelliteStateListener callback);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ void registerForSatelliteProvisionStateChanged(int subId,
+ in IIntegerConsumer errorCallback, in ISatelliteStateListener callback);
/**
* Unregister for the satellite provision state change.
*
* @param subId The subId of the subscription associated with the satellite service.
- * @param callback The callback that was passed to
- * registerForSatelliteProvisionStateChanged.
+ * @param errorCallback The callback to get the error code of the request.
+ * @param callback The callback that was passed to registerForSatelliteProvisionStateChanged.
*/
- int unregisterForSatelliteProvisionStateChanged(int subId, ISatelliteStateListener callback);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ void unregisterForSatelliteProvisionStateChanged(int subId,
+ in IIntegerConsumer errorCallback, in ISatelliteStateListener callback);
/**
- * Get the list of provisioned satellite features.
+ * Request to get whether the device is provisioned with a satellite provider.
*
- * @param subId The subId of the subscription to be provisioned.
- * @param callback The callback to get the list of provisioned satellite features.
+ * @param subId The subId of the subscription to get whether the device is provisioned for.
+ * @param receiver Result receiver to get the error code of the request and whether the
+ * device is provisioned with a satellite provider.
*/
- int getProvisionedSatelliteFeatures(int subId, IIntArrayConsumer callback);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ void requestIsSatelliteProvisioned(int subId, in ResultReceiver receiver);
}
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index aa337e5..0d6dc35 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -50,6 +50,7 @@
],
target: {
windows: {
+ compile_multilib: "64",
enabled: true,
cflags: ["-Wno-maybe-uninitialized"],
ldflags: ["-static"],
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java b/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
index a40049b..10ef066 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
@@ -101,13 +101,13 @@
@Override
public void registerCallback(ISharedConnectivityCallback callback) {
checkPermissions();
- mHandler.post(() -> registerCallback(callback));
+ mHandler.post(() -> onRegisterCallback(callback));
}
@Override
public void unregisterCallback(ISharedConnectivityCallback callback) {
checkPermissions();
- mHandler.post(() -> unregisterCallback(callback));
+ mHandler.post(() -> onUnregisterCallback(callback));
}
@Override
@@ -147,7 +147,7 @@
};
}
- private void registerCallback(ISharedConnectivityCallback callback) {
+ private void onRegisterCallback(ISharedConnectivityCallback callback) {
// Listener gets triggered on first register using cashed data
if (!notifyTetherNetworkUpdate(callback) || !notifyKnownNetworkUpdate(callback)
|| !notifySettingsStateUpdate(callback)
@@ -167,7 +167,7 @@
}
}
- private void unregisterCallback(ISharedConnectivityCallback callback) {
+ private void onUnregisterCallback(ISharedConnectivityCallback callback) {
DeathRecipient deathRecipient = mDeathRecipientMap.get(callback);
if (deathRecipient != null) {
callback.asBinder().unlinkToDeath(deathRecipient, 0);