Merge "Require an app activity for launching UIs."
diff --git a/cmds/idmap2/self_targeting/SelfTargeting.cpp b/cmds/idmap2/self_targeting/SelfTargeting.cpp
index 20aa7d3..a8aa033 100644
--- a/cmds/idmap2/self_targeting/SelfTargeting.cpp
+++ b/cmds/idmap2/self_targeting/SelfTargeting.cpp
@@ -38,9 +38,10 @@
constexpr const mode_t kIdmapFilePermission = S_IRUSR | S_IWUSR; // u=rw-, g=---, o=---
extern "C" bool
-CreateFrroFile(std::string& out_err_result, std::string& packageName, std::string& overlayName,
- std::string& targetPackageName, std::optional<std::string>& targetOverlayable,
- std::vector<FabricatedOverlayEntryParameters>& entries_params,
+CreateFrroFile(std::string& out_err_result, const std::string& packageName,
+ const std::string& overlayName, const std::string& targetPackageName,
+ const std::optional<std::string>& targetOverlayable,
+ const std::vector<FabricatedOverlayEntryParameters>& entries_params,
const std::string& frro_file_path) {
android::idmap2::FabricatedOverlay::Builder builder(packageName, overlayName,
targetPackageName);
@@ -90,9 +91,46 @@
return true;
}
+static PolicyBitmask GetFulfilledPolicy(const bool isSystem, const bool isVendor,
+ const bool isProduct, const bool isTargetSignature,
+ const bool isOdm, const bool isOem) {
+ auto fulfilled_policy = static_cast<PolicyBitmask>(PolicyFlags::PUBLIC);
+
+ if (isSystem) {
+ fulfilled_policy |= PolicyFlags::SYSTEM_PARTITION;
+ }
+ if (isVendor) {
+ fulfilled_policy |= PolicyFlags::VENDOR_PARTITION;
+ }
+ if (isProduct) {
+ fulfilled_policy |= PolicyFlags::PRODUCT_PARTITION;
+ }
+ if (isOdm) {
+ fulfilled_policy |= PolicyFlags::ODM_PARTITION;
+ }
+ if (isOem) {
+ fulfilled_policy |= PolicyFlags::OEM_PARTITION;
+ }
+ if (isTargetSignature) {
+ fulfilled_policy |= PolicyFlags::SIGNATURE;
+ }
+
+ // Not support actor_signature and config_overlay_signature
+ fulfilled_policy &=
+ ~(PolicyFlags::ACTOR_SIGNATURE | PolicyFlags::CONFIG_SIGNATURE);
+
+ ALOGV(
+ "fulfilled_policy = 0x%08x, isSystem = %d, isVendor = %d, isProduct = %d,"
+ " isTargetSignature = %d, isOdm = %d, isOem = %d,",
+ fulfilled_policy, isSystem, isVendor, isProduct, isTargetSignature, isOdm, isOem);
+ return fulfilled_policy;
+}
+
extern "C" bool
CreateIdmapFile(std::string& out_err, const std::string& targetPath, const std::string& overlayPath,
- const std::string& idmapPath, const std::string& overlayName) {
+ const std::string& idmapPath, const std::string& overlayName,
+ const bool isSystem, const bool isVendor, const bool isProduct,
+ const bool isTargetSignature, const bool isOdm, const bool isOem) {
// idmap files are mapped with mmap in libandroidfw. Deleting and recreating the idmap
// guarantees that existing memory maps will continue to be valid and unaffected. The file must
// be deleted before attempting to create the idmap, so that if idmap creation fails, the
@@ -114,14 +152,11 @@
}
// Overlay self target process. Only allow self-targeting types.
- const auto fulfilled_policies = static_cast<PolicyBitmask>(
- PolicyFlags::PUBLIC | PolicyFlags::SYSTEM_PARTITION | PolicyFlags::VENDOR_PARTITION |
- PolicyFlags::PRODUCT_PARTITION | PolicyFlags::SIGNATURE | PolicyFlags::ODM_PARTITION |
- PolicyFlags::OEM_PARTITION | PolicyFlags::ACTOR_SIGNATURE |
- PolicyFlags::CONFIG_SIGNATURE);
+ const auto fulfilled_policies = GetFulfilledPolicy(isSystem, isVendor, isProduct,
+ isTargetSignature, isOdm, isOem);
const auto idmap = Idmap::FromContainers(**target, **overlay, overlayName,
- fulfilled_policies, false /* enforce_overlayable */);
+ fulfilled_policies, true /* enforce_overlayable */);
if (!idmap) {
out_err = base::StringPrintf("Failed to create idmap because of %s",
idmap.GetErrorMessage().c_str());
diff --git a/core/api/current.txt b/core/api/current.txt
index e83214c..dab32d2 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -39328,6 +39328,149 @@
}
+package android.service.credentials {
+
+ public final class Action implements android.os.Parcelable {
+ ctor public Action(@NonNull android.app.slice.Slice, @NonNull android.app.PendingIntent);
+ method public int describeContents();
+ method @NonNull public android.app.PendingIntent getPendingIntent();
+ method @NonNull public android.app.slice.Slice getSlice();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.Action> CREATOR;
+ }
+
+ public final class BeginCreateCredentialRequest implements android.os.Parcelable {
+ ctor public BeginCreateCredentialRequest(@NonNull String, @NonNull String, @NonNull android.os.Bundle);
+ method public int describeContents();
+ method @NonNull public String getCallingPackage();
+ method @NonNull public android.os.Bundle getData();
+ method @NonNull public String getType();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.BeginCreateCredentialRequest> CREATOR;
+ }
+
+ public final class BeginCreateCredentialResponse implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<android.service.credentials.CreateEntry> getCreateEntries();
+ method @Nullable public android.service.credentials.CreateEntry getRemoteCreateEntry();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.BeginCreateCredentialResponse> CREATOR;
+ }
+
+ public static final class BeginCreateCredentialResponse.Builder {
+ ctor public BeginCreateCredentialResponse.Builder();
+ method @NonNull public android.service.credentials.BeginCreateCredentialResponse.Builder addCreateEntry(@NonNull android.service.credentials.CreateEntry);
+ method @NonNull public android.service.credentials.BeginCreateCredentialResponse build();
+ method @NonNull public android.service.credentials.BeginCreateCredentialResponse.Builder setCreateEntries(@NonNull java.util.List<android.service.credentials.CreateEntry>);
+ method @NonNull public android.service.credentials.BeginCreateCredentialResponse.Builder setRemoteCreateEntry(@Nullable android.service.credentials.CreateEntry);
+ }
+
+ public final class CreateCredentialRequest implements android.os.Parcelable {
+ ctor public CreateCredentialRequest(@NonNull String, @NonNull String, @NonNull android.os.Bundle);
+ method public int describeContents();
+ method @NonNull public String getCallingPackage();
+ method @NonNull public android.os.Bundle getData();
+ method @NonNull public String getType();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.CreateCredentialRequest> CREATOR;
+ }
+
+ public final class CreateEntry implements android.os.Parcelable {
+ ctor public CreateEntry(@NonNull android.app.slice.Slice, @NonNull android.app.PendingIntent);
+ method public int describeContents();
+ method @NonNull public android.app.PendingIntent getPendingIntent();
+ method @NonNull public android.app.slice.Slice getSlice();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.CreateEntry> CREATOR;
+ }
+
+ public final class CredentialEntry implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public android.credentials.Credential getCredential();
+ method @Nullable public android.app.PendingIntent getPendingIntent();
+ method @NonNull public android.app.slice.Slice getSlice();
+ method @NonNull public String getType();
+ method public boolean isAutoSelectAllowed();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.CredentialEntry> CREATOR;
+ }
+
+ public static final class CredentialEntry.Builder {
+ ctor public CredentialEntry.Builder(@NonNull String, @NonNull android.app.slice.Slice, @NonNull android.app.PendingIntent);
+ ctor public CredentialEntry.Builder(@NonNull String, @NonNull android.app.slice.Slice, @NonNull android.credentials.Credential);
+ method @NonNull public android.service.credentials.CredentialEntry build();
+ method @NonNull public android.service.credentials.CredentialEntry.Builder setAutoSelectAllowed(@NonNull boolean);
+ }
+
+ public class CredentialProviderException extends java.lang.Exception {
+ ctor public CredentialProviderException(int, @NonNull String, @NonNull Throwable);
+ ctor public CredentialProviderException(int, @NonNull String);
+ ctor public CredentialProviderException(int, @NonNull Throwable);
+ ctor public CredentialProviderException(int);
+ method public int getErrorCode();
+ field public static final int ERROR_UNKNOWN = 0; // 0x0
+ }
+
+ public abstract class CredentialProviderService extends android.app.Service {
+ ctor public CredentialProviderService();
+ method public abstract void onBeginCreateCredential(@NonNull android.service.credentials.BeginCreateCredentialRequest, @NonNull android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<android.service.credentials.BeginCreateCredentialResponse,android.service.credentials.CredentialProviderException>);
+ method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
+ method public abstract void onGetCredentials(@NonNull android.service.credentials.GetCredentialsRequest, @NonNull android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<android.service.credentials.GetCredentialsResponse,android.service.credentials.CredentialProviderException>);
+ field public static final String CAPABILITY_META_DATA_KEY = "android.credentials.capabilities";
+ field public static final String EXTRA_CREATE_CREDENTIAL_REQUEST = "android.service.credentials.extra.CREATE_CREDENTIAL_REQUEST";
+ field public static final String EXTRA_CREATE_CREDENTIAL_RESULT = "android.service.credentials.extra.CREATE_CREDENTIAL_RESULT";
+ field public static final String EXTRA_CREDENTIAL_RESULT = "android.service.credentials.extra.CREDENTIAL_RESULT";
+ field public static final String EXTRA_ERROR = "android.service.credentials.extra.ERROR";
+ field public static final String EXTRA_GET_CREDENTIALS_CONTENT_RESULT = "android.service.credentials.extra.GET_CREDENTIALS_CONTENT_RESULT";
+ field public static final String SERVICE_INTERFACE = "android.service.credentials.CredentialProviderService";
+ }
+
+ public final class CredentialsResponseContent implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<android.service.credentials.Action> getActions();
+ method @NonNull public java.util.List<android.service.credentials.CredentialEntry> getCredentialEntries();
+ method @Nullable public android.service.credentials.CredentialEntry getRemoteCredentialEntry();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.CredentialsResponseContent> CREATOR;
+ }
+
+ public static final class CredentialsResponseContent.Builder {
+ ctor public CredentialsResponseContent.Builder();
+ method @NonNull public android.service.credentials.CredentialsResponseContent.Builder addAction(@NonNull android.service.credentials.Action);
+ method @NonNull public android.service.credentials.CredentialsResponseContent.Builder addCredentialEntry(@NonNull android.service.credentials.CredentialEntry);
+ method @NonNull public android.service.credentials.CredentialsResponseContent build();
+ method @NonNull public android.service.credentials.CredentialsResponseContent.Builder setActions(@NonNull java.util.List<android.service.credentials.Action>);
+ method @NonNull public android.service.credentials.CredentialsResponseContent.Builder setCredentialEntries(@NonNull java.util.List<android.service.credentials.CredentialEntry>);
+ method @NonNull public android.service.credentials.CredentialsResponseContent.Builder setRemoteCredentialEntry(@Nullable android.service.credentials.CredentialEntry);
+ }
+
+ public final class GetCredentialsRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public String getCallingPackage();
+ method @NonNull public java.util.List<android.credentials.GetCredentialOption> getGetCredentialOptions();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.GetCredentialsRequest> CREATOR;
+ }
+
+ public static final class GetCredentialsRequest.Builder {
+ ctor public GetCredentialsRequest.Builder(@NonNull String);
+ method @NonNull public android.service.credentials.GetCredentialsRequest.Builder addGetCredentialOption(@NonNull android.credentials.GetCredentialOption);
+ method @NonNull public android.service.credentials.GetCredentialsRequest build();
+ method @NonNull public android.service.credentials.GetCredentialsRequest.Builder setGetCredentialOptions(@NonNull java.util.List<android.credentials.GetCredentialOption>);
+ }
+
+ public final class GetCredentialsResponse implements android.os.Parcelable {
+ method @NonNull public static android.service.credentials.GetCredentialsResponse createWithAuthentication(@NonNull android.service.credentials.Action);
+ method @NonNull public static android.service.credentials.GetCredentialsResponse createWithResponseContent(@NonNull android.service.credentials.CredentialsResponseContent);
+ method public int describeContents();
+ method @Nullable public android.service.credentials.Action getAuthenticationAction();
+ method @Nullable public android.service.credentials.CredentialsResponseContent getCredentialsResponseContent();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.GetCredentialsResponse> CREATOR;
+ }
+
+}
+
package android.service.dreams {
public class DreamService extends android.app.Service implements android.view.Window.Callback {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index eac990d..802e614 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -12818,14 +12818,14 @@
method @NonNull public android.telephony.BarringInfo createLocationInfoSanitizedCopy();
}
- @Deprecated public final class CallAttributes implements android.os.Parcelable {
- ctor @Deprecated public CallAttributes(@NonNull android.telephony.PreciseCallState, int, @NonNull android.telephony.CallQuality);
- method @Deprecated public int describeContents();
- method @Deprecated @NonNull public android.telephony.CallQuality getCallQuality();
- method @Deprecated public int getNetworkType();
- method @Deprecated @NonNull public android.telephony.PreciseCallState getPreciseCallState();
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallAttributes> CREATOR;
+ public final class CallAttributes implements android.os.Parcelable {
+ ctor public CallAttributes(@NonNull android.telephony.PreciseCallState, int, @NonNull android.telephony.CallQuality);
+ method public int describeContents();
+ method @NonNull public android.telephony.CallQuality getCallQuality();
+ method public int getNetworkType();
+ method @NonNull public android.telephony.PreciseCallState getPreciseCallState();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallAttributes> CREATOR;
}
public final class CallForwardingInfo implements android.os.Parcelable {
@@ -12905,28 +12905,6 @@
method @NonNull public android.telephony.CallQuality.Builder setUplinkCallQualityLevel(int);
}
- public final class CallState implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public android.telephony.CallQuality getCallQuality();
- method public int getCallState();
- method public int getImsCallServiceType();
- method @Nullable public String getImsCallSessionId();
- method public int getImsCallType();
- method public int getNetworkType();
- method public void writeToParcel(@Nullable android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallState> CREATOR;
- }
-
- public static final class CallState.Builder {
- ctor public CallState.Builder(int);
- method @NonNull public android.telephony.CallState build();
- method @NonNull public android.telephony.CallState.Builder setCallQuality(@Nullable android.telephony.CallQuality);
- method @NonNull public android.telephony.CallState.Builder setImsCallServiceType(int);
- method @NonNull public android.telephony.CallState.Builder setImsCallSessionId(@Nullable String);
- method @NonNull public android.telephony.CallState.Builder setImsCallType(int);
- method @NonNull public android.telephony.CallState.Builder setNetworkType(int);
- }
-
public class CarrierConfigManager {
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultCarrierServicePackageName();
method @NonNull public static android.os.PersistableBundle getDefaultConfig();
@@ -13677,8 +13655,7 @@
}
public static interface TelephonyCallback.CallAttributesListener {
- method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public default void onCallAttributesChanged(@NonNull android.telephony.CallAttributes);
- method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public default void onCallStatesChanged(@NonNull java.util.List<android.telephony.CallState>);
+ method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onCallAttributesChanged(@NonNull android.telephony.CallAttributes);
}
public static interface TelephonyCallback.DataEnabledListener {
@@ -14779,7 +14756,6 @@
field public static final int CALL_RESTRICT_CAUSE_HD = 3; // 0x3
field public static final int CALL_RESTRICT_CAUSE_NONE = 0; // 0x0
field public static final int CALL_RESTRICT_CAUSE_RAT = 1; // 0x1
- field public static final int CALL_TYPE_NONE = 0; // 0x0
field public static final int CALL_TYPE_VIDEO_N_VOICE = 3; // 0x3
field public static final int CALL_TYPE_VOICE = 2; // 0x2
field public static final int CALL_TYPE_VOICE_N_VIDEO = 1; // 0x1
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 5aa8f1f..884870b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -6426,23 +6426,28 @@
}
private void handleTrimMemory(int level) {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "trimMemory");
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "trimMemory: " + level);
+ }
if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level);
- if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
- PropertyInvalidatedCache.onTrimMemory();
- }
+ try {
+ if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
+ PropertyInvalidatedCache.onTrimMemory();
+ }
- final ArrayList<ComponentCallbacks2> callbacks =
- collectComponentCallbacks(true /* includeUiContexts */);
+ final ArrayList<ComponentCallbacks2> callbacks =
+ collectComponentCallbacks(true /* includeUiContexts */);
- final int N = callbacks.size();
- for (int i = 0; i < N; i++) {
- callbacks.get(i).onTrimMemory(level);
+ final int N = callbacks.size();
+ for (int i = 0; i < N; i++) {
+ callbacks.get(i).onTrimMemory(level);
+ }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
WindowManagerGlobal.getInstance().trimMemory(level);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
if (SystemProperties.getInt("debug.am.run_gc_trim_level", Integer.MAX_VALUE) <= level) {
unscheduleGcIdler();
diff --git a/core/java/android/service/credentials/Action.java b/core/java/android/service/credentials/Action.java
index 553a324..7757081 100644
--- a/core/java/android/service/credentials/Action.java
+++ b/core/java/android/service/credentials/Action.java
@@ -27,8 +27,6 @@
/**
* An action defined by the provider that intents into the provider's app for specific
* user actions.
- *
- * @hide
*/
public final class Action implements Parcelable {
/** Slice object containing display content to be displayed with this action on the UI. */
@@ -39,6 +37,13 @@
/**
* Constructs an action to be displayed on the UI.
*
+ * <p> Actions must be used for any provider related operations, such as opening the provider
+ * app, intenting straight into certain app activities like 'manage credentials', top
+ * level authentication before displaying any content etc.
+ *
+ * <p> See details on usage of {@code Action} for various actionable entries in
+ * {@link BeginCreateCredentialResponse} and {@link GetCredentialsResponse}.
+ *
* @param slice the display content to be displayed on the UI, along with this action
* @param pendingIntent the intent to be invoked when the user selects this action
*/
diff --git a/core/java/android/service/credentials/BeginCreateCredentialRequest.aidl b/core/java/android/service/credentials/BeginCreateCredentialRequest.aidl
new file mode 100644
index 0000000..30cab8d
--- /dev/null
+++ b/core/java/android/service/credentials/BeginCreateCredentialRequest.aidl
@@ -0,0 +1,3 @@
+package android.service.credentials;
+
+parcelable BeginCreateCredentialRequest;
\ No newline at end of file
diff --git a/core/java/android/service/credentials/BeginCreateCredentialRequest.java b/core/java/android/service/credentials/BeginCreateCredentialRequest.java
new file mode 100644
index 0000000..1918d8c
--- /dev/null
+++ b/core/java/android/service/credentials/BeginCreateCredentialRequest.java
@@ -0,0 +1,102 @@
+/*
+ * 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 android.service.credentials;
+
+import android.annotation.NonNull;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.Objects;
+
+/**
+ * Request for beginning a create credential request.
+ *
+ * See {@link BeginCreateCredentialResponse} for the counterpart response
+ */
+public final class BeginCreateCredentialRequest implements Parcelable {
+ private final @NonNull String mCallingPackage;
+ private final @NonNull String mType;
+ private final @NonNull Bundle mData;
+
+ /**
+ * Constructs a new instance.
+ *
+ * @throws IllegalArgumentException If {@code callingPackage}, or {@code type} string is
+ * null or empty.
+ * @throws NullPointerException If {@code data} is null.
+ */
+ public BeginCreateCredentialRequest(@NonNull String callingPackage,
+ @NonNull String type, @NonNull Bundle data) {
+ mCallingPackage = Preconditions.checkStringNotEmpty(callingPackage,
+ "callingPackage must not be null or empty");
+ mType = Preconditions.checkStringNotEmpty(type,
+ "type must not be null or empty");
+ mData = Objects.requireNonNull(data, "data must not be null");
+ }
+
+ private BeginCreateCredentialRequest(@NonNull Parcel in) {
+ mCallingPackage = in.readString8();
+ mType = in.readString8();
+ mData = in.readBundle(Bundle.class.getClassLoader());
+ }
+
+ public static final @NonNull Creator<BeginCreateCredentialRequest> CREATOR =
+ new Creator<BeginCreateCredentialRequest>() {
+ @Override
+ public BeginCreateCredentialRequest createFromParcel(@NonNull Parcel in) {
+ return new BeginCreateCredentialRequest(in);
+ }
+
+ @Override
+ public BeginCreateCredentialRequest[] newArray(int size) {
+ return new BeginCreateCredentialRequest[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString8(mCallingPackage);
+ dest.writeString8(mType);
+ dest.writeBundle(mData);
+ }
+
+ /** Returns the calling package of the calling app. */
+ @NonNull
+ public String getCallingPackage() {
+ return mCallingPackage;
+ }
+
+ /** Returns the type of the credential to be created. */
+ @NonNull
+ public String getType() {
+ return mType;
+ }
+
+ /** Returns the data to be used while resolving the credential to create. */
+ @NonNull
+ public Bundle getData() {
+ return mData;
+ }
+}
diff --git a/core/java/android/service/credentials/CreateCredentialResponse.aidl b/core/java/android/service/credentials/BeginCreateCredentialResponse.aidl
similarity index 93%
rename from core/java/android/service/credentials/CreateCredentialResponse.aidl
rename to core/java/android/service/credentials/BeginCreateCredentialResponse.aidl
index 73c9147..d2a1408 100644
--- a/core/java/android/service/credentials/CreateCredentialResponse.aidl
+++ b/core/java/android/service/credentials/BeginCreateCredentialResponse.aidl
@@ -16,4 +16,4 @@
package android.service.credentials;
-parcelable CreateCredentialResponse;
+parcelable BeginCreateCredentialResponse;
diff --git a/core/java/android/service/credentials/BeginCreateCredentialResponse.java b/core/java/android/service/credentials/BeginCreateCredentialResponse.java
new file mode 100644
index 0000000..022678e
--- /dev/null
+++ b/core/java/android/service/credentials/BeginCreateCredentialResponse.java
@@ -0,0 +1,150 @@
+/*
+ * 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 android.service.credentials;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Response to a {@link BeginCreateCredentialRequest}.
+ */
+public final class BeginCreateCredentialResponse implements Parcelable {
+ private final @NonNull List<CreateEntry> mCreateEntries;
+ private final @Nullable CreateEntry mRemoteCreateEntry;
+
+ private BeginCreateCredentialResponse(@NonNull Parcel in) {
+ List<CreateEntry> createEntries = new ArrayList<>();
+ in.readTypedList(createEntries, CreateEntry.CREATOR);
+ mCreateEntries = createEntries;
+ mRemoteCreateEntry = in.readTypedObject(CreateEntry.CREATOR);
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeTypedList(mCreateEntries);
+ dest.writeTypedObject(mRemoteCreateEntry, flags);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final @NonNull Creator<BeginCreateCredentialResponse> CREATOR =
+ new Creator<BeginCreateCredentialResponse>() {
+ @Override
+ public BeginCreateCredentialResponse createFromParcel(@NonNull Parcel in) {
+ return new BeginCreateCredentialResponse(in);
+ }
+
+ @Override
+ public BeginCreateCredentialResponse[] newArray(int size) {
+ return new BeginCreateCredentialResponse[size];
+ }
+ };
+
+ /* package-private */ BeginCreateCredentialResponse(
+ @NonNull List<CreateEntry> createEntries,
+ @Nullable CreateEntry remoteCreateEntry) {
+ this.mCreateEntries = createEntries;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mCreateEntries);
+ this.mRemoteCreateEntry = remoteCreateEntry;
+ }
+
+ /** Returns the list of create entries to be displayed on the UI. */
+ public @NonNull List<CreateEntry> getCreateEntries() {
+ return mCreateEntries;
+ }
+
+ /** Returns the remote create entry to be displayed on the UI. */
+ public @Nullable CreateEntry getRemoteCreateEntry() {
+ return mRemoteCreateEntry;
+ }
+
+ /**
+ * A builder for {@link BeginCreateCredentialResponse}
+ */
+ @SuppressWarnings("WeakerAccess") /* synthetic access */
+ public static final class Builder {
+ private @NonNull List<CreateEntry> mCreateEntries = new ArrayList<>();
+ private @Nullable CreateEntry mRemoteCreateEntry;
+
+ /**
+ * Sets the list of create entries to be shown on the UI.
+ *
+ * @throws IllegalArgumentException If {@code createEntries} is empty.
+ * @throws NullPointerException If {@code createEntries} is null, or any of its elements
+ * are null.
+ */
+ public @NonNull Builder setCreateEntries(@NonNull List<CreateEntry> createEntries) {
+ Preconditions.checkCollectionNotEmpty(createEntries, "createEntries");
+ mCreateEntries = Preconditions.checkCollectionElementsNotNull(
+ createEntries, "createEntries");
+ return this;
+ }
+
+ /**
+ * Adds an entry to the list of create entries to be shown on the UI.
+ *
+ * @throws NullPointerException If {@code createEntry} is null.
+ */
+ public @NonNull Builder addCreateEntry(@NonNull CreateEntry createEntry) {
+ mCreateEntries.add(Objects.requireNonNull(createEntry));
+ return this;
+ }
+
+ /**
+ * Sets a remote create entry to be shown on the UI. Provider must set this entry if they
+ * wish to create the credential on a different device.
+ *
+ * <p> When constructing the {@link CreateEntry} object, the {@code pendingIntent} must be
+ * set such that it leads to an activity that can provide UI to fulfill the request on
+ * a remote device. When user selects this {@code remoteCreateEntry}, the system will
+ * invoke the {@code pendingIntent} set on the {@link CreateEntry}.
+ *
+ * <p> Once the remote credential flow is complete, the {@link android.app.Activity}
+ * result should be set to {@link android.app.Activity#RESULT_OK} and an extra with the
+ * {@link CredentialProviderService#EXTRA_CREATE_CREDENTIAL_RESULT} key should be populated
+ * with a {@link android.credentials.CreateCredentialResponse} object.
+ */
+ public @NonNull Builder setRemoteCreateEntry(@Nullable CreateEntry remoteCreateEntry) {
+ mRemoteCreateEntry = remoteCreateEntry;
+ return this;
+ }
+
+ /**
+ * Builds a new instance of {@link BeginCreateCredentialResponse}.
+ *
+ * @throws NullPointerException If {@code createEntries} is null.
+ * @throws IllegalArgumentException If {@code createEntries} is empty.
+ */
+ public @NonNull BeginCreateCredentialResponse build() {
+ Preconditions.checkCollectionNotEmpty(mCreateEntries, "createEntries must "
+ + "not be null, or empty");
+ return new BeginCreateCredentialResponse(mCreateEntries, mRemoteCreateEntry);
+ }
+ }
+}
diff --git a/core/java/android/service/credentials/CreateCredentialRequest.aidl b/core/java/android/service/credentials/CreateCredentialRequest.aidl
deleted file mode 100644
index eb7fba9..0000000
--- a/core/java/android/service/credentials/CreateCredentialRequest.aidl
+++ /dev/null
@@ -1,3 +0,0 @@
-package android.service.credentials;
-
-parcelable CreateCredentialRequest;
\ No newline at end of file
diff --git a/core/java/android/service/credentials/CreateCredentialRequest.java b/core/java/android/service/credentials/CreateCredentialRequest.java
index e6da349..aee85ab 100644
--- a/core/java/android/service/credentials/CreateCredentialRequest.java
+++ b/core/java/android/service/credentials/CreateCredentialRequest.java
@@ -27,8 +27,6 @@
/**
* Request for creating a credential.
- *
- * @hide
*/
public final class CreateCredentialRequest implements Parcelable {
private final @NonNull String mCallingPackage;
diff --git a/core/java/android/service/credentials/CreateCredentialResponse.java b/core/java/android/service/credentials/CreateCredentialResponse.java
deleted file mode 100644
index f69dca8..0000000
--- a/core/java/android/service/credentials/CreateCredentialResponse.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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 android.service.credentials;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.util.Preconditions;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Response to a {@link CreateCredentialRequest}.
- *
- * @hide
- */
-public final class CreateCredentialResponse implements Parcelable {
- private final @NonNull List<SaveEntry> mSaveEntries;
- private final @Nullable Action mRemoteSaveEntry;
- //TODO : Add actions if needed
-
- private CreateCredentialResponse(@NonNull Parcel in) {
- List<SaveEntry> saveEntries = new ArrayList<>();
- in.readTypedList(saveEntries, SaveEntry.CREATOR);
- mSaveEntries = saveEntries;
- mRemoteSaveEntry = in.readTypedObject(Action.CREATOR);
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeTypedList(mSaveEntries);
- dest.writeTypedObject(mRemoteSaveEntry, flags);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final @NonNull Creator<CreateCredentialResponse> CREATOR =
- new Creator<CreateCredentialResponse>() {
- @Override
- public CreateCredentialResponse createFromParcel(@NonNull Parcel in) {
- return new CreateCredentialResponse(in);
- }
-
- @Override
- public CreateCredentialResponse[] newArray(int size) {
- return new CreateCredentialResponse[size];
- }
- };
-
- /* package-private */ CreateCredentialResponse(
- @NonNull List<SaveEntry> saveEntries,
- @Nullable Action remoteSaveEntry) {
- this.mSaveEntries = saveEntries;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mSaveEntries);
- this.mRemoteSaveEntry = remoteSaveEntry;
- }
-
- /** Returns the list of save entries to be displayed on the UI. */
- public @NonNull List<SaveEntry> getSaveEntries() {
- return mSaveEntries;
- }
-
- /** Returns the remote save entry to be displayed on the UI. */
- public @NonNull Action getRemoteSaveEntry() {
- return mRemoteSaveEntry;
- }
-
- /**
- * A builder for {@link CreateCredentialResponse}
- */
- @SuppressWarnings("WeakerAccess")
- public static final class Builder {
- private @NonNull List<SaveEntry> mSaveEntries = new ArrayList<>();
- private @Nullable Action mRemoteSaveEntry;
-
- /**
- * Sets the list of save entries to be shown on the UI.
- *
- * @throws IllegalArgumentException If {@code saveEntries} is empty.
- * @throws NullPointerException If {@code saveEntries} is null, or any of its elements
- * are null.
- */
- public @NonNull Builder setSaveEntries(@NonNull List<SaveEntry> saveEntries) {
- Preconditions.checkCollectionNotEmpty(saveEntries, "saveEntries");
- mSaveEntries = Preconditions.checkCollectionElementsNotNull(
- saveEntries, "saveEntries");
- return this;
- }
-
- /**
- * Adds an entry to the list of save entries to be shown on the UI.
- *
- * @throws NullPointerException If {@code saveEntry} is null.
- */
- public @NonNull Builder addSaveEntry(@NonNull SaveEntry saveEntry) {
- mSaveEntries.add(Objects.requireNonNull(saveEntry));
- return this;
- }
-
- /**
- * Sets a remote save entry to be shown on the UI.
- */
- public @NonNull Builder setRemoteSaveEntry(@Nullable Action remoteSaveEntry) {
- mRemoteSaveEntry = remoteSaveEntry;
- return this;
- }
-
- /**
- * Builds the instance.
- *
- * @throws IllegalArgumentException If {@code saveEntries} is empty.
- */
- public @NonNull CreateCredentialResponse build() {
- Preconditions.checkCollectionNotEmpty(mSaveEntries, "saveEntries must "
- + "not be empty");
- return new CreateCredentialResponse(
- mSaveEntries,
- mRemoteSaveEntry);
- }
- }
-}
diff --git a/core/java/android/service/credentials/SaveEntry.java b/core/java/android/service/credentials/CreateEntry.java
similarity index 77%
rename from core/java/android/service/credentials/SaveEntry.java
rename to core/java/android/service/credentials/CreateEntry.java
index 55ff6ff..eb25e25 100644
--- a/core/java/android/service/credentials/SaveEntry.java
+++ b/core/java/android/service/credentials/CreateEntry.java
@@ -25,27 +25,25 @@
/**
* An entry to be shown on the UI. This entry represents where the credential to be created will
* be stored. Examples include user's account, family group etc.
- *
- * @hide
*/
-public final class SaveEntry implements Parcelable {
+public final class CreateEntry implements Parcelable {
private final @NonNull Slice mSlice;
private final @NonNull PendingIntent mPendingIntent;
- private SaveEntry(@NonNull Parcel in) {
+ private CreateEntry(@NonNull Parcel in) {
mSlice = in.readTypedObject(Slice.CREATOR);
mPendingIntent = in.readTypedObject(PendingIntent.CREATOR);
}
- public static final @NonNull Creator<SaveEntry> CREATOR = new Creator<SaveEntry>() {
+ public static final @NonNull Creator<CreateEntry> CREATOR = new Creator<CreateEntry>() {
@Override
- public SaveEntry createFromParcel(@NonNull Parcel in) {
- return new SaveEntry(in);
+ public CreateEntry createFromParcel(@NonNull Parcel in) {
+ return new CreateEntry(in);
}
@Override
- public SaveEntry[] newArray(int size) {
- return new SaveEntry[size];
+ public CreateEntry[] newArray(int size) {
+ return new CreateEntry[size];
}
};
@@ -61,12 +59,12 @@
}
/**
- * Constructs a save entry to be displayed on the UI.
+ * Constructs a CreateEntry to be displayed on the UI.
*
* @param slice the display content to be displayed on the UI, along with this entry
* @param pendingIntent the intent to be invoked when the user selects this entry
*/
- public SaveEntry(
+ public CreateEntry(
@NonNull Slice slice,
@NonNull PendingIntent pendingIntent) {
this.mSlice = slice;
@@ -77,12 +75,12 @@
NonNull.class, null, mPendingIntent);
}
- /** Returns the content to be displayed with this save entry on the UI. */
+ /** Returns the content to be displayed with this create entry on the UI. */
public @NonNull Slice getSlice() {
return mSlice;
}
- /** Returns the pendingIntent to be invoked when this save entry on the UI is selectcd. */
+ /** Returns the pendingIntent to be invoked when this create entry on the UI is selectcd. */
public @NonNull PendingIntent getPendingIntent() {
return mPendingIntent;
}
diff --git a/core/java/android/service/credentials/CredentialEntry.java b/core/java/android/service/credentials/CredentialEntry.java
index 98c537a..941db02b 100644
--- a/core/java/android/service/credentials/CredentialEntry.java
+++ b/core/java/android/service/credentials/CredentialEntry.java
@@ -31,8 +31,6 @@
/**
* A credential entry that is displayed on the account selector UI. Each entry corresponds to
* something that the user can select.
- *
- * @hide
*/
public final class CredentialEntry implements Parcelable {
/** The type of the credential entry to be shown on the UI. */
@@ -145,61 +143,67 @@
private boolean mAutoSelectAllowed = false;
/**
- * Builds the instance.
+ * Creates a builder for a {@link CredentialEntry} that should invoke a
+ * {@link PendingIntent} when selected by the user.
+ *
+ * <p>The {@code pendingIntent} can be used to launch activities that require some user
+ * engagement before getting the credential corresponding to this entry,
+ * e.g. authentication, confirmation etc.
+ * Once the activity fulfills the required user engagement, the
+ * {@link android.app.Activity} result should be set to
+ * {@link android.app.Activity#RESULT_OK}, and the
+ * {@link CredentialProviderService#EXTRA_CREDENTIAL_RESULT} must be set with a
+ * {@link Credential} object.
+ *
* @param type the type of credential underlying this credential entry
* @param slice the content to be displayed with this entry on the UI
+ * @param pendingIntent the pendingIntent to be invoked when this entry is selected by the
+ * user
*
- * @throws IllegalArgumentException If {@code type} is null or empty.
- * @throws NullPointerException If {@code slice} is null.
+ * @throws NullPointerException If {@code slice}, or {@code pendingIntent} is null.
+ * @throws IllegalArgumentException If {@code type} is null or empty, or if
+ * {@code pendingIntent} was not created with {@link PendingIntent#getActivity}
+ * or {@link PendingIntent#getActivities}.
*/
- public Builder(@NonNull String type, @NonNull Slice slice) {
+ public Builder(@NonNull String type, @NonNull Slice slice,
+ @NonNull PendingIntent pendingIntent) {
mType = Preconditions.checkStringNotEmpty(type, "type must not be "
+ "null, or empty");
mSlice = Objects.requireNonNull(slice,
"slice must not be null");
+ mPendingIntent = Objects.requireNonNull(pendingIntent,
+ "pendingIntent must not be null");
+ if (!mPendingIntent.isActivity()) {
+ throw new IllegalStateException("Pending intent must start an activity");
+ }
}
/**
- * Sets the pendingIntent to be invoked if the user selects this entry.
+ * Creates a builder for a {@link CredentialEntry} that contains a {@link Credential},
+ * and does not require further action.
+ * @param type the type of credential underlying this credential entry
+ * @param slice the content to be displayed with this entry on the UI
+ * @param credential the credential to be returned to the client app, when this entry is
+ * selected by the user
*
- * The pending intent can be used to launch activities that require some user engagement
- * before getting the credential corresponding to this entry, e.g. authentication,
- * confirmation etc.
- * Once the activity fulfills the required user engagement, a {@link Credential} object
- * must be returned as an extra on activity finish.
- *
- * @throws IllegalStateException If {@code credential} is already set. Must either set the
- * {@code credential}, or the {@code pendingIntent}.
+ * @throws IllegalArgumentException If {@code type} is null or empty.
+ * @throws NullPointerException If {@code slice}, or {@code credential} is null.
*/
- public @NonNull Builder setPendingIntent(@Nullable PendingIntent pendingIntent) {
- if (pendingIntent != null) {
- Preconditions.checkState(mCredential == null,
- "credential is already set. Cannot set both the pendingIntent "
- + "and the credential");
- }
- mPendingIntent = pendingIntent;
- return this;
- }
-
- /**
- * Sets the credential to be used, if the user selects this entry.
- *
- * @throws IllegalStateException If {@code pendingIntent} is already set. Must either set
- * the {@code pendingIntent}, or the {@code credential}.
- */
- public @NonNull Builder setCredential(@Nullable Credential credential) {
- if (credential != null) {
- Preconditions.checkState(mPendingIntent == null,
- "pendingIntent is already set. Cannot set both the "
- + "pendingIntent and the credential");
- }
- mCredential = credential;
- return this;
+ public Builder(@NonNull String type, @NonNull Slice slice, @NonNull Credential credential) {
+ mType = Preconditions.checkStringNotEmpty(type, "type must not be "
+ + "null, or empty");
+ mSlice = Objects.requireNonNull(slice,
+ "slice must not be null");
+ mCredential = Objects.requireNonNull(credential,
+ "credential must not be null");
}
/**
* Sets whether the entry is allowed to be auto selected by the framework.
* The default value is set to false.
+ *
+ * <p> The entry is only auto selected if it is the only entry on the user selector,
+ * AND the developer has also enabled auto select, while building the request.
*/
public @NonNull Builder setAutoSelectAllowed(@NonNull boolean autoSelectAllowed) {
mAutoSelectAllowed = autoSelectAllowed;
diff --git a/core/java/android/service/credentials/CredentialProviderException.java b/core/java/android/service/credentials/CredentialProviderException.java
index 06f0052..02b7443 100644
--- a/core/java/android/service/credentials/CredentialProviderException.java
+++ b/core/java/android/service/credentials/CredentialProviderException.java
@@ -24,8 +24,6 @@
/**
* Contains custom exceptions to be used by credential providers on failure.
- *
- * @hide
*/
public class CredentialProviderException extends Exception {
public static final int ERROR_UNKNOWN = 0;
@@ -59,6 +57,11 @@
@Retention(RetentionPolicy.SOURCE)
public @interface CredentialProviderError { }
+ public CredentialProviderException(@CredentialProviderError int errorCode,
+ @NonNull String message, @NonNull Throwable cause) {
+ super(message, cause);
+ mErrorCode = errorCode;
+ }
public CredentialProviderException(@CredentialProviderError int errorCode,
@NonNull String message) {
diff --git a/core/java/android/service/credentials/CredentialProviderService.java b/core/java/android/service/credentials/CredentialProviderService.java
index 24b7c3c..32646e6 100644
--- a/core/java/android/service/credentials/CredentialProviderService.java
+++ b/core/java/android/service/credentials/CredentialProviderService.java
@@ -37,30 +37,63 @@
/**
* Service to be extended by credential providers, in order to return user credentials
* to the framework.
- *
- * @hide
*/
public abstract class CredentialProviderService extends Service {
- /** Extra to be used by provider to populate the credential when ending the activity started
- * through the {@code pendingIntent} on the selected {@link SaveEntry}. **/
- public static final String EXTRA_CREATE_CREDENTIAL_RESPONSE =
- "android.service.credentials.extra.CREATE_CREDENTIAL_RESPONSE";
-
- /** Extra to be used by provider to populate the {@link CredentialsDisplayContent} when
- * an authentication action entry is selected. **/
- public static final String EXTRA_GET_CREDENTIALS_DISPLAY_CONTENT =
- "android.service.credentials.extra.GET_CREDENTIALS_DISPLAY_CONTENT";
+ /**
+ * Intent extra: The {@link android.credentials.CreateCredentialRequest} attached with
+ * the {@code pendingIntent} that is invoked when the user selects a {@link CreateEntry}
+ * returned as part of the {@link BeginCreateCredentialResponse}
+ *
+ * <p>
+ * Type: {@link android.credentials.CreateCredentialRequest}
+ */
+ public static final String EXTRA_CREATE_CREDENTIAL_REQUEST =
+ "android.service.credentials.extra.CREATE_CREDENTIAL_REQUEST";
/**
- * Provider must read the value against this extra to receive the complete create credential
- * request parameters, when a pending intent is launched.
+ * Intent extra: The result of a create flow operation, to be set on finish of the
+ * {@link android.app.Activity} invoked through the {@code pendingIntent} set on
+ * a {@link CreateEntry}.
+ *
+ * <p>
+ * Type: {@link android.credentials.CreateCredentialResponse}
*/
- public static final String EXTRA_CREATE_CREDENTIAL_REQUEST_PARAMS =
- "android.service.credentials.extra.CREATE_CREDENTIAL_REQUEST_PARAMS";
+ public static final String EXTRA_CREATE_CREDENTIAL_RESULT =
+ "android.service.credentials.extra.CREATE_CREDENTIAL_RESULT";
- /** Extra to be used by the provider when setting the credential result. */
- public static final String EXTRA_GET_CREDENTIAL =
- "android.service.credentials.extra.GET_CREDENTIAL";
+ /**
+ * Intent extra: The result of a get credential flow operation, to be set on finish of the
+ * {@link android.app.Activity} invoked through the {@code pendingIntent} set on
+ * a {@link CredentialEntry}.
+ *
+ * <p>
+ * Type: {@link android.credentials.Credential}
+ */
+ public static final String EXTRA_CREDENTIAL_RESULT =
+ "android.service.credentials.extra.CREDENTIAL_RESULT";
+
+ /**
+ * Intent extra: The result of an authentication flow, to be set on finish of the
+ * {@link android.app.Activity} invoked through the {@link android.app.PendingIntent} set on
+ * a {@link GetCredentialsResponse}. This result should contain the actual content, including
+ * credential entries and action entries, to be shown on the selector.
+ *
+ * <p>
+ * Type: {@link CredentialsResponseContent}
+ */
+ public static final String EXTRA_GET_CREDENTIALS_CONTENT_RESULT =
+ "android.service.credentials.extra.GET_CREDENTIALS_CONTENT_RESULT";
+
+ /**
+ * Intent extra: The error result of any {@link android.app.PendingIntent} flow, to be set
+ * on finish of the corresponding {@link android.app.Activity}. This result should contain an
+ * error code, representing the error encountered by the provider.
+ *
+ * <p>
+ * Type: {@link String}
+ */
+ public static final String EXTRA_ERROR =
+ "android.service.credentials.extra.ERROR";
private static final String TAG = "CredProviderService";
@@ -129,20 +162,21 @@
}
@Override
- public ICancellationSignal onCreateCredential(CreateCredentialRequest request,
- ICreateCredentialCallback callback) {
+ public ICancellationSignal onBeginCreateCredential(BeginCreateCredentialRequest request,
+ IBeginCreateCredentialCallback callback) {
Objects.requireNonNull(request);
Objects.requireNonNull(callback);
ICancellationSignal transport = CancellationSignal.createTransport();
mHandler.sendMessage(obtainMessage(
- CredentialProviderService::onCreateCredential,
+ CredentialProviderService::onBeginCreateCredential,
CredentialProviderService.this, request,
CancellationSignal.fromTransport(transport),
- new OutcomeReceiver<CreateCredentialResponse, CredentialProviderException>() {
+ new OutcomeReceiver<
+ BeginCreateCredentialResponse, CredentialProviderException>() {
@Override
- public void onResult(CreateCredentialResponse result) {
+ public void onResult(BeginCreateCredentialResponse result) {
try {
callback.onSuccess(result);
} catch (RemoteException e) {
@@ -182,8 +216,8 @@
* the android system.
* @param callback Object used to relay the response of the credential creation request.
*/
- public abstract void onCreateCredential(@NonNull CreateCredentialRequest request,
+ public abstract void onBeginCreateCredential(@NonNull BeginCreateCredentialRequest request,
@NonNull CancellationSignal cancellationSignal,
- @NonNull OutcomeReceiver<CreateCredentialResponse,
+ @NonNull OutcomeReceiver<BeginCreateCredentialResponse,
CredentialProviderException> callback);
}
diff --git a/core/java/android/service/credentials/CredentialsDisplayContent.java b/core/java/android/service/credentials/CredentialsResponseContent.java
similarity index 64%
rename from core/java/android/service/credentials/CredentialsDisplayContent.java
rename to core/java/android/service/credentials/CredentialsResponseContent.java
index 4b23800..32cab50 100644
--- a/core/java/android/service/credentials/CredentialsDisplayContent.java
+++ b/core/java/android/service/credentials/CredentialsResponseContent.java
@@ -28,12 +28,10 @@
import java.util.Objects;
/**
- * Content to be displayed on the account selector UI, including credential entries,
- * actions etc.
- *
- * @hide
+ * The content to be displayed on the account selector UI, including credential entries,
+ * actions etc. Returned as part of {@link GetCredentialsResponse}
*/
-public final class CredentialsDisplayContent implements Parcelable {
+public final class CredentialsResponseContent implements Parcelable {
/** List of credential entries to be displayed on the UI. */
private final @NonNull List<CredentialEntry> mCredentialEntries;
@@ -41,36 +39,36 @@
private final @NonNull List<Action> mActions;
/** Remote credential entry to get the response from a different device. */
- private final @Nullable Action mRemoteCredentialEntry;
+ private final @Nullable CredentialEntry mRemoteCredentialEntry;
- private CredentialsDisplayContent(@NonNull List<CredentialEntry> credentialEntries,
+ private CredentialsResponseContent(@NonNull List<CredentialEntry> credentialEntries,
@NonNull List<Action> actions,
- @Nullable Action remoteCredentialEntry) {
+ @Nullable CredentialEntry remoteCredentialEntry) {
mCredentialEntries = credentialEntries;
mActions = actions;
mRemoteCredentialEntry = remoteCredentialEntry;
}
- private CredentialsDisplayContent(@NonNull Parcel in) {
+ private CredentialsResponseContent(@NonNull Parcel in) {
List<CredentialEntry> credentialEntries = new ArrayList<>();
in.readTypedList(credentialEntries, CredentialEntry.CREATOR);
mCredentialEntries = credentialEntries;
List<Action> actions = new ArrayList<>();
in.readTypedList(actions, Action.CREATOR);
mActions = actions;
- mRemoteCredentialEntry = in.readTypedObject(Action.CREATOR);
+ mRemoteCredentialEntry = in.readTypedObject(CredentialEntry.CREATOR);
}
- public static final @NonNull Creator<CredentialsDisplayContent> CREATOR =
- new Creator<CredentialsDisplayContent>() {
+ public static final @NonNull Creator<CredentialsResponseContent> CREATOR =
+ new Creator<CredentialsResponseContent>() {
@Override
- public CredentialsDisplayContent createFromParcel(@NonNull Parcel in) {
- return new CredentialsDisplayContent(in);
+ public CredentialsResponseContent createFromParcel(@NonNull Parcel in) {
+ return new CredentialsResponseContent(in);
}
@Override
- public CredentialsDisplayContent[] newArray(int size) {
- return new CredentialsDisplayContent[size];
+ public CredentialsResponseContent[] newArray(int size) {
+ return new CredentialsResponseContent[size];
}
};
@@ -103,22 +101,34 @@
/**
* Returns the remote credential entry to be displayed on the UI.
*/
- public @Nullable Action getRemoteCredentialEntry() {
+ public @Nullable CredentialEntry getRemoteCredentialEntry() {
return mRemoteCredentialEntry;
}
/**
- * Builds an instance of {@link CredentialsDisplayContent}.
+ * Builds an instance of {@link CredentialsResponseContent}.
*/
public static final class Builder {
private List<CredentialEntry> mCredentialEntries = new ArrayList<>();
private List<Action> mActions = new ArrayList<>();
- private Action mRemoteCredentialEntry;
+ private CredentialEntry mRemoteCredentialEntry;
/**
- * Sets the remote credential entry to be displayed on the UI.
+ * Sets a remote credential entry to be shown on the UI. Provider must set this if they
+ * wish to get the credential from a different device.
+ *
+ * <p> When constructing the {@link CredentialEntry} object, the {@code pendingIntent}
+ * must be set such that it leads to an activity that can provide UI to fulfill the request
+ * on a remote device. When user selects this {@code remoteCredentialEntry}, the system will
+ * invoke the {@code pendingIntent} set on the {@link CredentialEntry}.
+ *
+ * <p> Once the remote credential flow is complete, the {@link android.app.Activity}
+ * result should be set to {@link android.app.Activity#RESULT_OK} and an extra with the
+ * {@link CredentialProviderService#EXTRA_CREDENTIAL_RESULT} key should be populated
+ * with a {@link android.credentials.Credential} object.
*/
- public @NonNull Builder setRemoteCredentialEntry(@Nullable Action remoteCredentialEntry) {
+ public @NonNull Builder setRemoteCredentialEntry(@Nullable CredentialEntry
+ remoteCredentialEntry) {
mRemoteCredentialEntry = remoteCredentialEntry;
return this;
}
@@ -138,6 +148,11 @@
* Adds an {@link Action} to the list of actions to be displayed on
* the UI.
*
+ * <p> An {@code action} must be used for independent user actions,
+ * such as opening the app, intenting directly into a certain app activity etc. The
+ * {@code pendingIntent} set with the {@code action} must invoke the corresponding
+ * activity.
+ *
* @throws NullPointerException If {@code action} is null.
*/
public @NonNull Builder addAction(@NonNull Action action) {
@@ -175,17 +190,16 @@
/**
* Builds a {@link GetCredentialsResponse} instance.
*
- * @throws NullPointerException If {@code credentialEntries} is null.
- * @throws IllegalStateException if both {@code credentialEntries} and
- * {@code actions} are empty.
+ * @throws IllegalStateException if {@code credentialEntries}, {@code actions}
+ * and {@code remoteCredentialEntry} are all null or empty.
*/
- public @NonNull CredentialsDisplayContent build() {
+ public @NonNull CredentialsResponseContent build() {
if (mCredentialEntries != null && mCredentialEntries.isEmpty()
- && mActions != null && mActions.isEmpty()) {
+ && mActions != null && mActions.isEmpty() && mRemoteCredentialEntry == null) {
throw new IllegalStateException("credentialEntries and actions must not both "
+ "be empty");
}
- return new CredentialsDisplayContent(mCredentialEntries, mActions,
+ return new CredentialsResponseContent(mCredentialEntries, mActions,
mRemoteCredentialEntry);
}
}
diff --git a/core/java/android/service/credentials/GetCredentialsRequest.java b/core/java/android/service/credentials/GetCredentialsRequest.java
index 03ba20e..9052b54 100644
--- a/core/java/android/service/credentials/GetCredentialsRequest.java
+++ b/core/java/android/service/credentials/GetCredentialsRequest.java
@@ -29,8 +29,6 @@
/**
* Request for getting user's credentials from a given credential provider.
- *
- * @hide
*/
public final class GetCredentialsRequest implements Parcelable {
/** Calling package of the app requesting for credentials. */
diff --git a/core/java/android/service/credentials/GetCredentialsResponse.java b/core/java/android/service/credentials/GetCredentialsResponse.java
index 979a699..5263141 100644
--- a/core/java/android/service/credentials/GetCredentialsResponse.java
+++ b/core/java/android/service/credentials/GetCredentialsResponse.java
@@ -26,12 +26,10 @@
/**
* Response from a credential provider, containing credential entries and other associated
* data to be shown on the account selector UI.
- *
- * @hide
*/
public final class GetCredentialsResponse implements Parcelable {
/** Content to be used for the UI. */
- private final @Nullable CredentialsDisplayContent mCredentialsDisplayContent;
+ private final @Nullable CredentialsResponseContent mCredentialsResponseContent;
/**
* Authentication action that must be launched and completed before showing any content
@@ -40,11 +38,17 @@
private final @Nullable Action mAuthenticationAction;
/**
- * Creates a {@link GetCredentialsRequest} instance with an authentication action set.
+ * Creates a {@link GetCredentialsResponse} instance with an authentication {@link Action} set.
* Providers must use this method when no content can be shown before authentication.
*
- * Once the authentication action activity is launched, and the user is authenticated, providers
- * should create another response with {@link CredentialsDisplayContent} using
+ * <p> When the user selects this {@code authenticationAction}, the system invokes the
+ * corresponding {@code pendingIntent}. Once the authentication flow is complete,
+ * the {@link android.app.Activity} result should be set
+ * to {@link android.app.Activity#RESULT_OK} and the
+ * {@link CredentialProviderService#EXTRA_GET_CREDENTIALS_CONTENT_RESULT} extra should be set
+ * with a fully populated {@link CredentialsResponseContent} object.
+ * the authentication action activity is launched, and the user is authenticated, providers
+ * should create another response with {@link CredentialsResponseContent} using
* {@code createWithDisplayContent}, and add that response to the result of the authentication
* activity.
*
@@ -58,27 +62,27 @@
}
/**
- * Creates a {@link GetCredentialsRequest} instance with display content to be shown on the UI.
+ * Creates a {@link GetCredentialsRequest} instance with content to be shown on the UI.
* Providers must use this method when there is content to be shown without top level
- * authentication required.
+ * authentication required, including credential entries, action entries or a remote entry,
*
- * @throws NullPointerException If {@code credentialsDisplayContent} is null.
+ * @throws NullPointerException If {@code credentialsResponseContent} is null.
*/
- public static @NonNull GetCredentialsResponse createWithDisplayContent(
- @NonNull CredentialsDisplayContent credentialsDisplayContent) {
- Objects.requireNonNull(credentialsDisplayContent,
- "credentialsDisplayContent must not be null");
- return new GetCredentialsResponse(credentialsDisplayContent, null);
+ public static @NonNull GetCredentialsResponse createWithResponseContent(
+ @NonNull CredentialsResponseContent credentialsResponseContent) {
+ Objects.requireNonNull(credentialsResponseContent,
+ "credentialsResponseContent must not be null");
+ return new GetCredentialsResponse(credentialsResponseContent, null);
}
- private GetCredentialsResponse(@Nullable CredentialsDisplayContent credentialsDisplayContent,
+ private GetCredentialsResponse(@Nullable CredentialsResponseContent credentialsResponseContent,
@Nullable Action authenticationAction) {
- mCredentialsDisplayContent = credentialsDisplayContent;
+ mCredentialsResponseContent = credentialsResponseContent;
mAuthenticationAction = authenticationAction;
}
private GetCredentialsResponse(@NonNull Parcel in) {
- mCredentialsDisplayContent = in.readTypedObject(CredentialsDisplayContent.CREATOR);
+ mCredentialsResponseContent = in.readTypedObject(CredentialsResponseContent.CREATOR);
mAuthenticationAction = in.readTypedObject(Action.CREATOR);
}
@@ -102,23 +106,23 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeTypedObject(mCredentialsDisplayContent, flags);
+ dest.writeTypedObject(mCredentialsResponseContent, flags);
dest.writeTypedObject(mAuthenticationAction, flags);
}
/**
- * Returns the authentication action to be invoked before any other content
- * can be shown to the user.
+ * If this response represents a top level authentication action, returns the authentication
+ * action to be invoked before any other content can be shown to the user.
*/
public @Nullable Action getAuthenticationAction() {
return mAuthenticationAction;
}
/**
- * Returns the credentialDisplayContent that does not require authentication, and
- * can be shown to the user on the account selector UI.
+ * Returns the actual content to be displayed on the selector, if this response does not
+ * require any top level authentication.
*/
- public @Nullable CredentialsDisplayContent getCredentialsDisplayContent() {
- return mCredentialsDisplayContent;
+ public @Nullable CredentialsResponseContent getCredentialsResponseContent() {
+ return mCredentialsResponseContent;
}
}
diff --git a/core/java/android/service/credentials/IBeginCreateCredentialCallback.aidl b/core/java/android/service/credentials/IBeginCreateCredentialCallback.aidl
new file mode 100644
index 0000000..ec0bc36
--- /dev/null
+++ b/core/java/android/service/credentials/IBeginCreateCredentialCallback.aidl
@@ -0,0 +1,13 @@
+package android.service.credentials;
+
+import android.service.credentials.BeginCreateCredentialResponse;
+
+/**
+ * Interface from the system to a credential provider service.
+ *
+ * @hide
+ */
+oneway interface IBeginCreateCredentialCallback {
+ void onSuccess(in BeginCreateCredentialResponse request);
+ void onFailure(int errorCode, in CharSequence message);
+}
\ No newline at end of file
diff --git a/core/java/android/service/credentials/ICreateCredentialCallback.aidl b/core/java/android/service/credentials/ICreateCredentialCallback.aidl
deleted file mode 100644
index 4cc76a4..0000000
--- a/core/java/android/service/credentials/ICreateCredentialCallback.aidl
+++ /dev/null
@@ -1,13 +0,0 @@
-package android.service.credentials;
-
-import android.service.credentials.CreateCredentialResponse;
-
-/**
- * Interface from the system to a credential provider service.
- *
- * @hide
- */
-oneway interface ICreateCredentialCallback {
- void onSuccess(in CreateCredentialResponse request);
- void onFailure(int errorCode, in CharSequence message);
-}
\ No newline at end of file
diff --git a/core/java/android/service/credentials/ICredentialProviderService.aidl b/core/java/android/service/credentials/ICredentialProviderService.aidl
index c21cefa..b9eb3ed 100644
--- a/core/java/android/service/credentials/ICredentialProviderService.aidl
+++ b/core/java/android/service/credentials/ICredentialProviderService.aidl
@@ -18,9 +18,9 @@
import android.os.ICancellationSignal;
import android.service.credentials.GetCredentialsRequest;
-import android.service.credentials.CreateCredentialRequest;
+import android.service.credentials.BeginCreateCredentialRequest;
import android.service.credentials.IGetCredentialsCallback;
-import android.service.credentials.ICreateCredentialCallback;
+import android.service.credentials.IBeginCreateCredentialCallback;
import android.os.ICancellationSignal;
/**
@@ -30,5 +30,5 @@
*/
interface ICredentialProviderService {
ICancellationSignal onGetCredentials(in GetCredentialsRequest request, in IGetCredentialsCallback callback);
- ICancellationSignal onCreateCredential(in CreateCredentialRequest request, in ICreateCredentialCallback callback);
+ ICancellationSignal onBeginCreateCredential(in BeginCreateCredentialRequest request, in IBeginCreateCredentialCallback callback);
}
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index 09d0fc5..e5c9adb 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -26,6 +26,7 @@
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
+import android.telephony.Annotation.CallState;
import android.telephony.Annotation.DisconnectCauses;
import android.telephony.Annotation.PreciseDisconnectCauses;
import android.telephony.Annotation.RadioPowerState;
@@ -725,7 +726,7 @@
*/
@Deprecated
@RequiresPermission(value = android.Manifest.permission.READ_PHONE_STATE, conditional = true)
- public void onCallStateChanged(@Annotation.CallState int state, String phoneNumber) {
+ public void onCallStateChanged(@CallState int state, String phoneNumber) {
// default implementation empty
}
@@ -1568,48 +1569,12 @@
() -> mExecutor.execute(() -> psl.onRadioPowerStateChanged(state)));
}
- public void onCallStatesChanged(List<CallState> callStateList) {
+ public void onCallAttributesChanged(CallAttributes callAttributes) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
- if (callStateList == null) return;
- CallAttributes ca;
- if (callStateList.isEmpty()) {
- ca = new CallAttributes(
- new PreciseCallState(PreciseCallState.PRECISE_CALL_STATE_IDLE,
- PreciseCallState.PRECISE_CALL_STATE_IDLE,
- PreciseCallState.PRECISE_CALL_STATE_IDLE,
- DisconnectCause.NOT_VALID, PreciseDisconnectCause.NOT_VALID),
- TelephonyManager.NETWORK_TYPE_UNKNOWN, new CallQuality());
- } else {
- int foregroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
- int backgroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
- int ringingCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
- for (CallState cs : callStateList) {
- switch (cs.getCallClassification()) {
- case CallState.CALL_CLASSIFICATION_FOREGROUND:
- foregroundCallState = cs.getCallState();
- break;
- case CallState.CALL_CLASSIFICATION_BACKGROUND:
- backgroundCallState = cs.getCallState();
- break;
- case CallState.CALL_CLASSIFICATION_RINGING:
- ringingCallState = cs.getCallState();
- break;
- default:
- break;
- }
- }
- ca = new CallAttributes(
- new PreciseCallState(
- foregroundCallState, backgroundCallState, ringingCallState,
- DisconnectCause.NOT_VALID, PreciseDisconnectCause.NOT_VALID),
- callStateList.get(0).getNetworkType(),
- callStateList.get(0).getCallQuality());
- }
Binder.withCleanCallingIdentity(
- () -> mExecutor.execute(
- () -> psl.onCallAttributesChanged(ca)));
+ () -> mExecutor.execute(() -> psl.onCallAttributesChanged(callAttributes)));
}
public void onActiveDataSubIdChanged(int subId) {
diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java
index 54c4b668..e8960b8 100644
--- a/core/java/android/telephony/TelephonyCallback.java
+++ b/core/java/android/telephony/TelephonyCallback.java
@@ -27,7 +27,6 @@
import android.os.Build;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo;
-import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.IPhoneStateListener;
@@ -63,7 +62,7 @@
* appropriate sub-interfaces.
*/
public class TelephonyCallback {
- private static final String LOG_TAG = "TelephonyCallback";
+
/**
* Experiment flag to set the per-pid registration limit for TelephonyCallback
*
@@ -1333,9 +1332,7 @@
@SystemApi
public interface CallAttributesListener {
/**
- * Callback invoked when the call attributes changes on the active call on the registered
- * subscription. If the user swaps between a foreground and background call the call
- * attributes will be reported for the active call only.
+ * Callback invoked when the call attributes changes on the registered subscription.
* Note, the registration subscription ID comes from {@link TelephonyManager} object
* which registers TelephonyCallback by
* {@link TelephonyManager#registerTelephonyCallback(Executor, TelephonyCallback)}.
@@ -1349,77 +1346,9 @@
* {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}.
*
* @param callAttributes the call attributes
- * @deprecated Use onCallStatesChanged({@link List<CallState>}) to get each of call
- * state for all ongoing calls on the subscription.
*/
@RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
- @Deprecated
- default void onCallAttributesChanged(@NonNull CallAttributes callAttributes) {
- Log.w(LOG_TAG, "onCallAttributesChanged(List<CallAttributes>) should be "
- + "overridden.");
- }
-
- /**
- * Callback invoked when the call attributes changes on the ongoing calls on the registered
- * subscription. If there are 1 foreground and 1 background call, Two {@link CallState}
- * will be passed.
- * Note, the registration subscription ID comes from {@link TelephonyManager} object
- * which registers TelephonyCallback by
- * {@link TelephonyManager#registerTelephonyCallback(Executor, TelephonyCallback)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subscription ID. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- * In the event that there are no active(state is not
- * {@link PreciseCallState#PRECISE_CALL_STATE_IDLE}) calls, this API will report empty list.
- *
- * The calling app should have carrier privileges
- * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
- * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}.
- *
- * @param callStateList the list of call states for each ongoing call. If there are
- * a active call and a holding call, 1 call attributes for
- * {@link PreciseCallState#PRECISE_CALL_STATE_ACTIVE} and another
- * for {@link PreciseCallState#PRECISE_CALL_STATE_HOLDING}
- * will be in this list.
- */
- // Added as default for backward compatibility
- @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
- default void onCallStatesChanged(@NonNull List<CallState> callStateList) {
- if (callStateList.size() > 0) {
- int foregroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
- int backgroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
- int ringingCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
- for (CallState cs : callStateList) {
- switch (cs.getCallClassification()) {
- case CallState.CALL_CLASSIFICATION_FOREGROUND:
- foregroundCallState = cs.getCallState();
- break;
- case CallState.CALL_CLASSIFICATION_BACKGROUND:
- backgroundCallState = cs.getCallState();
- break;
- case CallState.CALL_CLASSIFICATION_RINGING:
- ringingCallState = cs.getCallState();
- break;
- default:
- break;
- }
- }
- onCallAttributesChanged(new CallAttributes(
- new PreciseCallState(
- ringingCallState, foregroundCallState, backgroundCallState,
- DisconnectCause.NOT_VALID, PreciseDisconnectCause.NOT_VALID),
- callStateList.get(0).getNetworkType(),
- callStateList.get(0).getCallQuality()));
- } else {
- onCallAttributesChanged(new CallAttributes(
- new PreciseCallState(PreciseCallState.PRECISE_CALL_STATE_IDLE,
- PreciseCallState.PRECISE_CALL_STATE_IDLE,
- PreciseCallState.PRECISE_CALL_STATE_IDLE,
- DisconnectCause.NOT_VALID, PreciseDisconnectCause.NOT_VALID),
- TelephonyManager.NETWORK_TYPE_UNKNOWN, new CallQuality()));
- }
- }
+ void onCallAttributesChanged(@NonNull CallAttributes callAttributes);
}
/**
@@ -1773,13 +1702,14 @@
() -> mExecutor.execute(() -> listener.onRadioPowerStateChanged(state)));
}
- public void onCallStatesChanged(List<CallState> callStateList) {
+ public void onCallAttributesChanged(CallAttributes callAttributes) {
CallAttributesListener listener =
(CallAttributesListener) mTelephonyCallbackWeakRef.get();
if (listener == null) return;
Binder.withCleanCallingIdentity(
- () -> mExecutor.execute(() -> listener.onCallStatesChanged(callStateList)));
+ () -> mExecutor.execute(() -> listener.onCallAttributesChanged(
+ callAttributes)));
}
public void onActiveDataSubIdChanged(int subId) {
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 0a1538de..a3696e3 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -32,13 +32,13 @@
import android.telephony.Annotation.DataActivityType;
import android.telephony.Annotation.DisconnectCauses;
import android.telephony.Annotation.NetworkType;
+import android.telephony.Annotation.PreciseCallStates;
import android.telephony.Annotation.PreciseDisconnectCauses;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SimActivationState;
import android.telephony.Annotation.SrvccState;
import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
import android.telephony.emergency.EmergencyNumber;
-import android.telephony.ims.ImsCallSession;
import android.telephony.ims.ImsReasonInfo;
import android.util.ArraySet;
import android.util.Log;
@@ -741,20 +741,17 @@
* @param slotIndex for which precise call state changed. Can be derived from subId except when
* subId is invalid.
* @param subId for which precise call state changed.
- * @param callStates Array of PreciseCallState of foreground, background & ringing calls.
- * @param imsCallIds Array of IMS call session ID{@link ImsCallSession#getCallId} for
- * ringing, foreground & background calls.
- * @param imsServiceTypes Array of IMS call service type for ringing, foreground &
- * background calls.
- * @param imsCallTypes Array of IMS call type for ringing, foreground & background calls.
+ * @param ringCallPreciseState ringCall state.
+ * @param foregroundCallPreciseState foreground call state.
+ * @param backgroundCallPreciseState background call state.
*/
public void notifyPreciseCallState(int slotIndex, int subId,
- @Annotation.PreciseCallStates int[] callStates, String[] imsCallIds,
- @Annotation.ImsCallServiceType int[] imsServiceTypes,
- @Annotation.ImsCallType int[] imsCallTypes) {
+ @PreciseCallStates int ringCallPreciseState,
+ @PreciseCallStates int foregroundCallPreciseState,
+ @PreciseCallStates int backgroundCallPreciseState) {
try {
- sRegistry.notifyPreciseCallState(slotIndex, subId, callStates,
- imsCallIds, imsServiceTypes, imsCallTypes);
+ sRegistry.notifyPreciseCallState(slotIndex, subId, ringCallPreciseState,
+ foregroundCallPreciseState, backgroundCallPreciseState);
} catch (RemoteException ex) {
// system process is dead
throw ex.rethrowFromSystemServer();
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index d77e499..03b25c2 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -29,6 +29,7 @@
import static android.view.WindowInsets.Type.SYSTEM_GESTURES;
import static android.view.WindowInsets.Type.TAPPABLE_ELEMENT;
import static android.view.WindowInsets.Type.all;
+import static android.view.WindowInsets.Type.displayCutout;
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.indexOf;
import static android.view.WindowInsets.Type.systemBars;
@@ -597,7 +598,10 @@
return new WindowInsets(null, null,
mTypeVisibilityMap,
mIsRound, mAlwaysConsumeSystemBars,
- displayCutoutCopyConstructorArgument(this),
+ // If the system window insets types contain displayCutout, we should also consume
+ // it.
+ (mCompatInsetsTypes & displayCutout()) != 0
+ ? null : displayCutoutCopyConstructorArgument(this),
mRoundedCorners, mPrivacyIndicatorBounds, mCompatInsetsTypes,
mCompatIgnoreVisibility);
}
diff --git a/core/java/com/android/internal/content/om/OverlayManagerImpl.java b/core/java/com/android/internal/content/om/OverlayManagerImpl.java
index 76e068d..6ceccd1 100644
--- a/core/java/com/android/internal/content/om/OverlayManagerImpl.java
+++ b/core/java/com/android/internal/content/om/OverlayManagerImpl.java
@@ -17,14 +17,20 @@
package com.android.internal.content.om;
import static android.content.Context.MODE_PRIVATE;
+import static android.content.om.OverlayManagerTransaction.Request.BUNDLE_FABRICATED_OVERLAY;
+import static android.content.om.OverlayManagerTransaction.Request.TYPE_REGISTER_FABRICATED;
+import static android.content.om.OverlayManagerTransaction.Request.TYPE_UNREGISTER_FABRICATED;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
import static com.android.internal.content.om.OverlayConfig.DEFAULT_PRIORITY;
import android.annotation.NonNull;
+import android.annotation.NonUiContext;
import android.content.Context;
+import android.content.om.OverlayIdentifier;
import android.content.om.OverlayInfo;
+import android.content.om.OverlayManagerTransaction;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.parsing.FrameworkParsingPackageUtils;
@@ -48,6 +54,7 @@
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import java.util.Objects;
@@ -129,10 +136,9 @@
}
}
- /**
- * Ensure the base dir for self-targeting is valid.
- */
+ /** Ensure the base dir for self-targeting is valid. */
@VisibleForTesting
+ @NonUiContext
public void ensureBaseDir() {
final String baseApkPath = mContext.getApplicationInfo().getBaseCodePath();
final Path baseApkFolderName = Path.of(baseApkPath).getParent().getFileName();
@@ -170,6 +176,16 @@
mBasePath = baseFile.toPath();
}
+ private boolean isSameWithTargetSignature(final String targetPackage) {
+ final PackageManager packageManager = mContext.getPackageManager();
+ final String packageName = mContext.getPackageName();
+ if (TextUtils.equals(packageName, targetPackage)) {
+ return true;
+ }
+ return packageManager.checkSignatures(packageName, targetPackage)
+ == PackageManager.SIGNATURE_MATCH;
+ }
+
/**
* Check if the overlay name is valid or not.
*
@@ -202,8 +218,12 @@
/**
* Save FabricatedOverlay instance as frro and idmap files.
*
+ * <p>In order to fill the overlayable policy, it's necessary to collect the information from
+ * app. And then, the information is passed to native layer to fill the overlayable policy
+ *
* @param overlayInternal the FabricatedOverlayInternal to be saved.
*/
+ @NonUiContext
public void registerFabricatedOverlay(@NonNull FabricatedOverlayInternal overlayInternal)
throws IOException, PackageManager.NameNotFoundException {
ensureBaseDir();
@@ -214,6 +234,9 @@
final String overlayName = checkOverlayNameValid(overlayInternal.overlayName);
checkPackageName(overlayInternal.packageName);
checkPackageName(overlayInternal.targetPackageName);
+ Preconditions.checkStringNotEmpty(
+ overlayInternal.targetOverlayable,
+ "Target overlayable should be neither null nor empty string.");
final ApplicationInfo applicationInfo = mContext.getApplicationInfo();
final String targetPackage = Preconditions.checkStringNotEmpty(
@@ -223,7 +246,17 @@
createFrroFile(frroPath.toString(), overlayInternal);
try {
- createIdmapFile(targetPackage, frroPath.toString(), idmapPath.toString(), overlayName);
+ createIdmapFile(
+ targetPackage,
+ frroPath.toString(),
+ idmapPath.toString(),
+ overlayName,
+ applicationInfo.isSystemApp() || applicationInfo.isSystemExt() /* isSystem */,
+ applicationInfo.isVendor(),
+ applicationInfo.isProduct(),
+ isSameWithTargetSignature(overlayInternal.targetPackageName),
+ applicationInfo.isOdm(),
+ applicationInfo.isOem());
} catch (IOException e) {
if (!frroPath.toFile().delete()) {
Log.w(TAG, "Failed to delete file " + frroPath);
@@ -237,6 +270,7 @@
*
* @param overlayName the specific name
*/
+ @NonUiContext
public void unregisterFabricatedOverlay(@NonNull String overlayName) {
ensureBaseDir();
checkOverlayNameValid(overlayName);
@@ -252,6 +286,46 @@
}
/**
+ * Commit the overlay manager transaction
+ *
+ * @param transaction the overlay manager transaction
+ */
+ @NonUiContext
+ public void commit(@NonNull OverlayManagerTransaction transaction)
+ throws PackageManager.NameNotFoundException, IOException {
+ Objects.requireNonNull(transaction);
+
+ for (Iterator<OverlayManagerTransaction.Request> it = transaction.iterator();
+ it.hasNext(); ) {
+ final OverlayManagerTransaction.Request request = it.next();
+ if (request.type == TYPE_REGISTER_FABRICATED) {
+ final FabricatedOverlayInternal fabricatedOverlayInternal =
+ Objects.requireNonNull(
+ request.extras.getParcelable(
+ BUNDLE_FABRICATED_OVERLAY,
+ FabricatedOverlayInternal.class));
+
+ // populate the mandatory data
+ if (TextUtils.isEmpty(fabricatedOverlayInternal.packageName)) {
+ fabricatedOverlayInternal.packageName = mContext.getPackageName();
+ } else {
+ if (!TextUtils.equals(
+ fabricatedOverlayInternal.packageName, mContext.getPackageName())) {
+ throw new IllegalArgumentException("Unknown package name in transaction");
+ }
+ }
+
+ registerFabricatedOverlay(fabricatedOverlayInternal);
+ } else if (request.type == TYPE_UNREGISTER_FABRICATED) {
+ final OverlayIdentifier overlayIdentifier = Objects.requireNonNull(request.overlay);
+ unregisterFabricatedOverlay(overlayIdentifier.getOverlayName());
+ } else {
+ throw new IllegalArgumentException("Unknown request in transaction " + request);
+ }
+ }
+ }
+
+ /**
* Get the list of overlays information for the target package name.
*
* @param targetPackage the target package name
@@ -315,7 +389,13 @@
@NonNull String targetPath,
@NonNull String overlayPath,
@NonNull String idmapPath,
- @NonNull String overlayName)
+ @NonNull String overlayName,
+ boolean isSystem,
+ boolean isVendor,
+ boolean isProduct,
+ boolean isSameWithTargetSignature,
+ boolean isOdm,
+ boolean isOem)
throws IOException;
private static native FabricatedOverlayInfo getFabricatedOverlayInfo(
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 9cb2e68..4b1753a 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -17,7 +17,7 @@
package com.android.internal.telephony;
import android.telephony.BarringInfo;
-import android.telephony.CallState;
+import android.telephony.CallAttributes;
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.DataConnectionRealTimeInfo;
@@ -62,7 +62,7 @@
void onPhoneCapabilityChanged(in PhoneCapability capability);
void onActiveDataSubIdChanged(in int subId);
void onRadioPowerStateChanged(in int state);
- void onCallStatesChanged(in List<CallState> callStateList);
+ void onCallAttributesChanged(in CallAttributes callAttributes);
@SuppressWarnings(value={"untyped-collection"})
void onEmergencyNumberListChanged(in Map emergencyNumberList);
void onOutgoingEmergencyCall(in EmergencyNumber placedEmergencyNumber, int subscriptionId);
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 7ba2686..c7fa757 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -66,8 +66,8 @@
void notifyCellLocationForSubscriber(in int subId, in CellIdentity cellLocation);
@UnsupportedAppUsage
void notifyCellInfo(in List<CellInfo> cellInfo);
- void notifyPreciseCallState(int phoneId, int subId, in int[] callStates, in String[] imsCallIds,
- in int[] imsCallServiceTypes, in int[] imsCallTypes);
+ void notifyPreciseCallState(int phoneId, int subId, int ringingCallState,
+ int foregroundCallState, int backgroundCallState);
void notifyDisconnectCause(int phoneId, int subId, int disconnectCause,
int preciseDisconnectCause);
void notifyCellInfoForSubscriber(in int subId, in List<CellInfo> cellInfo);
diff --git a/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp b/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp
index df55e42..bba1760 100644
--- a/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp
+++ b/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp
@@ -123,8 +123,12 @@
bool callCreateIdmapFile(std::string& out_error, const std::string& targetPath,
const std::string& overlayPath, const std::string& idmapPath,
- const std::string& overlayName) {
- return createIdmapFileFuncPtr_(out_error, targetPath, overlayPath, idmapPath, overlayName);
+ const std::string& overlayName, const bool isSystem,
+ const bool isVendor, const bool isProduct,
+ const bool isTargetSignature, const bool isOdm, const bool isOem) {
+ return createIdmapFileFuncPtr_(out_error, targetPath, overlayPath, idmapPath, overlayName,
+ isSystem, isVendor, isProduct, isTargetSignature, isOdm,
+ isOem);
}
bool callGetFabricatedOverlayInfo(std::string& out_error, const std::string& overlay_path,
@@ -158,7 +162,10 @@
typedef bool (*CreateIdmapFileFunc)(std::string& out_error, const std::string& targetPath,
const std::string& overlayPath,
const std::string& idmapPath,
- const std::string& overlayName);
+ const std::string& overlayName, const jboolean isSystem,
+ const jboolean isVendor, const jboolean isProduct,
+ const jboolean isSameWithTargetSignature,
+ const jboolean isOdm, const jboolean isOem);
typedef bool (*GetFabricatedOverlayInfoFunc)(std::string& out_error,
const std::string& overlay_path,
@@ -295,7 +302,9 @@
}
static void CreateIdmapFile(JNIEnv* env, jclass /* clazz */, jstring jsTargetPath,
- jstring jsOverlayPath, jstring jsIdmapPath, jstring jsOverlayName) {
+ jstring jsOverlayPath, jstring jsIdmapPath, jstring jsOverlayName,
+ jboolean isSystem, jboolean isVendor, jboolean isProduct,
+ jboolean isTargetSignature, jboolean isOdm, jboolean isOem) {
DynamicLibraryLoader& dlLoader = EnsureDynamicLibraryLoader(env);
if (!dlLoader) {
jniThrowNullPointerException(env, "libidmap2 is not loaded");
@@ -327,7 +336,10 @@
std::string err_result;
if (!dlLoader.callCreateIdmapFile(err_result, targetPath.c_str(), overlayPath.c_str(),
- idmapPath.c_str(), overlayName.c_str())) {
+ idmapPath.c_str(), overlayName.c_str(),
+ (isSystem == JNI_TRUE), (isVendor == JNI_TRUE),
+ (isProduct == JNI_TRUE), (isTargetSignature == JNI_TRUE),
+ (isOdm == JNI_TRUE), (isOem == JNI_TRUE))) {
jniThrowException(env, kIOException, err_result.c_str());
return;
}
@@ -374,7 +386,7 @@
{"createFrroFile", "(Ljava/lang/String;Landroid/os/FabricatedOverlayInternal;)V",
reinterpret_cast<void*>(self_targeting::CreateFrroFile)},
{"createIdmapFile",
- "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZZZZ)V",
reinterpret_cast<void*>(self_targeting::CreateIdmapFile)},
{"getFabricatedOverlayInfo", "(Ljava/lang/String;)Landroid/os/FabricatedOverlayInfo;",
reinterpret_cast<void*>(self_targeting::GetFabricatedOverlayInfo)},
diff --git a/core/tests/overlaytests/device_self_targeting/Android.bp b/core/tests/overlaytests/device_self_targeting/Android.bp
index 82998db..063c569 100644
--- a/core/tests/overlaytests/device_self_targeting/Android.bp
+++ b/core/tests/overlaytests/device_self_targeting/Android.bp
@@ -29,6 +29,7 @@
"androidx.test.rules",
"androidx.test.runner",
"androidx.test.ext.junit",
+ "mockito-target-minus-junit4",
"truth-prebuilt",
],
diff --git a/core/tests/overlaytests/device_self_targeting/res/values/overlayable.xml b/core/tests/overlaytests/device_self_targeting/res/values/overlayable.xml
new file mode 100644
index 0000000..5cc214d
--- /dev/null
+++ b/core/tests/overlaytests/device_self_targeting/res/values/overlayable.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ 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.
+ -->
+
+<resources>
+ <overlayable name="PublicOverlayable" actor="overlay://theme">
+ <!-- The app with the same signature can overlay the below resources -->
+ <policy type="public">
+ <item type="color" name="public_overlayable_color" />
+ </policy>
+ </overlayable>
+
+ <overlayable name="SignatureOverlayable" actor="overlay://theme">
+ <!-- The app with the same signature can overlay the below resources -->
+ <policy type="signature">
+ <item type="color" name="mycolor" />
+ <item type="color" name="signature_overlayable_color" />
+ <item type="string" name="mystring" />
+ <item type="drawable" name="mydrawable" />
+ </policy>
+ </overlayable>
+
+ <overlayable name="SystemAppOverlayable" actor="overlay://theme">
+ <!-- The app in system partition can overlay the below resources -->
+ <policy type="system">
+ <item type="color" name="system_app_overlayable_color" />
+ </policy>
+ </overlayable>
+
+ <overlayable name="OdmOverlayable" actor="overlay://theme">
+ <!-- The app with the same signature can overlay the below resources -->
+ <policy type="odm">
+ <item type="color" name="odm_overlayable_color" />
+ </policy>
+ </overlayable>
+
+ <overlayable name="OemOverlayable" actor="overlay://theme">
+ <!-- The app with the same signature can overlay the below resources -->
+ <policy type="oem">
+ <item type="color" name="oem_overlayable_color" />
+ </policy>
+ </overlayable>
+
+ <overlayable name="VendorOverlayable" actor="overlay://theme">
+ <!-- The app with the same signature can overlay the below resources -->
+ <policy type="vendor">
+ <item type="color" name="vendor_overlayable_color" />
+ </policy>
+ </overlayable>
+
+ <overlayable name="ProductOverlayable" actor="overlay://theme">
+ <!-- The app with the same signature can overlay the below resources -->
+ <policy type="product">
+ <item type="color" name="product_overlayable_color" />
+ </policy>
+ </overlayable>
+
+ <overlayable name="ActorOverlayable" actor="overlay://theme">
+ <!-- The app with the same signature can overlay the below resources -->
+ <policy type="actor">
+ <item type="color" name="actor_overlayable_color" />
+ </policy>
+ </overlayable>
+
+ <overlayable name="ConfigOverlayable" actor="overlay://theme">
+ <!-- The app with the same signature can overlay the below resources -->
+ <policy type="config_signature">
+ <item type="color" name="config_overlayable_color" />
+ </policy>
+ </overlayable>
+
+</resources>
diff --git a/core/tests/overlaytests/device_self_targeting/res/values/values.xml b/core/tests/overlaytests/device_self_targeting/res/values/values.xml
index f0b4a6f..d82de97 100644
--- a/core/tests/overlaytests/device_self_targeting/res/values/values.xml
+++ b/core/tests/overlaytests/device_self_targeting/res/values/values.xml
@@ -17,4 +17,14 @@
<resources>
<color name="mycolor">#ff112233</color>
<string name="mystring">hello</string>
+
+ <color name="public_overlayable_color">#000</color>
+ <color name="signature_overlayable_color">#000</color>
+ <color name="system_app_overlayable_color">#000</color>
+ <color name="odm_overlayable_color">#000</color>
+ <color name="oem_overlayable_color">#000</color>
+ <color name="vendor_overlayable_color">#000</color>
+ <color name="product_overlayable_color">#000</color>
+ <color name="actor_overlayable_color">#000</color>
+ <color name="config_overlayable_color">#000</color>
</resources>
diff --git a/core/tests/overlaytests/device_self_targeting/src/com/android/overlaytest/OverlayManagerImplTest.java b/core/tests/overlaytests/device_self_targeting/src/com/android/overlaytest/OverlayManagerImplTest.java
index ca58410..40d0bef 100644
--- a/core/tests/overlaytests/device_self_targeting/src/com/android/overlaytest/OverlayManagerImplTest.java
+++ b/core/tests/overlaytests/device_self_targeting/src/com/android/overlaytest/OverlayManagerImplTest.java
@@ -17,15 +17,24 @@
package com.android.overlaytest;
import static android.content.Context.MODE_PRIVATE;
+import static android.content.pm.PackageManager.SIGNATURE_NO_MATCH;
import static com.android.internal.content.om.OverlayManagerImpl.SELF_TARGET;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.content.Context;
import android.content.ContextWrapper;
+import android.content.om.FabricatedOverlay;
import android.content.om.OverlayInfo;
+import android.content.om.OverlayManagerTransaction;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.FabricatedOverlayInternal;
@@ -72,11 +81,23 @@
private static final String TARGET_COLOR_RES = "color/mycolor";
private static final String TARGET_STRING_RES = "string/mystring";
private static final String TARGET_DRAWABLE_RES = "drawable/mydrawable";
+ private static final String PUBLIC_OVERLAYABLE = "PublicOverlayable";
+ private static final String SIGNATURE_OVERLAYABLE = "SignatureOverlayable";
+ private static final String SYSTEM_APP_OVERLAYABLE = "SystemAppOverlayable";
+ private static final String ODM_OVERLAYABLE = "OdmOverlayable";
+ private static final String OEM_OVERLAYABLE = "OemOverlayable";
+ private static final String VENDOR_OVERLAYABLE = "VendorOverlayable";
+ private static final String PRODUCT_OVERLAYABLE = "ProductOverlayable";
+ private static final String ACTOR_OVERLAYABLE = "ActorOverlayable";
+ private static final String CONFIG_OVERLAYABLE = "ConfigOverlayable";
private Context mContext;
private OverlayManagerImpl mOverlayManagerImpl;
private String mOverlayName;
+ private PackageManager mMockPackageManager;
+ private ApplicationInfo mMockApplicationInfo;
+
@Rule public TestName mTestName = new TestName();
@Rule public Expect expect = Expect.create();
@@ -111,7 +132,36 @@
public void setUp() throws IOException {
clearDir();
mOverlayName = mTestName.getMethodName();
- mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+ mMockApplicationInfo = mock(ApplicationInfo.class);
+ when(mMockApplicationInfo.isSystemApp()).thenReturn(false);
+ when(mMockApplicationInfo.isSystemExt()).thenReturn(false);
+ when(mMockApplicationInfo.isOdm()).thenReturn(false);
+ when(mMockApplicationInfo.isOem()).thenReturn(false);
+ when(mMockApplicationInfo.isVendor()).thenReturn(false);
+ when(mMockApplicationInfo.isProduct()).thenReturn(false);
+ when(mMockApplicationInfo.getBaseCodePath()).thenReturn(
+ context.getApplicationInfo().getBaseCodePath());
+ mMockApplicationInfo.sourceDir = context.getApplicationInfo().sourceDir;
+
+ mMockPackageManager = mock(PackageManager.class);
+ when(mMockPackageManager.checkSignatures(anyString(), anyString()))
+ .thenReturn(SIGNATURE_NO_MATCH);
+
+ mContext =
+ new ContextWrapper(context) {
+ @Override
+ public ApplicationInfo getApplicationInfo() {
+ return mMockApplicationInfo;
+ }
+
+ @Override
+ public PackageManager getPackageManager() {
+ return mMockPackageManager;
+ }
+ };
+
mOverlayManagerImpl = new OverlayManagerImpl(mContext);
}
@@ -144,12 +194,14 @@
private <T> FabricatedOverlayInternal createOverlayWithName(
@NonNull String overlayName,
+ @NonNull String targetOverlayable,
@NonNull String targetPackageName,
@NonNull List<Pair<String, Pair<String, T>>> entryDefinitions) {
final String packageName = mContext.getPackageName();
FabricatedOverlayInternal overlayInternal = new FabricatedOverlayInternal();
overlayInternal.overlayName = overlayName;
overlayInternal.targetPackageName = targetPackageName;
+ overlayInternal.targetOverlayable = targetOverlayable;
overlayInternal.packageName = packageName;
addOverlayEntry(overlayInternal, entryDefinitions);
@@ -162,6 +214,7 @@
FabricatedOverlayInternal overlayInternal =
createOverlayWithName(
mOverlayName,
+ SYSTEM_APP_OVERLAYABLE,
"android",
List.of(Pair.create("color/white", Pair.create(null, Color.BLACK))));
@@ -190,6 +243,7 @@
FabricatedOverlayInternal overlayInternal =
createOverlayWithName(
mOverlayName,
+ SIGNATURE_OVERLAYABLE,
mContext.getPackageName(),
List.of(Pair.create(TARGET_COLOR_RES, Pair.create(null, Color.WHITE))));
@@ -215,6 +269,7 @@
FabricatedOverlayInternal overlayInternal =
createOverlayWithName(
mOverlayName,
+ SIGNATURE_OVERLAYABLE,
mContext.getPackageName(),
List.of(Pair.create(TARGET_STRING_RES, Pair.create(null, "HELLO"))));
@@ -242,6 +297,7 @@
FabricatedOverlayInternal overlayInternal =
createOverlayWithName(
mOverlayName,
+ SIGNATURE_OVERLAYABLE,
mContext.getPackageName(),
List.of(Pair.create(TARGET_DRAWABLE_RES,
Pair.create(null, parcelFileDescriptor))));
@@ -268,6 +324,7 @@
FabricatedOverlayInternal overlayInternal =
createOverlayWithName(
mOverlayName,
+ SIGNATURE_OVERLAYABLE,
mContext.getPackageName(),
List.of(Pair.create("color/not_existed", Pair.create(null, "HELLO"))));
@@ -301,6 +358,7 @@
FabricatedOverlayInternal overlayInternal =
createOverlayWithName(
mOverlayName,
+ SIGNATURE_OVERLAYABLE,
mContext.getPackageName(),
List.of(Pair.create(TARGET_COLOR_RES, Pair.create(null, Color.WHITE))));
mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
@@ -309,6 +367,7 @@
overlayInternal =
createOverlayWithName(
secondOverlayName,
+ SIGNATURE_OVERLAYABLE,
mContext.getPackageName(),
List.of(Pair.create(TARGET_COLOR_RES, Pair.create(null, Color.WHITE))));
mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
@@ -341,6 +400,7 @@
FabricatedOverlayInternal overlayInternal =
createOverlayWithName(
mOverlayName,
+ SIGNATURE_OVERLAYABLE,
mContext.getPackageName(),
List.of(Pair.create(TARGET_COLOR_RES, Pair.create(null, Color.WHITE))));
mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
@@ -349,6 +409,7 @@
overlayInternal =
createOverlayWithName(
mOverlayName,
+ SIGNATURE_OVERLAYABLE,
mContext.getPackageName(),
List.of(Pair.create(TARGET_COLOR_RES, Pair.create(null, Color.WHITE))));
mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
@@ -392,6 +453,40 @@
}
@Test
+ public void commit_withNullTransaction_shouldFail() {
+ assertThrows(NullPointerException.class, () -> mOverlayManagerImpl.commit(null));
+ }
+
+ @Test
+ public void commitRegisterOverlay_fromOtherBuilder_shouldWork()
+ throws PackageManager.NameNotFoundException, IOException {
+ FabricatedOverlay overlay =
+ new FabricatedOverlay.Builder(
+ mContext.getPackageName(), mOverlayName, mContext.getPackageName())
+ .setTargetOverlayable(SIGNATURE_OVERLAYABLE)
+ .setResourceValue(
+ TARGET_COLOR_RES, TypedValue.TYPE_INT_COLOR_ARGB8, Color.WHITE)
+ .build();
+ OverlayManagerTransaction transaction =
+ new OverlayManagerTransaction.Builder().registerFabricatedOverlay(overlay).build();
+
+ mOverlayManagerImpl.commit(transaction);
+
+ final List<OverlayInfo> overlayInfos =
+ mOverlayManagerImpl.getOverlayInfosForTarget(mContext.getPackageName());
+ final int firstNumberOfOverlays = overlayInfos.size();
+ expect.that(firstNumberOfOverlays).isEqualTo(1);
+ final OverlayInfo overlayInfo = overlayInfos.get(0);
+ expect.that(overlayInfo).isNotNull();
+ Truth.assertThat(expect.hasFailures()).isFalse();
+ expect.that(overlayInfo.isFabricated()).isTrue();
+ expect.that(overlayInfo.getOverlayName()).isEqualTo(mOverlayName);
+ expect.that(overlayInfo.getPackageName()).isEqualTo(mContext.getPackageName());
+ expect.that(overlayInfo.getTargetPackageName()).isEqualTo(mContext.getPackageName());
+ expect.that(overlayInfo.getUserId()).isEqualTo(mContext.getUserId());
+ }
+
+ @Test
public void newOverlayManagerImpl_forOtherUser_shouldFail() {
Context fakeContext =
new ContextWrapper(mContext) {
@@ -408,4 +503,177 @@
assertThrows(SecurityException.class, () -> new OverlayManagerImpl(fakeContext));
}
+
+ FabricatedOverlayInternal prepareFabricatedOverlayInternal(
+ String targetOverlayableName, String targetEntryName) {
+ return createOverlayWithName(
+ mOverlayName,
+ targetOverlayableName,
+ mContext.getPackageName(),
+ List.of(
+ Pair.create(
+ targetEntryName,
+ Pair.create(null, Color.WHITE))));
+ }
+
+ @Test
+ public void registerOverlayOnSystemOverlayable_selfIsNotSystemApp_shouldFail() {
+ final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+ SYSTEM_APP_OVERLAYABLE,
+ "color/system_app_overlayable_color");
+
+ assertThrows(
+ IOException.class,
+ () -> mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal));
+ }
+
+ @Test
+ public void registerOverlayOnOdmOverlayable_selfIsNotOdm_shouldFail() {
+ final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+ ODM_OVERLAYABLE,
+ "color/odm_overlayable_color");
+
+ assertThrows(
+ IOException.class,
+ () -> mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal));
+ }
+
+ @Test
+ public void registerOverlayOnOemOverlayable_selfIsNotOem_shouldFail() {
+ final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+ OEM_OVERLAYABLE,
+ "color/oem_overlayable_color");
+
+ assertThrows(
+ IOException.class,
+ () -> mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal));
+ }
+
+ @Test
+ public void registerOverlayOnVendorOverlayable_selfIsNotVendor_shouldFail() {
+ final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+ VENDOR_OVERLAYABLE,
+ "color/vendor_overlayable_color");
+
+ assertThrows(
+ IOException.class,
+ () -> mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal));
+ }
+
+ @Test
+ public void registerOverlayOnProductOverlayable_selfIsNotProduct_shouldFail() {
+ final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+ PRODUCT_OVERLAYABLE,
+ "color/product_overlayable_color");
+
+ assertThrows(
+ IOException.class,
+ () -> mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal));
+ }
+
+ @Test
+ public void registerOverlayOnActorOverlayable_notSupport_shouldFail() {
+ final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+ ACTOR_OVERLAYABLE,
+ "color/actor_overlayable_color");
+
+ assertThrows(
+ IOException.class,
+ () -> mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal));
+ }
+
+ @Test
+ public void registerOverlayOnConfigOverlayable_notSupport_shouldFail() {
+ final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+ CONFIG_OVERLAYABLE,
+ "color/config_overlayable_color");
+
+ assertThrows(
+ IOException.class,
+ () -> mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal));
+ }
+
+ @Test
+ public void registerOverlayOnPublicOverlayable_shouldAlwaysSucceed()
+ throws PackageManager.NameNotFoundException, IOException {
+ final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+ PUBLIC_OVERLAYABLE,
+ "color/public_overlayable_color");
+
+ mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
+
+ assertThat(mOverlayManagerImpl.getOverlayInfosForTarget(mContext.getPackageName()).size())
+ .isEqualTo(1);
+ }
+
+ @Test
+ public void registerOverlayOnSystemOverlayable_selfIsSystemApp_shouldSucceed()
+ throws PackageManager.NameNotFoundException, IOException {
+ final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+ SYSTEM_APP_OVERLAYABLE,
+ "color/system_app_overlayable_color");
+ when(mMockApplicationInfo.isSystemApp()).thenReturn(true);
+ when(mMockApplicationInfo.isSystemExt()).thenReturn(true);
+
+ mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
+
+ assertThat(mOverlayManagerImpl.getOverlayInfosForTarget(mContext.getPackageName()).size())
+ .isEqualTo(1);
+ }
+
+ @Test
+ public void registerOverlayOnOdmOverlayable_selfIsOdm_shouldSucceed()
+ throws PackageManager.NameNotFoundException, IOException {
+ final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+ ODM_OVERLAYABLE,
+ "color/odm_overlayable_color");
+ when(mMockApplicationInfo.isOdm()).thenReturn(true);
+
+ mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
+
+ assertThat(mOverlayManagerImpl.getOverlayInfosForTarget(mContext.getPackageName()).size())
+ .isEqualTo(1);
+ }
+
+ @Test
+ public void registerOverlayOnOemOverlayable_selfIsOem_shouldSucceed()
+ throws PackageManager.NameNotFoundException, IOException {
+ final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+ OEM_OVERLAYABLE,
+ "color/oem_overlayable_color");
+ when(mMockApplicationInfo.isOem()).thenReturn(true);
+
+ mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
+
+ assertThat(mOverlayManagerImpl.getOverlayInfosForTarget(mContext.getPackageName()).size())
+ .isEqualTo(1);
+ }
+
+ @Test
+ public void registerOverlayOnVendorOverlayable_selfIsVendor_shouldSucceed()
+ throws PackageManager.NameNotFoundException, IOException {
+ final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+ VENDOR_OVERLAYABLE,
+ "color/vendor_overlayable_color");
+ when(mMockApplicationInfo.isVendor()).thenReturn(true);
+
+ mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
+
+ assertThat(mOverlayManagerImpl.getOverlayInfosForTarget(mContext.getPackageName()).size())
+ .isEqualTo(1);
+ }
+
+ @Test
+ public void registerOverlayOnProductOverlayable_selfIsProduct_shouldSucceed()
+ throws PackageManager.NameNotFoundException, IOException {
+ final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+ PRODUCT_OVERLAYABLE,
+ "color/product_overlayable_color");
+ when(mMockApplicationInfo.isProduct()).thenReturn(true);
+
+ mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
+
+ assertThat(mOverlayManagerImpl.getOverlayInfosForTarget(mContext.getPackageName()).size())
+ .isEqualTo(1);
+ }
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
index 2bede9a..94bd057 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
@@ -39,6 +39,7 @@
import android.os.Binder
import android.os.Bundle
import android.os.ResultReceiver
+import android.service.credentials.CredentialProviderService
import com.android.credentialmanager.createflow.ActiveEntry
import com.android.credentialmanager.createflow.CreateCredentialUiState
import com.android.credentialmanager.createflow.CreateScreenState
@@ -390,11 +391,12 @@
intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
or PendingIntent.FLAG_ONE_SHOT))
val createPasswordRequest = android.service.credentials.CreateCredentialRequest(
- context.applicationInfo.packageName,
- "PASSWORD",
- toBundle("beckett-bakert@gmail.com", "password123")
+ context.applicationInfo.packageName,
+ TYPE_PASSWORD_CREDENTIAL,
+ toBundle("beckett-bakert@gmail.com", "password123")
)
- val fillInIntent = Intent().putExtra("create_request_params", createPasswordRequest)
+ val fillInIntent = Intent().putExtra(CredentialProviderService.EXTRA_CREATE_CREDENTIAL_REQUEST,
+ createPasswordRequest)
val slice = Slice.Builder(
Entry.CREDENTIAL_MANAGER_ENTRY_URI, SliceSpec(Entry.VERSION, 1)
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/button/ActionButtonsPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/button/ActionButtonsPage.kt
index 96e2498..decc292 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/button/ActionButtonsPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/button/ActionButtonsPage.kt
@@ -46,7 +46,6 @@
fun buildInjectEntry(): SettingsEntryBuilder {
return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
- .setIsAllowSearch(true)
.setUiLayoutFn {
Preference(object : PreferenceModel {
override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/dialog/AlterDialogPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/dialog/AlterDialogPage.kt
index a57df0f..063b61c 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/dialog/AlterDialogPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/dialog/AlterDialogPage.kt
@@ -50,7 +50,6 @@
)
fun buildInjectEntry() = SettingsEntryBuilder.createInject(owner)
- .setIsAllowSearch(true)
.setUiLayoutFn {
Preference(object : PreferenceModel {
override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt
index 7958d11..42ac1ac 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt
@@ -55,7 +55,6 @@
entryList.add(
createEntry(owner, EntryEnum.STRING_PARAM)
// Set attributes
- .setIsAllowSearch(true)
.setIsSearchDataDynamic(true)
.setSearchDataFn { ArgumentPageModel.genStringParamSearchData() }
.setUiLayoutFn {
@@ -67,7 +66,6 @@
entryList.add(
createEntry(owner, EntryEnum.INT_PARAM)
// Set attributes
- .setIsAllowSearch(true)
.setIsSearchDataDynamic(true)
.setSearchDataFn { ArgumentPageModel.genIntParamSearchData() }
.setUiLayoutFn {
@@ -90,8 +88,6 @@
owner = createSettingsPage(arguments),
displayName = "${name}_$stringParam",
)
- // Set attributes
- .setIsAllowSearch(false)
.setSearchDataFn { ArgumentPageModel.genInjectSearchData() }
.setUiLayoutFn {
// Set ui rendering
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ChartPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ChartPage.kt
index 160e77b..7f21a4d 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ChartPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ChartPage.kt
@@ -134,7 +134,6 @@
fun buildInjectEntry(): SettingsEntryBuilder {
return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
- .setIsAllowSearch(true)
.setUiLayoutFn {
Preference(object : PreferenceModel {
override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt
index c903cfd..9f24ea9 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt
@@ -20,6 +20,7 @@
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.common.EntrySearchData
import com.android.settingslib.spa.framework.common.SettingsEntry
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
import com.android.settingslib.spa.framework.common.SettingsPage
@@ -42,7 +43,7 @@
val entryList = mutableListOf<SettingsEntry>()
entryList.add(
SettingsEntryBuilder.create( "Some Preference", owner)
- .setIsAllowSearch(true)
+ .setSearchDataFn { EntrySearchData(title = "Some Preference") }
.setUiLayoutFn {
Preference(remember {
object : PreferenceModel {
@@ -58,7 +59,6 @@
fun buildInjectEntry(): SettingsEntryBuilder {
return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
- .setIsAllowSearch(true)
.setUiLayoutFn {
Preference(object : PreferenceModel {
override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/IllustrationPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/IllustrationPage.kt
index e10cf3a..ddf66aa 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/IllustrationPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/IllustrationPage.kt
@@ -72,7 +72,6 @@
fun buildInjectEntry(): SettingsEntryBuilder {
return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
- .setIsAllowSearch(true)
.setUiLayoutFn {
Preference(object : PreferenceModel {
override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/LoadingBarPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/LoadingBarPage.kt
index c354930..4332a81 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/LoadingBarPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/LoadingBarPage.kt
@@ -46,7 +46,6 @@
fun buildInjectEntry(): SettingsEntryBuilder {
return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
- .setIsAllowSearch(true)
.setUiLayoutFn {
Preference(object : PreferenceModel {
override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ProgressBarPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ProgressBarPage.kt
index 1f76557..20d90dd 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ProgressBarPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ProgressBarPage.kt
@@ -48,7 +48,6 @@
fun buildInjectEntry(): SettingsEntryBuilder {
return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
- .setIsAllowSearch(true)
.setUiLayoutFn {
Preference(object : PreferenceModel {
override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SettingsPagerPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SettingsPagerPage.kt
index cb58a95..c0d0abc 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SettingsPagerPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SettingsPagerPage.kt
@@ -40,7 +40,6 @@
fun buildInjectEntry(): SettingsEntryBuilder {
return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
- .setIsAllowSearch(true)
.setUiLayoutFn {
Preference(object : PreferenceModel {
override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt
index 73b34a5..a62ec7b 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt
@@ -48,7 +48,6 @@
val entryList = mutableListOf<SettingsEntry>()
entryList.add(
SettingsEntryBuilder.create("Simple Slider", owner)
- .setIsAllowSearch(true)
.setUiLayoutFn {
SliderPreference(object : SliderPreferenceModel {
override val title = "Simple Slider"
@@ -58,7 +57,6 @@
)
entryList.add(
SettingsEntryBuilder.create("Slider with icon", owner)
- .setIsAllowSearch(true)
.setUiLayoutFn {
SliderPreference(object : SliderPreferenceModel {
override val title = "Slider with icon"
@@ -72,7 +70,6 @@
)
entryList.add(
SettingsEntryBuilder.create("Slider with changeable icon", owner)
- .setIsAllowSearch(true)
.setUiLayoutFn {
val initValue = 0
var icon by remember { mutableStateOf(Icons.Outlined.MusicOff) }
@@ -93,7 +90,6 @@
)
entryList.add(
SettingsEntryBuilder.create("Slider with steps", owner)
- .setIsAllowSearch(true)
.setUiLayoutFn {
SliderPreference(object : SliderPreferenceModel {
override val title = "Slider with steps"
@@ -109,7 +105,6 @@
fun buildInjectEntry(): SettingsEntryBuilder {
return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
- .setIsAllowSearch(true)
.setUiLayoutFn {
Preference(object : PreferenceModel {
override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt
index f38a8d4..67e35dc 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt
@@ -44,14 +44,12 @@
val entryList = mutableListOf<SettingsEntry>()
entryList.add(
SettingsEntryBuilder.create( "MainSwitchPreference", owner)
- .setIsAllowSearch(true)
.setUiLayoutFn {
SampleMainSwitchPreference()
}.build()
)
entryList.add(
SettingsEntryBuilder.create( "MainSwitchPreference not changeable", owner)
- .setIsAllowSearch(true)
.setUiLayoutFn {
SampleNotChangeableMainSwitchPreference()
}.build()
@@ -62,7 +60,6 @@
fun buildInjectEntry(): SettingsEntryBuilder {
return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
- .setIsAllowSearch(true)
.setUiLayoutFn {
Preference(object : PreferenceModel {
override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferenceMain.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferenceMain.kt
index 61925a7..eddede7 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferenceMain.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferenceMain.kt
@@ -43,7 +43,6 @@
fun buildInjectEntry(): SettingsEntryBuilder {
return SettingsEntryBuilder.createInject(owner = owner)
- .setIsAllowSearch(true)
.setUiLayoutFn {
Preference(object : PreferenceModel {
override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePage.kt
index ff89f2b..0c9a043 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePage.kt
@@ -87,7 +87,6 @@
val entryList = mutableListOf<SettingsEntry>()
entryList.add(
createEntry(EntryEnum.SIMPLE_PREFERENCE)
- .setIsAllowSearch(true)
.setMacro {
spaLogger.message(TAG, "create macro for ${EntryEnum.SIMPLE_PREFERENCE}")
SimplePreferenceMacro(title = SIMPLE_PREFERENCE_TITLE)
@@ -96,7 +95,6 @@
)
entryList.add(
createEntry(EntryEnum.SUMMARY_PREFERENCE)
- .setIsAllowSearch(true)
.setMacro {
spaLogger.message(TAG, "create macro for ${EntryEnum.SUMMARY_PREFERENCE}")
SimplePreferenceMacro(
@@ -110,7 +108,6 @@
entryList.add(singleLineSummaryEntry())
entryList.add(
createEntry(EntryEnum.DISABLED_PREFERENCE)
- .setIsAllowSearch(true)
.setHasMutableStatus(true)
.setMacro {
spaLogger.message(TAG, "create macro for ${EntryEnum.DISABLED_PREFERENCE}")
@@ -126,7 +123,6 @@
)
entryList.add(
createEntry(EntryEnum.ASYNC_SUMMARY_PREFERENCE)
- .setIsAllowSearch(true)
.setHasMutableStatus(true)
.setSearchDataFn {
EntrySearchData(title = ASYNC_PREFERENCE_TITLE)
@@ -165,7 +161,6 @@
)
entryList.add(
createEntry(EntryEnum.MANUAL_UPDATE_PREFERENCE)
- .setIsAllowSearch(true)
.setUiLayoutFn {
val model = PreferencePageModel.create()
val manualUpdaterSummary = remember { model.getManualUpdaterSummary() }
@@ -179,7 +174,8 @@
}
}
)
- }.setSliceDataFn { sliceUri, args ->
+ }
+ .setSliceDataFn { sliceUri, args ->
val createSliceImpl = { v: Int ->
createDemoActionSlice(
sliceUri = sliceUri,
@@ -204,7 +200,6 @@
)
entryList.add(
createEntry(EntryEnum.AUTO_UPDATE_PREFERENCE)
- .setIsAllowSearch(true)
.setUiLayoutFn {
val model = PreferencePageModel.create()
val autoUpdaterSummary = remember { model.getAutoUpdaterSummary() }
@@ -251,7 +246,6 @@
}
private fun singleLineSummaryEntry() = createEntry(EntryEnum.SINGLE_LINE_SUMMARY_PREFERENCE)
- .setIsAllowSearch(true)
.setUiLayoutFn {
Preference(
model = object : PreferenceModel {
@@ -267,7 +261,6 @@
fun buildInjectEntry(): SettingsEntryBuilder {
return SettingsEntryBuilder.createInject(owner = owner)
- .setIsAllowSearch(true)
.setMacro {
spaLogger.message(TAG, "create macro for INJECT entry")
SimplePreferenceMacro(
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePage.kt
index dab04fd..067911c 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePage.kt
@@ -49,35 +49,30 @@
val entryList = mutableListOf<SettingsEntry>()
entryList.add(
SettingsEntryBuilder.create( "SwitchPreference", owner)
- .setIsAllowSearch(true)
.setUiLayoutFn {
SampleSwitchPreference()
}.build()
)
entryList.add(
SettingsEntryBuilder.create( "SwitchPreference with summary", owner)
- .setIsAllowSearch(true)
.setUiLayoutFn {
SampleSwitchPreferenceWithSummary()
}.build()
)
entryList.add(
SettingsEntryBuilder.create( "SwitchPreference with async summary", owner)
- .setIsAllowSearch(true)
.setUiLayoutFn {
SampleSwitchPreferenceWithAsyncSummary()
}.build()
)
entryList.add(
SettingsEntryBuilder.create( "SwitchPreference not changeable", owner)
- .setIsAllowSearch(true)
.setUiLayoutFn {
SampleNotChangeableSwitchPreference()
}.build()
)
entryList.add(
SettingsEntryBuilder.create( "SwitchPreference with icon", owner)
- .setIsAllowSearch(true)
.setUiLayoutFn {
SampleSwitchPreferenceWithIcon()
}.build()
@@ -88,7 +83,6 @@
fun buildInjectEntry(): SettingsEntryBuilder {
return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
- .setIsAllowSearch(true)
.setUiLayoutFn {
Preference(object : PreferenceModel {
override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePage.kt
index 22da99c..33e5e8d 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePage.kt
@@ -46,28 +46,24 @@
val entryList = mutableListOf<SettingsEntry>()
entryList.add(
SettingsEntryBuilder.create( "TwoTargetSwitchPreference", owner)
- .setIsAllowSearch(true)
.setUiLayoutFn {
SampleTwoTargetSwitchPreference()
}.build()
)
entryList.add(
SettingsEntryBuilder.create( "TwoTargetSwitchPreference with summary", owner)
- .setIsAllowSearch(true)
.setUiLayoutFn {
SampleTwoTargetSwitchPreferenceWithSummary()
}.build()
)
entryList.add(
SettingsEntryBuilder.create( "TwoTargetSwitchPreference with async summary", owner)
- .setIsAllowSearch(true)
.setUiLayoutFn {
SampleTwoTargetSwitchPreferenceWithAsyncSummary()
}.build()
)
entryList.add(
SettingsEntryBuilder.create( "TwoTargetSwitchPreference not changeable", owner)
- .setIsAllowSearch(true)
.setUiLayoutFn {
SampleNotChangeableTwoTargetSwitchPreference()
}.build()
@@ -78,7 +74,6 @@
fun buildInjectEntry(): SettingsEntryBuilder {
return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
- .setIsAllowSearch(true)
.setUiLayoutFn {
Preference(object : PreferenceModel {
override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/CategoryPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/CategoryPage.kt
index d87cbe8..cb58abf6 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/CategoryPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/CategoryPage.kt
@@ -39,7 +39,6 @@
fun buildInjectEntry(): SettingsEntryBuilder {
return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
- .setIsAllowSearch(true)
.setUiLayoutFn {
Preference(object : PreferenceModel {
override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPage.kt
index ec2f436..ba769d2 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPage.kt
@@ -40,7 +40,6 @@
fun buildInjectEntry(): SettingsEntryBuilder {
return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
- .setIsAllowSearch(true)
.setUiLayoutFn {
Preference(object : PreferenceModel {
override val title = TITLE
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/common/Contexts.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/common/Contexts.kt
index bb1cd6e..76f6611 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/common/Contexts.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/common/Contexts.kt
@@ -16,6 +16,7 @@
package com.android.settingslib.spaprivileged.framework.common
+import android.app.ActivityManager
import android.app.AlarmManager
import android.app.AppOpsManager
import android.app.admin.DevicePolicyManager
@@ -28,6 +29,9 @@
import android.os.UserManager
import android.permission.PermissionControllerManager
+/** The [ActivityManager] instance. */
+val Context.activityManager get() = getSystemService(ActivityManager::class.java)!!
+
/** The [AlarmManager] instance. */
val Context.alarmManager get() = getSystemService(AlarmManager::class.java)!!
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 2e0155b..caaa88d 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1105,6 +1105,8 @@
<string name="power_charging_duration"><xliff:g id="level">%1$s</xliff:g> - <xliff:g id="time">%2$s</xliff:g> left until full</string>
<!-- [CHAR_LIMIT=80] Label for battery level chart when charge been limited -->
<string name="power_charging_limited"><xliff:g id="level">%1$s</xliff:g> - Charging is paused</string>
+ <!-- [CHAR_LIMIT=80] Label for battery charging future pause -->
+ <string name="power_charging_future_paused"><xliff:g id="level">%1$s</xliff:g> - Charging to <xliff:g id="dock_defender_threshold">%2$s</xliff:g></string>
<!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="battery_info_status_unknown">Unknown</string>
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 8609e4a..10d31ea 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -972,13 +972,8 @@
if (imageData.uri != null) {
if (!imageData.owner.equals(Process.myUserHandle())) {
- // TODO: Handle non-primary user ownership (e.g. Work Profile)
- // This image is owned by another user. Special treatment will be
- // required in the UI (badging) as well as sending intents which can
- // correctly forward those URIs on to be read (actions).
-
- Log.d(TAG, "*** Screenshot saved to a non-primary user ("
- + imageData.owner + ") as " + imageData.uri);
+ Log.d(TAG, "Screenshot saved to user " + imageData.owner + " as "
+ + imageData.uri);
}
mScreenshotHandler.post(() -> {
if (mScreenshotAnimation != null && mScreenshotAnimation.isRunning()) {
@@ -1059,6 +1054,11 @@
R.string.screenshot_failed_to_save_text);
} else {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SAVED, 0, mPackageName);
+ if (mFlags.isEnabled(SCREENSHOT_WORK_PROFILE_POLICY)
+ && mUserManager.isManagedProfile(imageData.owner.getIdentifier())) {
+ mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SAVED_TO_WORK_PROFILE, 0,
+ mPackageName);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index a3d9965..7fbdeca 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -2072,13 +2072,6 @@
mInitialTouchX = x;
initVelocityTracker();
trackMovement(event);
- float qsExpansionFraction = computeQsExpansionFraction();
- // Intercept the touch if QS is between fully collapsed and fully expanded state
- if (qsExpansionFraction > 0.0 && qsExpansionFraction < 1.0) {
- mShadeLog.logMotionEvent(event,
- "onQsIntercept: down action, QS partially expanded/collapsed");
- return true;
- }
if (mKeyguardShowing
&& shouldQuickSettingsIntercept(mInitialTouchX, mInitialTouchY, 0)) {
// Dragging down on the lockscreen statusbar should prohibit other interactions
@@ -2331,13 +2324,6 @@
if (!isFullyCollapsed()) {
handleQsDown(event);
}
- // defer touches on QQS to shade while shade is collapsing. Added margin for error
- // as sometimes the qsExpansionFraction can be a tiny value instead of 0 when in QQS.
- if (computeQsExpansionFraction() <= 0.01 && getExpandedFraction() < 1.0) {
- mShadeLog.logMotionEvent(event,
- "handleQsTouch: QQS touched while shade collapsing");
- mQsTracking = false;
- }
if (!mQsExpandImmediate && mQsTracking) {
onQsTouch(event);
if (!mConflictingQsExpansionGesture && !mSplitShadeEnabled) {
@@ -2578,6 +2564,7 @@
// Reset scroll position and apply that position to the expanded height.
float height = mQsExpansionHeight;
setQsExpansionHeight(height);
+ updateExpandedHeightToMaxHeight();
mNotificationStackScrollLayoutController.checkSnoozeLeavebehind();
// When expanding QS, let's authenticate the user if possible,
diff --git a/services/OWNERS b/services/OWNERS
index 495c0737..eace906 100644
--- a/services/OWNERS
+++ b/services/OWNERS
@@ -3,7 +3,7 @@
# art-team@ manages the system server profile
per-file art-profile* = calin@google.com, ngeoffray@google.com, vmarko@google.com
-per-file java/com/android/server/* = toddke@google.com,patb@google.com
+per-file java/com/android/server/* = patb@google.com #{LAST_RESORT_SUGGESTION}
per-file tests/servicestests/src/com/android/server/systemconfig/* = patb@google.com
per-file proguard.flags = jdduke@google.com
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 30d4b8b..ca86021c 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -52,8 +52,8 @@
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SrvccState;
import android.telephony.BarringInfo;
+import android.telephony.CallAttributes;
import android.telephony.CallQuality;
-import android.telephony.CallState;
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.CellSignalStrength;
@@ -82,7 +82,6 @@
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.telephony.emergency.EmergencyNumber;
-import android.telephony.ims.ImsCallSession;
import android.telephony.ims.ImsReasonInfo;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -350,9 +349,9 @@
private CallQuality[] mCallQuality;
- private ArrayList<List<CallState>> mCallStateLists;
+ private CallAttributes[] mCallAttributes;
- // network type of the call associated with the mCallStateLists and mCallQuality
+ // network type of the call associated with the mCallAttributes and mCallQuality
private int[] mCallNetworkType;
private int[] mSrvccState;
@@ -688,6 +687,7 @@
mCallPreciseDisconnectCause = copyOf(mCallPreciseDisconnectCause, mNumPhones);
mCallQuality = copyOf(mCallQuality, mNumPhones);
mCallNetworkType = copyOf(mCallNetworkType, mNumPhones);
+ mCallAttributes = copyOf(mCallAttributes, mNumPhones);
mOutgoingCallEmergencyNumber = copyOf(mOutgoingCallEmergencyNumber, mNumPhones);
mOutgoingSmsEmergencyNumber = copyOf(mOutgoingSmsEmergencyNumber, mNumPhones);
mTelephonyDisplayInfos = copyOf(mTelephonyDisplayInfos, mNumPhones);
@@ -707,7 +707,6 @@
cutListToSize(mLinkCapacityEstimateLists, mNumPhones);
cutListToSize(mCarrierPrivilegeStates, mNumPhones);
cutListToSize(mCarrierServiceStates, mNumPhones);
- cutListToSize(mCallStateLists, mNumPhones);
return;
}
@@ -731,7 +730,8 @@
mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
mCallQuality[i] = createCallQuality();
- mCallStateLists.add(i, new ArrayList<>());
+ mCallAttributes[i] = new CallAttributes(createPreciseCallState(),
+ TelephonyManager.NETWORK_TYPE_UNKNOWN, createCallQuality());
mCallNetworkType[i] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
mPreciseCallState[i] = createPreciseCallState();
mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
@@ -799,7 +799,7 @@
mCallPreciseDisconnectCause = new int[numPhones];
mCallQuality = new CallQuality[numPhones];
mCallNetworkType = new int[numPhones];
- mCallStateLists = new ArrayList<>();
+ mCallAttributes = new CallAttributes[numPhones];
mPreciseDataConnectionStates = new ArrayList<>();
mCellInfo = new ArrayList<>(numPhones);
mImsReasonInfo = new ArrayList<>();
@@ -837,7 +837,8 @@
mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
mCallQuality[i] = createCallQuality();
- mCallStateLists.add(i, new ArrayList<>());
+ mCallAttributes[i] = new CallAttributes(createPreciseCallState(),
+ TelephonyManager.NETWORK_TYPE_UNKNOWN, createCallQuality());
mCallNetworkType[i] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
mPreciseCallState[i] = createPreciseCallState();
mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
@@ -1335,7 +1336,7 @@
}
if (events.contains(TelephonyCallback.EVENT_CALL_ATTRIBUTES_CHANGED)) {
try {
- r.callback.onCallStatesChanged(mCallStateLists.get(r.phoneId));
+ r.callback.onCallAttributesChanged(mCallAttributes[r.phoneId]);
} catch (RemoteException ex) {
remove(r.binder);
}
@@ -2170,30 +2171,11 @@
}
}
- /**
- * Send a notification to registrants that the precise call state has changed.
- *
- * @param phoneId the phoneId carrying the data connection
- * @param subId the subscriptionId for the data connection
- * @param callStates Array of PreciseCallState of foreground, background & ringing calls.
- * @param imsCallIds Array of IMS call session ID{@link ImsCallSession#getCallId()} for
- * ringing, foreground & background calls.
- * @param imsServiceTypes Array of IMS call service type for ringing, foreground &
- * background calls.
- * @param imsCallTypes Array of IMS call type for ringing, foreground & background calls.
- */
- public void notifyPreciseCallState(int phoneId, int subId,
- @Annotation.PreciseCallStates int[] callStates, String[] imsCallIds,
- @Annotation.ImsCallServiceType int[] imsServiceTypes,
- @Annotation.ImsCallType int[] imsCallTypes) {
+ public void notifyPreciseCallState(int phoneId, int subId, int ringingCallState,
+ int foregroundCallState, int backgroundCallState) {
if (!checkNotifyPermission("notifyPreciseCallState()")) {
return;
}
-
- int ringingCallState = callStates[CallState.CALL_CLASSIFICATION_RINGING];
- int foregroundCallState = callStates[CallState.CALL_CLASSIFICATION_FOREGROUND];
- int backgroundCallState = callStates[CallState.CALL_CLASSIFICATION_BACKGROUND];
-
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mRingingCallState[phoneId] = ringingCallState;
@@ -2204,11 +2186,11 @@
backgroundCallState,
DisconnectCause.NOT_VALID,
PreciseDisconnectCause.NOT_VALID);
- boolean notifyCallState = true;
+ boolean notifyCallAttributes = true;
if (mCallQuality == null) {
log("notifyPreciseCallState: mCallQuality is null, "
+ "skipping call attributes");
- notifyCallState = false;
+ notifyCallAttributes = false;
} else {
// If the precise call state is no longer active, reset the call network type
// and call quality.
@@ -2217,54 +2199,8 @@
mCallNetworkType[phoneId] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
mCallQuality[phoneId] = createCallQuality();
}
- mCallStateLists.get(phoneId).clear();
- if (foregroundCallState != PreciseCallState.PRECISE_CALL_STATE_IDLE) {
- CallQuality callQuality = mCallQuality[phoneId];
- mCallStateLists.get(phoneId).add(
- new CallState.Builder(
- callStates[CallState.CALL_CLASSIFICATION_FOREGROUND])
- .setNetworkType(mCallNetworkType[phoneId])
- .setCallQuality(callQuality)
- .setCallClassification(
- CallState.CALL_CLASSIFICATION_FOREGROUND)
- .setImsCallSessionId(imsCallIds[
- CallState.CALL_CLASSIFICATION_FOREGROUND])
- .setImsCallServiceType(imsServiceTypes[
- CallState.CALL_CLASSIFICATION_FOREGROUND])
- .setImsCallType(imsCallTypes[
- CallState.CALL_CLASSIFICATION_FOREGROUND]).build());
-
- }
- if (backgroundCallState != PreciseCallState.PRECISE_CALL_STATE_IDLE) {
- mCallStateLists.get(phoneId).add(
- new CallState.Builder(
- callStates[CallState.CALL_CLASSIFICATION_BACKGROUND])
- .setNetworkType(mCallNetworkType[phoneId])
- .setCallQuality(createCallQuality())
- .setCallClassification(
- CallState.CALL_CLASSIFICATION_BACKGROUND)
- .setImsCallSessionId(imsCallIds[
- CallState.CALL_CLASSIFICATION_BACKGROUND])
- .setImsCallServiceType(imsServiceTypes[
- CallState.CALL_CLASSIFICATION_BACKGROUND])
- .setImsCallType(imsCallTypes[
- CallState.CALL_CLASSIFICATION_BACKGROUND]).build());
- }
- if (ringingCallState != PreciseCallState.PRECISE_CALL_STATE_IDLE) {
- mCallStateLists.get(phoneId).add(
- new CallState.Builder(
- callStates[CallState.CALL_CLASSIFICATION_RINGING])
- .setNetworkType(mCallNetworkType[phoneId])
- .setCallQuality(createCallQuality())
- .setCallClassification(
- CallState.CALL_CLASSIFICATION_RINGING)
- .setImsCallSessionId(imsCallIds[
- CallState.CALL_CLASSIFICATION_RINGING])
- .setImsCallServiceType(imsServiceTypes[
- CallState.CALL_CLASSIFICATION_RINGING])
- .setImsCallType(imsCallTypes[
- CallState.CALL_CLASSIFICATION_RINGING]).build());
- }
+ mCallAttributes[phoneId] = new CallAttributes(mPreciseCallState[phoneId],
+ mCallNetworkType[phoneId], mCallQuality[phoneId]);
}
for (Record r : mRecords) {
@@ -2277,11 +2213,11 @@
mRemoveList.add(r.binder);
}
}
- if (notifyCallState && r.matchTelephonyCallbackEvent(
+ if (notifyCallAttributes && r.matchTelephonyCallbackEvent(
TelephonyCallback.EVENT_CALL_ATTRIBUTES_CHANGED)
&& idMatch(r, subId, phoneId)) {
try {
- r.callback.onCallStatesChanged(mCallStateLists.get(phoneId));
+ r.callback.onCallAttributesChanged(mCallAttributes[phoneId]);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
@@ -2579,29 +2515,15 @@
// merge CallQuality with PreciseCallState and network type
mCallQuality[phoneId] = callQuality;
mCallNetworkType[phoneId] = callNetworkType;
- if (mCallStateLists.get(phoneId).size() > 0
- && mCallStateLists.get(phoneId).get(0).getCallState()
- == PreciseCallState.PRECISE_CALL_STATE_ACTIVE) {
- CallState prev = mCallStateLists.get(phoneId).remove(0);
- mCallStateLists.get(phoneId).add(
- 0, new CallState.Builder(prev.getCallState())
- .setNetworkType(callNetworkType)
- .setCallQuality(callQuality)
- .setCallClassification(prev.getCallClassification())
- .setImsCallSessionId(prev.getImsCallSessionId())
- .setImsCallServiceType(prev.getImsCallServiceType())
- .setImsCallType(prev.getImsCallType()).build());
- } else {
- log("There is no active call to report CallQaulity");
- return;
- }
+ mCallAttributes[phoneId] = new CallAttributes(mPreciseCallState[phoneId],
+ callNetworkType, callQuality);
for (Record r : mRecords) {
if (r.matchTelephonyCallbackEvent(
TelephonyCallback.EVENT_CALL_ATTRIBUTES_CHANGED)
&& idMatch(r, subId, phoneId)) {
try {
- r.callback.onCallStatesChanged(mCallStateLists.get(phoneId));
+ r.callback.onCallAttributesChanged(mCallAttributes[phoneId]);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
@@ -3069,6 +2991,7 @@
pw.println("mSrvccState=" + mSrvccState[i]);
pw.println("mCallPreciseDisconnectCause=" + mCallPreciseDisconnectCause[i]);
pw.println("mCallQuality=" + mCallQuality[i]);
+ pw.println("mCallAttributes=" + mCallAttributes[i]);
pw.println("mCallNetworkType=" + mCallNetworkType[i]);
pw.println("mPreciseDataConnectionStates=" + mPreciseDataConnectionStates.get(i));
pw.println("mOutgoingCallEmergencyNumber=" + mOutgoingCallEmergencyNumber[i]);
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index 2669d21..8d247f6 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -140,9 +140,7 @@
import com.android.server.location.provider.proxy.ProxyLocationProvider;
import com.android.server.location.settings.LocationSettings;
import com.android.server.location.settings.LocationUserSettings;
-import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.permission.LegacyPermissionManagerInternal;
-import com.android.server.utils.Slogf;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -310,10 +308,6 @@
permissionManagerInternal.setLocationExtraPackagesProvider(
userId -> mContext.getResources().getStringArray(
com.android.internal.R.array.config_locationExtraPackageNames));
-
- // TODO(b/241604546): properly handle this callback
- LocalServices.getService(UserManagerInternal.class).addUserVisibilityListener(
- (u, v) -> Slogf.i(TAG, "onUserVisibilityChanged(): %d -> %b", u, v));
}
@Nullable
@@ -1702,7 +1696,7 @@
private final Context mContext;
- private final UserInfoHelper mUserInfoHelper;
+ private final SystemUserInfoHelper mUserInfoHelper;
private final LocationSettings mLocationSettings;
private final AlarmHelper mAlarmHelper;
private final SystemAppOpsHelper mAppOpsHelper;
@@ -1725,7 +1719,7 @@
@GuardedBy("this")
private boolean mSystemReady;
- SystemInjector(Context context, UserInfoHelper userInfoHelper) {
+ SystemInjector(Context context, SystemUserInfoHelper userInfoHelper) {
mContext = context;
mUserInfoHelper = userInfoHelper;
@@ -1745,6 +1739,7 @@
}
synchronized void onSystemReady() {
+ mUserInfoHelper.onSystemReady();
mAppOpsHelper.onSystemReady();
mLocationPermissionsHelper.onSystemReady();
mSettingsHelper.onSystemReady();
diff --git a/services/core/java/com/android/server/location/eventlog/LocationEventLog.java b/services/core/java/com/android/server/location/eventlog/LocationEventLog.java
index 45436e7..cb952ed 100644
--- a/services/core/java/com/android/server/location/eventlog/LocationEventLog.java
+++ b/services/core/java/com/android/server/location/eventlog/LocationEventLog.java
@@ -110,6 +110,11 @@
addLog(new UserSwitchedEvent(userIdFrom, userIdTo));
}
+ /** Logs a user visibility changed event. */
+ public void logUserVisibilityChanged(int userId, boolean visible) {
+ addLog(new UserVisibilityChangedEvent(userId, visible));
+ }
+
/** Logs a location enabled/disabled event. */
public void logLocationEnabled(int userId, boolean enabled) {
addLog(new LocationEnabledEvent(userId, enabled));
@@ -475,6 +480,22 @@
}
}
+ private static final class UserVisibilityChangedEvent {
+
+ private final int mUserId;
+ private final boolean mVisible;
+
+ UserVisibilityChangedEvent(int userId, boolean visible) {
+ mUserId = userId;
+ mVisible = visible;
+ }
+
+ @Override
+ public String toString() {
+ return "[u" + mUserId + "] " + (mVisible ? "visible" : "invisible");
+ }
+ }
+
private static final class LocationEnabledEvent {
private final int mUserId;
diff --git a/services/core/java/com/android/server/location/geofence/GeofenceManager.java b/services/core/java/com/android/server/location/geofence/GeofenceManager.java
index 0f5e3d4..d3ceddd 100644
--- a/services/core/java/com/android/server/location/geofence/GeofenceManager.java
+++ b/services/core/java/com/android/server/location/geofence/GeofenceManager.java
@@ -387,7 +387,7 @@
if (!mSettingsHelper.isLocationEnabled(identity.getUserId())) {
return false;
}
- if (!mUserInfoHelper.isCurrentUserId(identity.getUserId())) {
+ if (!mUserInfoHelper.isVisibleUserId(identity.getUserId())) {
return false;
}
if (mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
@@ -534,7 +534,10 @@
}
void onUserChanged(int userId, int change) {
- if (change == UserListener.CURRENT_USER_CHANGED) {
+ // current user changes affect whether system server location requests are allowed to access
+ // location, and visibility changes affect whether any given user may access location.
+ if (change == UserListener.CURRENT_USER_CHANGED
+ || change == UserListener.USER_VISIBILITY_CHANGED) {
updateRegistrations(registration -> registration.getIdentity().getUserId() == userId);
}
}
diff --git a/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java b/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java
index 349b94b..567d8ac 100644
--- a/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java
+++ b/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java
@@ -317,7 +317,7 @@
identity.getUserId())) {
return false;
}
- if (!mUserInfoHelper.isCurrentUserId(identity.getUserId())) {
+ if (!mUserInfoHelper.isVisibleUserId(identity.getUserId())) {
return false;
}
if (mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
@@ -394,7 +394,10 @@
}
private void onUserChanged(int userId, int change) {
- if (change == UserListener.CURRENT_USER_CHANGED) {
+ // current user changes affect whether system server location requests are allowed to access
+ // location, and visibility changes affect whether any given user may access location.
+ if (change == UserListener.CURRENT_USER_CHANGED
+ || change == UserListener.USER_VISIBILITY_CHANGED) {
updateRegistrations(registration -> registration.getIdentity().getUserId() == userId);
}
}
diff --git a/services/core/java/com/android/server/location/injector/SystemUserInfoHelper.java b/services/core/java/com/android/server/location/injector/SystemUserInfoHelper.java
index ed1e654..40dd979 100644
--- a/services/core/java/com/android/server/location/injector/SystemUserInfoHelper.java
+++ b/services/core/java/com/android/server/location/injector/SystemUserInfoHelper.java
@@ -33,9 +33,11 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
+import com.android.server.pm.UserManagerInternal;
import java.io.FileDescriptor;
import java.util.Arrays;
+import java.util.Objects;
/**
* Provides accessors and listeners for all user info.
@@ -50,11 +52,21 @@
@Nullable private IActivityManager mActivityManager;
@GuardedBy("this")
@Nullable private UserManager mUserManager;
+ @GuardedBy("this")
+ @Nullable private UserManagerInternal mUserManagerInternal;
public SystemUserInfoHelper(Context context) {
mContext = context;
}
+ /** The function should be called when PHASE_SYSTEM_SERVICES_READY. */
+ public synchronized void onSystemReady() {
+ mUserManagerInternal =
+ Objects.requireNonNull(LocalServices.getService(UserManagerInternal.class));
+ mUserManagerInternal.addUserVisibilityListener(
+ (userId, visible) -> dispatchOnVisibleUserChanged(userId, visible));
+ }
+
@Nullable
protected final ActivityManagerInternal getActivityManagerInternal() {
synchronized (this) {
@@ -136,6 +148,24 @@
}
@Override
+ public boolean isVisibleUserId(@UserIdInt int userId) {
+ synchronized (this) {
+ // if you're hitting this precondition then you are invoking this before the system is
+ // ready
+ Preconditions.checkState(mUserManagerInternal != null);
+ }
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ return mUserManagerInternal.isUserVisible(userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
protected int[] getProfileIds(@UserIdInt int userId) {
UserManager userManager = getUserManager();
diff --git a/services/core/java/com/android/server/location/injector/UserInfoHelper.java b/services/core/java/com/android/server/location/injector/UserInfoHelper.java
index c835370..2b9db1c 100644
--- a/services/core/java/com/android/server/location/injector/UserInfoHelper.java
+++ b/services/core/java/com/android/server/location/injector/UserInfoHelper.java
@@ -22,6 +22,7 @@
import static com.android.server.location.injector.UserInfoHelper.UserListener.CURRENT_USER_CHANGED;
import static com.android.server.location.injector.UserInfoHelper.UserListener.USER_STARTED;
import static com.android.server.location.injector.UserInfoHelper.UserListener.USER_STOPPED;
+import static com.android.server.location.injector.UserInfoHelper.UserListener.USER_VISIBILITY_CHANGED;
import android.annotation.IntDef;
import android.annotation.UserIdInt;
@@ -47,8 +48,9 @@
int CURRENT_USER_CHANGED = 1;
int USER_STARTED = 2;
int USER_STOPPED = 3;
+ int USER_VISIBILITY_CHANGED = 4;
- @IntDef({CURRENT_USER_CHANGED, USER_STARTED, USER_STOPPED})
+ @IntDef({CURRENT_USER_CHANGED, USER_STARTED, USER_STOPPED, USER_VISIBILITY_CHANGED})
@Retention(RetentionPolicy.SOURCE)
@interface UserChange {}
@@ -121,6 +123,18 @@
}
}
+ protected final void dispatchOnVisibleUserChanged(@UserIdInt int userId, boolean visible) {
+ if (D) {
+ Log.d(TAG, "visibility of u" + userId + " changed to "
+ + (visible ? "visible" : "invisible"));
+ }
+ EVENT_LOG.logUserVisibilityChanged(userId, visible);
+
+ for (UserListener listener : mListeners) {
+ listener.onUserChanged(userId, USER_VISIBILITY_CHANGED);
+ }
+ }
+
/**
* Returns an array of running user ids. This will include all running users, and will also
* include any profiles of the running users. The caller must never mutate the returned
@@ -129,8 +143,8 @@
public abstract int[] getRunningUserIds();
/**
- * Returns true if the given user id is either the current user or a profile of the current
- * user.
+ * Returns {@code true} if the given user id is either the current user or a profile of the
+ * current user.
*/
public abstract boolean isCurrentUserId(@UserIdInt int userId);
@@ -140,6 +154,13 @@
*/
public abstract @UserIdInt int getCurrentUserId();
+ /**
+ * Returns {@code true} if the user is visible.
+ *
+ * <p>The visibility of a user is defined by {@link android.os.UserManager#isUserVisible()}.
+ */
+ public abstract boolean isVisibleUserId(@UserIdInt int userId);
+
protected abstract int[] getProfileIds(@UserIdInt int userId);
/**
diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
index 338a995..7063cb8 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -661,6 +661,8 @@
if (!GPS_PROVIDER.equals(mName)) {
Log.e(TAG, "adas gnss bypass request received in non-gps provider");
adasGnssBypass = false;
+ } else if (!mUserHelper.isCurrentUserId(getIdentity().getUserId())) {
+ adasGnssBypass = false;
} else if (!mLocationSettings.getUserSettings(
getIdentity().getUserId()).isAdasGnssLocationEnabled()) {
adasGnssBypass = false;
@@ -1712,6 +1714,8 @@
if (!GPS_PROVIDER.equals(mName)) {
Log.e(TAG, "adas gnss bypass request received in non-gps provider");
adasGnssBypass = false;
+ } else if (!mUserHelper.isCurrentUserId(identity.getUserId())) {
+ adasGnssBypass = false;
} else if (!mLocationSettings.getUserSettings(
identity.getUserId()).isAdasGnssLocationEnabled()) {
adasGnssBypass = false;
@@ -2193,7 +2197,7 @@
if (!isEnabled(identity.getUserId())) {
return false;
}
- if (!mUserHelper.isCurrentUserId(identity.getUserId())) {
+ if (!mUserHelper.isVisibleUserId(identity.getUserId())) {
return false;
}
}
@@ -2322,6 +2326,10 @@
switch (change) {
case UserListener.CURRENT_USER_CHANGED:
+ // current user changes affect whether system server location requests are
+ // allowed to access location, and visibility changes affect whether any given
+ // user may access location.
+ case UserListener.USER_VISIBILITY_CHANGED:
updateRegistrations(
registration -> registration.getIdentity().getUserId() == userId);
break;
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 3bb0238..14d6d7b 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
@@ -226,9 +227,8 @@
mBackAnimationInProgress = true;
// We don't have an application callback, let's find the destination of the back gesture
- Task finalTask = currentTask;
- prevActivity = currentTask.getActivity(
- (r) -> !r.finishing && r.getTask() == finalTask && !r.isTopRunningActivity());
+ // The search logic should align with ActivityClientController#finishActivity
+ prevActivity = currentTask.topRunningActivity(currentActivity.token, INVALID_TASK_ID);
// TODO Dialog window does not need to attach on activity, check
// window.mAttrs.type != TYPE_BASE_APPLICATION
if ((window.getParent().getChildCount() > 1
@@ -244,12 +244,14 @@
} else if (currentTask.returnsToHomeRootTask()) {
// Our Task should bring back to home
removedWindowContainer = currentTask;
+ prevTask = currentTask.getDisplayArea().getRootHomeTask();
backType = BackNavigationInfo.TYPE_RETURN_TO_HOME;
mShowWallpaper = true;
} else if (currentActivity.isRootOfTask()) {
// TODO(208789724): Create single source of truth for this, maybe in
// RootWindowContainer
- prevTask = currentTask.mRootWindowContainer.getTaskBelow(currentTask);
+ prevTask = currentTask.mRootWindowContainer.getTask(Task::showToCurrentUser,
+ currentTask, false /*includeBoundary*/, true /*traverseTopToBottom*/);
removedWindowContainer = currentTask;
// If it reaches the top activity, we will check the below task from parent.
// If it's null or multi-window, fallback the type to TYPE_CALLBACK.
@@ -423,6 +425,11 @@
void reset(@NonNull WindowContainer close, @NonNull WindowContainer open) {
clearBackAnimateTarget(null);
+ if (close == null || open == null) {
+ Slog.e(TAG, "reset animation with null target close: "
+ + close + " open: " + open);
+ return;
+ }
if (close.asActivityRecord() != null && open.asActivityRecord() != null
&& (close.asActivityRecord().getTask() == open.asActivityRecord().getTask())) {
mSwitchType = ACTIVITY_SWITCH;
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index 30fcd06..d3b9e10 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -35,6 +35,7 @@
import android.os.ICancellationSignal;
import android.os.UserHandle;
import android.provider.Settings;
+import android.service.credentials.BeginCreateCredentialRequest;
import android.service.credentials.GetCredentialsRequest;
import android.text.TextUtils;
import android.util.Log;
@@ -199,7 +200,7 @@
// Iterate over all provider sessions and invoke the request
providerSessions.forEach(providerCreateSession -> {
providerCreateSession.getRemoteCredentialService().onCreateCredential(
- (android.service.credentials.CreateCredentialRequest)
+ (BeginCreateCredentialRequest)
providerCreateSession.getProviderRequest(),
/*callback=*/providerCreateSession);
});
diff --git a/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java b/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java
index 4cdc457..d0bc074 100644
--- a/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java
+++ b/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java
@@ -22,7 +22,7 @@
import android.credentials.Credential;
import android.credentials.ui.ProviderPendingIntentResponse;
import android.service.credentials.CredentialProviderService;
-import android.service.credentials.CredentialsDisplayContent;
+import android.service.credentials.CredentialsResponseContent;
/**
* Helper class for setting up pending intent, and extracting objects from it.
@@ -37,14 +37,15 @@
return pendingIntentResponse.getResultCode() == Activity.RESULT_OK;
}
- /** Extracts the {@link CredentialsDisplayContent} object added to the result data. */
- public static CredentialsDisplayContent extractCredentialsDisplayContent(Intent resultData) {
+ /** Extracts the {@link CredentialsResponseContent} object added to the result data. */
+ public static CredentialsResponseContent extractResponseContent(Intent resultData) {
if (resultData == null) {
return null;
}
return resultData.getParcelableExtra(
- CredentialProviderService.EXTRA_GET_CREDENTIALS_DISPLAY_CONTENT,
- CredentialsDisplayContent.class);
+ CredentialProviderService
+ .EXTRA_GET_CREDENTIALS_CONTENT_RESULT,
+ CredentialsResponseContent.class);
}
/** Extracts the {@link CreateCredentialResponse} object added to the result data. */
@@ -53,7 +54,7 @@
return null;
}
return resultData.getParcelableExtra(
- CredentialProviderService.EXTRA_CREATE_CREDENTIAL_RESPONSE,
+ CredentialProviderService.EXTRA_CREATE_CREDENTIAL_RESULT,
CreateCredentialResponse.class);
}
@@ -63,7 +64,7 @@
return null;
}
return resultData.getParcelableExtra(
- CredentialProviderService.EXTRA_GET_CREDENTIAL,
+ CredentialProviderService.EXTRA_CREDENTIAL_RESULT,
Credential.class);
}
}
diff --git a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
index 6bb8c60..14fee78 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
@@ -26,11 +26,11 @@
import android.credentials.ui.Entry;
import android.credentials.ui.ProviderPendingIntentResponse;
import android.os.Bundle;
-import android.service.credentials.CreateCredentialRequest;
-import android.service.credentials.CreateCredentialResponse;
+import android.service.credentials.BeginCreateCredentialRequest;
+import android.service.credentials.BeginCreateCredentialResponse;
+import android.service.credentials.CreateEntry;
import android.service.credentials.CredentialProviderInfo;
import android.service.credentials.CredentialProviderService;
-import android.service.credentials.SaveEntry;
import android.util.Log;
import android.util.Slog;
@@ -44,16 +44,16 @@
* Will likely split this into remote response state and UI state.
*/
public final class ProviderCreateSession extends ProviderSession<
- CreateCredentialRequest, CreateCredentialResponse> {
+ BeginCreateCredentialRequest, BeginCreateCredentialResponse> {
private static final String TAG = "ProviderCreateSession";
// Key to be used as an entry key for a save entry
private static final String SAVE_ENTRY_KEY = "save_entry_key";
@NonNull
- private final Map<String, SaveEntry> mUiSaveEntries = new HashMap<>();
+ private final Map<String, CreateEntry> mUiSaveEntries = new HashMap<>();
/** The complete request to be used in the second round. */
- private final CreateCredentialRequest mCompleteRequest;
+ private final BeginCreateCredentialRequest mCompleteRequest;
/** Creates a new provider session to be used by the request session. */
@Nullable public static ProviderCreateSession createNewSession(
@@ -62,7 +62,7 @@
CredentialProviderInfo providerInfo,
CreateRequestSession createRequestSession,
RemoteCredentialService remoteCredentialService) {
- CreateCredentialRequest providerRequest =
+ BeginCreateCredentialRequest providerRequest =
createProviderRequest(providerInfo.getCapabilities(),
createRequestSession.mClientRequest,
createRequestSession.mClientCallingPackage);
@@ -75,21 +75,23 @@
}
@Nullable
- private static CreateCredentialRequest createProviderRequest(List<String> providerCapabilities,
+ private static BeginCreateCredentialRequest createProviderRequest(
+ List<String> providerCapabilities,
android.credentials.CreateCredentialRequest clientRequest,
String clientCallingPackage) {
String capability = clientRequest.getType();
if (providerCapabilities.contains(capability)) {
- return new CreateCredentialRequest(clientCallingPackage, capability,
+ return new BeginCreateCredentialRequest(clientCallingPackage, capability,
clientRequest.getData());
}
Log.i(TAG, "Unable to create provider request - capabilities do not match");
return null;
}
- private static CreateCredentialRequest getFirstRoundRequest(CreateCredentialRequest request) {
+ private static BeginCreateCredentialRequest getFirstRoundRequest(
+ BeginCreateCredentialRequest request) {
// TODO: Replace with first round bundle from request when ready
- return new CreateCredentialRequest(
+ return new BeginCreateCredentialRequest(
request.getCallingPackage(),
request.getType(),
new Bundle());
@@ -101,7 +103,7 @@
@NonNull ProviderInternalCallback callbacks,
@UserIdInt int userId,
@NonNull RemoteCredentialService remoteCredentialService,
- @NonNull CreateCredentialRequest request) {
+ @NonNull BeginCreateCredentialRequest request) {
super(context, info, getFirstRoundRequest(request), callbacks, userId,
remoteCredentialService);
// TODO : Replace with proper splitting of request
@@ -110,13 +112,13 @@
}
/** Returns the save entry maintained in state by this provider session. */
- public SaveEntry getUiSaveEntry(String entryId) {
+ public CreateEntry getUiSaveEntry(String entryId) {
return mUiSaveEntries.get(entryId);
}
@Override
public void onProviderResponseSuccess(
- @Nullable CreateCredentialResponse response) {
+ @Nullable BeginCreateCredentialResponse response) {
Log.i(TAG, "in onProviderResponseSuccess");
onUpdateResponse(response);
}
@@ -138,7 +140,7 @@
}
}
- private void onUpdateResponse(CreateCredentialResponse response) {
+ private void onUpdateResponse(BeginCreateCredentialResponse response) {
Log.i(TAG, "updateResponse with save entries");
mProviderResponse = response;
updateStatusAndInvokeCallback(Status.SAVE_ENTRIES_RECEIVED);
@@ -152,15 +154,15 @@
Log.i(TAG, "In prepareUiData not in uiInvokingStatus");
return null;
}
- final CreateCredentialResponse response = getProviderResponse();
+ final BeginCreateCredentialResponse response = getProviderResponse();
if (response == null) {
Log.i(TAG, "In prepareUiData response null");
throw new IllegalStateException("Response must be in completion mode");
}
- if (response.getSaveEntries() != null) {
+ if (response.getCreateEntries() != null) {
Log.i(TAG, "In prepareUiData save entries not null");
return prepareUiProviderData(
- prepareUiSaveEntries(response.getSaveEntries()),
+ prepareUiSaveEntries(response.getCreateEntries()),
null,
/*isDefaultProvider=*/false);
}
@@ -192,24 +194,25 @@
}
}
- private List<Entry> prepareUiSaveEntries(@NonNull List<SaveEntry> saveEntries) {
+ private List<Entry> prepareUiSaveEntries(@NonNull List<CreateEntry> saveEntries) {
Log.i(TAG, "in populateUiSaveEntries");
List<Entry> uiSaveEntries = new ArrayList<>();
// Populate the save entries
- for (SaveEntry saveEntry : saveEntries) {
+ for (CreateEntry createEntry : saveEntries) {
String entryId = generateEntryId();
- mUiSaveEntries.put(entryId, saveEntry);
+ mUiSaveEntries.put(entryId, createEntry);
Log.i(TAG, "in prepareUiProviderData creating ui entry with id " + entryId);
- uiSaveEntries.add(new Entry(SAVE_ENTRY_KEY, entryId, saveEntry.getSlice(),
- saveEntry.getPendingIntent(), setUpFillInIntent(saveEntry.getPendingIntent())));
+ uiSaveEntries.add(new Entry(SAVE_ENTRY_KEY, entryId, createEntry.getSlice(),
+ createEntry.getPendingIntent(), setUpFillInIntent(
+ createEntry.getPendingIntent())));
}
return uiSaveEntries;
}
private Intent setUpFillInIntent(PendingIntent pendingIntent) {
Intent intent = pendingIntent.getIntent();
- intent.putExtra(CredentialProviderService.EXTRA_CREATE_CREDENTIAL_REQUEST_PARAMS,
+ intent.putExtra(CredentialProviderService.EXTRA_CREATE_CREDENTIAL_REQUEST,
mCompleteRequest);
return intent;
}
diff --git a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
index d63cdeb..6cd011b 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
@@ -29,7 +29,7 @@
import android.service.credentials.Action;
import android.service.credentials.CredentialEntry;
import android.service.credentials.CredentialProviderInfo;
-import android.service.credentials.CredentialsDisplayContent;
+import android.service.credentials.CredentialsResponseContent;
import android.service.credentials.GetCredentialsRequest;
import android.service.credentials.GetCredentialsResponse;
import android.util.Log;
@@ -211,20 +211,20 @@
prepareUiAuthenticationAction(mProviderResponse.getAuthenticationAction()),
/*remoteEntry=*/null);
}
- if (mProviderResponse.getCredentialsDisplayContent() != null) {
- Log.i(TAG, "In prepareUiData displayContent not null");
+ if (mProviderResponse.getCredentialsResponseContent() != null) {
+ Log.i(TAG, "In prepareUiData credentialsResponseContent not null");
return prepareUiProviderData(prepareUiActionEntries(
- mProviderResponse.getCredentialsDisplayContent().getActions()),
- prepareUiCredentialEntries(mProviderResponse.getCredentialsDisplayContent()
+ mProviderResponse.getCredentialsResponseContent().getActions()),
+ prepareUiCredentialEntries(mProviderResponse.getCredentialsResponseContent()
.getCredentialEntries()),
/*authenticationAction=*/null,
prepareUiRemoteEntry(mProviderResponse
- .getCredentialsDisplayContent().getRemoteCredentialEntry()));
+ .getCredentialsResponseContent().getRemoteCredentialEntry()));
}
return null;
}
- private Entry prepareUiRemoteEntry(Action remoteCredentialEntry) {
+ private Entry prepareUiRemoteEntry(CredentialEntry remoteCredentialEntry) {
if (remoteCredentialEntry == null) {
return null;
}
@@ -316,11 +316,11 @@
@Nullable ProviderPendingIntentResponse providerPendingIntentResponse) {
if (providerPendingIntentResponse != null) {
if (PendingIntentResultHandler.isSuccessfulResponse(providerPendingIntentResponse)) {
- CredentialsDisplayContent content = PendingIntentResultHandler
- .extractCredentialsDisplayContent(providerPendingIntentResponse
+ CredentialsResponseContent content = PendingIntentResultHandler
+ .extractResponseContent(providerPendingIntentResponse
.getResultData());
if (content != null) {
- onUpdateResponse(GetCredentialsResponse.createWithDisplayContent(content));
+ onUpdateResponse(GetCredentialsResponse.createWithResponseContent(content));
return;
}
}
@@ -342,7 +342,7 @@
if (response.getAuthenticationAction() != null) {
Log.i(TAG , "updateResponse with authentication entry");
updateStatusAndInvokeCallback(Status.REQUIRES_AUTHENTICATION);
- } else if (response.getCredentialsDisplayContent() != null) {
+ } else if (response.getCredentialsResponseContent() != null) {
Log.i(TAG , "updateResponse with credentialEntries");
// TODO validate response
updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
diff --git a/services/credentials/java/com/android/server/credentials/ProviderSession.java b/services/credentials/java/com/android/server/credentials/ProviderSession.java
index 4a07f0a..ac360bd 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderSession.java
@@ -23,7 +23,7 @@
import android.credentials.Credential;
import android.credentials.ui.ProviderData;
import android.credentials.ui.ProviderPendingIntentResponse;
-import android.service.credentials.Action;
+import android.service.credentials.CredentialEntry;
import android.service.credentials.CredentialProviderException;
import android.service.credentials.CredentialProviderInfo;
import android.util.Pair;
@@ -50,7 +50,7 @@
@Nullable protected Credential mFinalCredentialResponse;
@NonNull protected final T mProviderRequest;
@Nullable protected R mProviderResponse;
- @Nullable protected Pair<String, Action> mUiRemoteEntry;
+ @Nullable protected Pair<String, CredentialEntry> mUiRemoteEntry;
/**
* Returns true if the given status reflects that the provider state is ready to be shown
diff --git a/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java b/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java
index c2464b5..e385bcb 100644
--- a/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java
+++ b/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java
@@ -24,14 +24,14 @@
import android.os.Handler;
import android.os.ICancellationSignal;
import android.os.RemoteException;
-import android.service.credentials.CreateCredentialRequest;
-import android.service.credentials.CreateCredentialResponse;
+import android.service.credentials.BeginCreateCredentialRequest;
+import android.service.credentials.BeginCreateCredentialResponse;
import android.service.credentials.CredentialProviderException;
import android.service.credentials.CredentialProviderException.CredentialProviderError;
import android.service.credentials.CredentialProviderService;
import android.service.credentials.GetCredentialsRequest;
import android.service.credentials.GetCredentialsResponse;
-import android.service.credentials.ICreateCredentialCallback;
+import android.service.credentials.IBeginCreateCredentialCallback;
import android.service.credentials.ICredentialProviderService;
import android.service.credentials.IGetCredentialsCallback;
import android.text.format.DateUtils;
@@ -146,27 +146,27 @@
handleExecutionResponse(result, error, cancellationSink, callback)));
}
- /** Main entry point to be called for executing a createCredential call on the remote
+ /** Main entry point to be called for executing a beginCreateCredential call on the remote
* provider service.
* @param request the request to be sent to the provider
* @param callback the callback to be used to send back the provider response to the
* {@link ProviderCreateSession} class that maintains provider state
*/
- public void onCreateCredential(@NonNull CreateCredentialRequest request,
- ProviderCallbacks<CreateCredentialResponse> callback) {
+ public void onCreateCredential(@NonNull BeginCreateCredentialRequest request,
+ ProviderCallbacks<BeginCreateCredentialResponse> callback) {
Log.i(TAG, "In onCreateCredential in RemoteCredentialService");
AtomicReference<ICancellationSignal> cancellationSink = new AtomicReference<>();
- AtomicReference<CompletableFuture<CreateCredentialResponse>> futureRef =
+ AtomicReference<CompletableFuture<BeginCreateCredentialResponse>> futureRef =
new AtomicReference<>();
- CompletableFuture<CreateCredentialResponse> connectThenExecute = postAsync(service -> {
- CompletableFuture<CreateCredentialResponse> createCredentialFuture =
+ CompletableFuture<BeginCreateCredentialResponse> connectThenExecute = postAsync(service -> {
+ CompletableFuture<BeginCreateCredentialResponse> createCredentialFuture =
new CompletableFuture<>();
- ICancellationSignal cancellationSignal = service.onCreateCredential(
- request, new ICreateCredentialCallback.Stub() {
+ ICancellationSignal cancellationSignal = service.onBeginCreateCredential(
+ request, new IBeginCreateCredentialCallback.Stub() {
@Override
- public void onSuccess(CreateCredentialResponse response) {
- Log.i(TAG, "In onSuccess onCreateCredential "
+ public void onSuccess(BeginCreateCredentialResponse response) {
+ Log.i(TAG, "In onSuccess onBeginCreateCredential "
+ "in RemoteCredentialService");
createCredentialFuture.complete(response);
}
@@ -179,7 +179,7 @@
createCredentialFuture.completeExceptionally(
new CredentialProviderException(errorCode, errorMsg));
}});
- CompletableFuture<CreateCredentialResponse> future = futureRef.get();
+ CompletableFuture<BeginCreateCredentialResponse> future = futureRef.get();
if (future != null && future.isCancelled()) {
dispatchCancellationSignal(cancellationSignal);
} else {
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeUserInfoHelper.java b/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeUserInfoHelper.java
index ac23d4e..014ef3d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeUserInfoHelper.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeUserInfoHelper.java
@@ -34,14 +34,16 @@
public static final int DEFAULT_USERID = 0;
private final IntArray mRunningUserIds;
+ private final IntArray mVisibleUserIds;
private final SparseArray<IntArray> mProfiles;
private int mCurrentUserId;
public FakeUserInfoHelper() {
mCurrentUserId = DEFAULT_USERID;
- mRunningUserIds = IntArray.wrap(new int[]{DEFAULT_USERID});
+ mRunningUserIds = IntArray.wrap(new int[] {DEFAULT_USERID});
mProfiles = new SparseArray<>();
+ mVisibleUserIds = IntArray.wrap(new int[] {DEFAULT_USERID});
}
public void startUser(int userId) {
@@ -65,6 +67,7 @@
mRunningUserIds.remove(idx);
}
+ setUserInvisibleInternal(userId);
dispatchOnUserStopped(userId);
}
@@ -82,16 +85,39 @@
// ensure all profiles are started if they didn't exist before...
for (int userId : currentProfileUserIds) {
startUserInternal(userId, false);
+ setUserVisibleInternal(userId, true);
}
if (oldUserId != mCurrentUserId) {
dispatchOnCurrentUserChanged(oldUserId, mCurrentUserId);
+ setUserVisibleInternal(mCurrentUserId, true);
}
}
- @Override
- public int[] getRunningUserIds() {
- return mRunningUserIds.toArray();
+ private void setUserVisibleInternal(int userId, boolean alwaysDispatch) {
+ int idx = mVisibleUserIds.indexOf(userId);
+ if (idx < 0) {
+ mVisibleUserIds.add(userId);
+ } else if (!alwaysDispatch) {
+ return;
+ }
+ dispatchOnVisibleUserChanged(userId, true);
+ }
+
+ private void setUserInvisibleInternal(int userId) {
+ int idx = mVisibleUserIds.indexOf(userId);
+ if (idx >= 0) {
+ mVisibleUserIds.remove(userId);
+ }
+ dispatchOnVisibleUserChanged(userId, false);
+ }
+
+ public void setUserVisible(int userId, boolean visible) {
+ if (visible) {
+ setUserVisibleInternal(userId, true);
+ } else {
+ setUserInvisibleInternal(userId);
+ }
}
@Override
@@ -100,11 +126,21 @@
}
@Override
+ public int[] getRunningUserIds() {
+ return mRunningUserIds.toArray();
+ }
+
+ @Override
public int getCurrentUserId() {
return mCurrentUserId;
}
@Override
+ public boolean isVisibleUserId(int userId) {
+ return mVisibleUserIds.indexOf(userId) >= 0;
+ }
+
+ @Override
protected int[] getProfileIds(int userId) {
IntArray profiles = mProfiles.get(userId);
if (profiles != null) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/injector/SystemUserInfoHelperTest.java b/services/tests/mockingservicestests/src/com/android/server/location/injector/SystemUserInfoHelperTest.java
index 490b2e8..d9aa232 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/injector/SystemUserInfoHelperTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/injector/SystemUserInfoHelperTest.java
@@ -15,6 +15,7 @@
*/
package com.android.server.location.injector;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@@ -31,6 +32,7 @@
import com.android.server.LocalServices;
import com.android.server.location.injector.UserInfoHelper.UserListener;
+import com.android.server.pm.UserManagerInternal;
import org.junit.After;
import org.junit.Before;
@@ -45,13 +47,14 @@
private static final int USER1_ID = 1;
private static final int USER1_MANAGED_ID = 11;
- private static final int[] USER1_PROFILES = new int[]{USER1_ID, USER1_MANAGED_ID};
+ private static final int[] USER1_PROFILES = new int[] {USER1_ID, USER1_MANAGED_ID};
private static final int USER2_ID = 2;
private static final int USER2_MANAGED_ID = 12;
- private static final int[] USER2_PROFILES = new int[]{USER2_ID, USER2_MANAGED_ID};
+ private static final int[] USER2_PROFILES = new int[] {USER2_ID, USER2_MANAGED_ID};
@Mock private Context mContext;
@Mock private UserManager mUserManager;
+ @Mock private UserManagerInternal mUserManagerInternal;
private SystemUserInfoHelper mHelper;
@@ -63,12 +66,15 @@
doReturn(USER1_PROFILES).when(mUserManager).getEnabledProfileIds(USER1_ID);
doReturn(USER2_PROFILES).when(mUserManager).getEnabledProfileIds(USER2_ID);
+ LocalServices.addService(UserManagerInternal.class, mUserManagerInternal);
+
mHelper = new SystemUserInfoHelper(mContext);
}
@After
public void tearDown() {
LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+ LocalServices.removeServiceForTest(UserManagerInternal.class);
}
@Test
@@ -77,11 +83,11 @@
mHelper.addListener(listener);
mHelper.dispatchOnCurrentUserChanged(USER1_ID, USER2_ID);
- verify(listener, times(1)).onUserChanged(USER1_ID, UserListener.CURRENT_USER_CHANGED);
- verify(listener, times(1)).onUserChanged(USER1_MANAGED_ID,
+ verify(listener).onUserChanged(USER1_ID, UserListener.CURRENT_USER_CHANGED);
+ verify(listener).onUserChanged(USER1_MANAGED_ID,
UserListener.CURRENT_USER_CHANGED);
- verify(listener, times(1)).onUserChanged(USER2_ID, UserListener.CURRENT_USER_CHANGED);
- verify(listener, times(1)).onUserChanged(USER2_MANAGED_ID,
+ verify(listener).onUserChanged(USER2_ID, UserListener.CURRENT_USER_CHANGED);
+ verify(listener).onUserChanged(USER2_MANAGED_ID,
UserListener.CURRENT_USER_CHANGED);
mHelper.dispatchOnCurrentUserChanged(USER2_ID, USER1_ID);
@@ -94,6 +100,25 @@
}
@Test
+ public void testListener_UserVisibilityChanged() {
+ mHelper.onSystemReady();
+ verify(mUserManagerInternal).addUserVisibilityListener(any());
+
+ UserListener listener = mock(UserListener.class);
+ mHelper.addListener(listener);
+
+ mHelper.dispatchOnVisibleUserChanged(USER1_ID, false);
+ mHelper.dispatchOnVisibleUserChanged(USER2_ID, true);
+ verify(listener).onUserChanged(USER1_ID, UserListener.USER_VISIBILITY_CHANGED);
+ verify(listener).onUserChanged(USER2_ID, UserListener.USER_VISIBILITY_CHANGED);
+
+ mHelper.dispatchOnVisibleUserChanged(USER2_ID, false);
+ mHelper.dispatchOnVisibleUserChanged(USER1_ID, true);
+ verify(listener, times(2)).onUserChanged(USER2_ID, UserListener.USER_VISIBILITY_CHANGED);
+ verify(listener, times(2)).onUserChanged(USER1_ID, UserListener.USER_VISIBILITY_CHANGED);
+ }
+
+ @Test
public void testListener_StartUser() {
UserListener listener = mock(UserListener.class);
mHelper.addListener(listener);
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
index 20e4e80..aa28ad4 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
@@ -175,7 +175,9 @@
doReturn(mWakeLock).when(mPowerManager).newWakeLock(anyInt(), anyString());
mInjector = new TestInjector(mContext);
+ mInjector.getUserInfoHelper().setUserVisible(CURRENT_USER, true);
mInjector.getUserInfoHelper().startUser(OTHER_USER);
+ mInjector.getUserInfoHelper().setUserVisible(OTHER_USER, true);
mPassive = new PassiveLocationProviderManager(mContext, mInjector);
mPassive.startManager(null);
@@ -331,6 +333,20 @@
}
@Test
+ public void testGetLastLocation_InvisibleUser() {
+ Location loc = createLocation(NAME, mRandom);
+ mProvider.setProviderLocation(loc);
+
+ mInjector.getUserInfoHelper().setUserVisible(CURRENT_USER, false);
+ assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
+ PERMISSION_FINE)).isNull();
+
+ mInjector.getUserInfoHelper().setUserVisible(CURRENT_USER, true);
+ assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
+ PERMISSION_FINE)).isEqualTo(loc);
+ }
+
+ @Test
public void testGetLastLocation_Bypass() {
mInjector.getSettingsHelper().setIgnoreSettingsAllowlist(
new PackageTagsList.Builder().add(
@@ -569,6 +585,25 @@
}
@Test
+ public void testRegisterListener_InvisibleUser() throws Exception {
+ ILocationListener listener = createMockLocationListener();
+ LocationRequest request = new LocationRequest.Builder(0)
+ .setWorkSource(WORK_SOURCE)
+ .build();
+ mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+
+ mInjector.getUserInfoHelper().setUserVisible(CURRENT_USER, false);
+ mProvider.setProviderLocation(createLocationResult(NAME, mRandom));
+ verify(listener, never()).onLocationChanged(any(List.class),
+ nullable(IRemoteCallback.class));
+
+ mInjector.getUserInfoHelper().setUserVisible(CURRENT_USER, true);
+ LocationResult loc = createLocationResult(NAME, mRandom);
+ mProvider.setProviderLocation(loc);
+ verify(listener).onLocationChanged(eq(loc.asList()), nullable(IRemoteCallback.class));
+ }
+
+ @Test
public void testRegisterListener_ExpiringAlarm() throws Exception {
ILocationListener listener = createMockLocationListener();
LocationRequest request = new LocationRequest.Builder(0)
@@ -799,6 +834,17 @@
}
@Test
+ public void testGetCurrentLocation_InvisibleUser() throws Exception {
+ mInjector.getUserInfoHelper().setUserVisible(CURRENT_USER, false);
+
+ ILocationCallback listener = createMockGetCurrentLocationListener();
+ LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
+ mManager.getCurrentLocation(request, IDENTITY, PERMISSION_FINE, listener);
+
+ verify(listener).onLocation(isNull());
+ }
+
+ @Test
public void testFlush() throws Exception {
ILocationListener listener = createMockLocationListener();
mManager.registerLocationRequest(
@@ -1008,6 +1054,21 @@
}
@Test
+ public void testProviderRequest_InvisibleUser() {
+ ILocationListener listener = createMockLocationListener();
+ LocationRequest request = new LocationRequest.Builder(5)
+ .setWorkSource(WORK_SOURCE)
+ .build();
+ mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+
+ mInjector.getUserInfoHelper().setUserVisible(CURRENT_USER, false);
+ assertThat(mProvider.getRequest().isActive()).isFalse();
+
+ mInjector.getUserInfoHelper().setUserVisible(CURRENT_USER, true);
+ assertThat(mProvider.getRequest().isActive()).isTrue();
+ }
+
+ @Test
public void testProviderRequest_IgnoreLocationSettings() {
mInjector.getSettingsHelper().setIgnoreSettingsAllowlist(
new PackageTagsList.Builder().add(
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
index f3f56e0..dc3515d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -114,6 +114,20 @@
}
@Test
+ public void backTypeBackToHomeDifferentUser() {
+ Task taskA = createTask(mDefaultDisplay);
+ ActivityRecord recordA = createActivityRecord(taskA);
+ Mockito.doNothing().when(recordA).reparentSurfaceControl(any(), any());
+ doReturn(false).when(taskA).showToCurrentUser();
+
+ withSystemCallback(createTopTaskWithActivity());
+ BackNavigationInfo backNavigationInfo = startBackNavigation();
+ assertWithMessage("BackNavigationInfo").that(backNavigationInfo).isNotNull();
+ assertThat(typeToString(backNavigationInfo.getType()))
+ .isEqualTo(typeToString(BackNavigationInfo.TYPE_RETURN_TO_HOME));
+ }
+
+ @Test
public void backTypeCrossActivityWhenBackToPreviousActivity() {
CrossActivityTestCase testCase = createTopTaskWithTwoActivities();
IOnBackInvokedCallback callback = withSystemCallback(testCase.task);
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index 2435243..86b98f1 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -5,7 +5,6 @@
import android.net.NetworkCapabilities;
import android.telecom.Connection;
import android.telephony.data.ApnSetting;
-import android.telephony.ims.ImsCallProfile;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -495,7 +494,7 @@
PreciseCallState.PRECISE_CALL_STATE_HOLDING,
PreciseCallState.PRECISE_CALL_STATE_DIALING,
PreciseCallState.PRECISE_CALL_STATE_ALERTING,
- PreciseCallState.PRECISE_CALL_STATE_INCOMING,
+ PreciseCallState. PRECISE_CALL_STATE_INCOMING,
PreciseCallState.PRECISE_CALL_STATE_WAITING,
PreciseCallState.PRECISE_CALL_STATE_DISCONNECTED,
PreciseCallState.PRECISE_CALL_STATE_DISCONNECTING})
@@ -728,36 +727,6 @@
})
public @interface ValidationStatus {}
- /**
- * IMS call Service types
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "SERVICE_TYPE_" }, value = {
- ImsCallProfile.SERVICE_TYPE_NONE,
- ImsCallProfile.SERVICE_TYPE_NORMAL,
- ImsCallProfile.SERVICE_TYPE_EMERGENCY,
- })
- public @interface ImsCallServiceType {}
-
- /**
- * IMS call types
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "CALL_TYPE_" }, value = {
- ImsCallProfile.CALL_TYPE_NONE,
- ImsCallProfile.CALL_TYPE_VOICE_N_VIDEO,
- ImsCallProfile.CALL_TYPE_VOICE,
- ImsCallProfile.CALL_TYPE_VIDEO_N_VOICE,
- ImsCallProfile.CALL_TYPE_VT,
- ImsCallProfile.CALL_TYPE_VT_TX,
- ImsCallProfile.CALL_TYPE_VT_RX,
- ImsCallProfile.CALL_TYPE_VT_NODIR,
- ImsCallProfile.CALL_TYPE_VS,
- ImsCallProfile.CALL_TYPE_VS_TX,
- ImsCallProfile.CALL_TYPE_VS_RX,
- })
- public @interface ImsCallType {}
-
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = { "NET_CAPABILITY_ENTERPRISE_SUB_LEVEL" }, value = {
diff --git a/telephony/java/android/telephony/CallAttributes.java b/telephony/java/android/telephony/CallAttributes.java
index 1dc64a9..b7bef39 100644
--- a/telephony/java/android/telephony/CallAttributes.java
+++ b/telephony/java/android/telephony/CallAttributes.java
@@ -29,10 +29,8 @@
* Contains information about a call's attributes as passed up from the HAL. If there are multiple
* ongoing calls, the CallAttributes will pertain to the call in the foreground.
* @hide
- * @deprecated use {@link CallState} for call information for each call.
*/
@SystemApi
-@Deprecated
public final class CallAttributes implements Parcelable {
private PreciseCallState mPreciseCallState;
@NetworkType
diff --git a/telephony/java/android/telephony/CallState.aidl b/telephony/java/android/telephony/CallState.aidl
deleted file mode 100644
index dd5af8e..0000000
--- a/telephony/java/android/telephony/CallState.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony;
-
-parcelable CallState;
-
diff --git a/telephony/java/android/telephony/CallState.java b/telephony/java/android/telephony/CallState.java
deleted file mode 100644
index 0a267cf..0000000
--- a/telephony/java/android/telephony/CallState.java
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.Annotation.ImsCallServiceType;
-import android.telephony.Annotation.ImsCallType;
-import android.telephony.Annotation.NetworkType;
-import android.telephony.Annotation.PreciseCallStates;
-import android.telephony.ims.ImsCallProfile;
-import android.telephony.ims.ImsCallSession;
-
-import java.util.Objects;
-
-/**
- * Contains information about various states for a call.
- * @hide
- */
-@SystemApi
-public final class CallState implements Parcelable {
-
- /**
- * Call classifications are just used for backward compatibility of deprecated API {@link
- * TelephonyCallback#CallAttributesListener#onCallAttributesChanged}, Since these will be
- * removed when the deprecated API is removed, they should not be opened.
- */
- /**
- * Call classification is not valid. It should not be opened.
- * @hide
- */
- public static final int CALL_CLASSIFICATION_UNKNOWN = -1;
-
- /**
- * Call classification indicating foreground call
- * @hide
- */
- public static final int CALL_CLASSIFICATION_RINGING = 0;
-
- /**
- * Call classification indicating background call
- * @hide
- */
- public static final int CALL_CLASSIFICATION_FOREGROUND = 1;
-
- /**
- * Call classification indicating ringing call
- * @hide
- */
- public static final int CALL_CLASSIFICATION_BACKGROUND = 2;
-
- /**
- * Call classification Max value.
- * @hide
- */
- public static final int CALL_CLASSIFICATION_MAX = CALL_CLASSIFICATION_BACKGROUND + 1;
-
- @PreciseCallStates
- private final int mPreciseCallState;
-
- @NetworkType
- private final int mNetworkType; // TelephonyManager.NETWORK_TYPE_* ints
- private final CallQuality mCallQuality;
-
- private final int mCallClassification;
- /**
- * IMS call session ID. {@link ImsCallSession#getCallId()}
- */
- @Nullable
- private String mImsCallId;
-
- /**
- * IMS call service type of this call
- */
- @ImsCallServiceType
- private int mImsCallServiceType;
-
- /**
- * IMS call type of this call.
- */
- @ImsCallType
- private int mImsCallType;
-
- /**
- * Constructor of CallAttributes
- *
- * @param callState call state defined in {@link PreciseCallState}
- * @param networkType network type for this call attributes
- * @param callQuality call quality for this call attributes, only CallState in
- * {@link PreciseCallState#PRECISE_CALL_STATE_ACTIVE} will have valid call
- * quality.
- * @param callClassification call classification
- * @param imsCallId IMS call session ID for this call attributes
- * @param imsCallServiceType IMS call service type for this call attributes
- * @param imsCallType IMS call type for this call attributes
- */
- private CallState(@PreciseCallStates int callState, @NetworkType int networkType,
- @NonNull CallQuality callQuality, int callClassification, @Nullable String imsCallId,
- @ImsCallServiceType int imsCallServiceType, @ImsCallType int imsCallType) {
- this.mPreciseCallState = callState;
- this.mNetworkType = networkType;
- this.mCallQuality = callQuality;
- this.mCallClassification = callClassification;
- this.mImsCallId = imsCallId;
- this.mImsCallServiceType = imsCallServiceType;
- this.mImsCallType = imsCallType;
- }
-
- @NonNull
- @Override
- public String toString() {
- return "mPreciseCallState=" + mPreciseCallState + " mNetworkType=" + mNetworkType
- + " mCallQuality=" + mCallQuality + " mCallClassification" + mCallClassification
- + " mImsCallId=" + mImsCallId + " mImsCallServiceType=" + mImsCallServiceType
- + " mImsCallType=" + mImsCallType;
- }
-
- private CallState(Parcel in) {
- this.mPreciseCallState = in.readInt();
- this.mNetworkType = in.readInt();
- this.mCallQuality = in.readParcelable(
- CallQuality.class.getClassLoader(), CallQuality.class);
- this.mCallClassification = in.readInt();
- this.mImsCallId = in.readString();
- this.mImsCallServiceType = in.readInt();
- this.mImsCallType = in.readInt();
- }
-
- // getters
- /**
- * Returns the precise call state of the call.
- */
- @PreciseCallStates
- public int getCallState() {
- return mPreciseCallState;
- }
-
- /**
- * Returns the {@link TelephonyManager#NetworkType} of the call.
- *
- * @see TelephonyManager#NETWORK_TYPE_UNKNOWN
- * @see TelephonyManager#NETWORK_TYPE_GPRS
- * @see TelephonyManager#NETWORK_TYPE_EDGE
- * @see TelephonyManager#NETWORK_TYPE_UMTS
- * @see TelephonyManager#NETWORK_TYPE_CDMA
- * @see TelephonyManager#NETWORK_TYPE_EVDO_0
- * @see TelephonyManager#NETWORK_TYPE_EVDO_A
- * @see TelephonyManager#NETWORK_TYPE_1xRTT
- * @see TelephonyManager#NETWORK_TYPE_HSDPA
- * @see TelephonyManager#NETWORK_TYPE_HSUPA
- * @see TelephonyManager#NETWORK_TYPE_HSPA
- * @see TelephonyManager#NETWORK_TYPE_IDEN
- * @see TelephonyManager#NETWORK_TYPE_EVDO_B
- * @see TelephonyManager#NETWORK_TYPE_LTE
- * @see TelephonyManager#NETWORK_TYPE_EHRPD
- * @see TelephonyManager#NETWORK_TYPE_HSPAP
- * @see TelephonyManager#NETWORK_TYPE_GSM
- * @see TelephonyManager#NETWORK_TYPE_TD_SCDMA
- * @see TelephonyManager#NETWORK_TYPE_IWLAN
- * @see TelephonyManager#NETWORK_TYPE_LTE_CA
- * @see TelephonyManager#NETWORK_TYPE_NR
- */
- @NetworkType
- public int getNetworkType() {
- return mNetworkType;
- }
-
- /**
- * Returns the {#link CallQuality} of the call.
- * @return call quality for this call attributes, only CallState in {@link PreciseCallState#
- * PRECISE_CALL_STATE_ACTIVE} will have valid call quality. It will be null for the
- * call which is not in {@link PreciseCallState#PRECISE_CALL_STATE_ACTIVE}.
- */
- @Nullable
- public CallQuality getCallQuality() {
- return mCallQuality;
- }
-
- /**
- * Returns the call classification.
- * @hide
- */
- public int getCallClassification() {
- return mCallClassification;
- }
-
- /**
- * Returns the IMS call session ID.
- */
- @Nullable
- public String getImsCallSessionId() {
- return mImsCallId;
- }
-
- /**
- * Returns the IMS call service type.
- */
- @ImsCallServiceType
- public int getImsCallServiceType() {
- return mImsCallServiceType;
- }
-
- /**
- * Returns the IMS call type.
- */
- @ImsCallType
- public int getImsCallType() {
- return mImsCallType;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mPreciseCallState, mNetworkType, mCallQuality, mCallClassification,
- mImsCallId, mImsCallServiceType, mImsCallType);
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (o == null || !(o instanceof CallState) || hashCode() != o.hashCode()) {
- return false;
- }
-
- if (this == o) {
- return true;
- }
-
- CallState s = (CallState) o;
-
- return (Objects.equals(mPreciseCallState, s.mPreciseCallState)
- && mPreciseCallState == s.mPreciseCallState
- && mNetworkType == s.mNetworkType
- && Objects.equals(mCallQuality, s.mCallQuality)
- && mCallClassification == s.mCallClassification
- && Objects.equals(mImsCallId, s.mImsCallId)
- && mImsCallType == s.mImsCallType
- && mImsCallServiceType == s.mImsCallServiceType);
- }
-
- /**
- * {@link Parcelable#describeContents}
- */
- public int describeContents() {
- return 0;
- }
-
- /**
- * {@link Parcelable#writeToParcel}
- */
- public void writeToParcel(@Nullable Parcel dest, int flags) {
- dest.writeInt(mPreciseCallState);
- dest.writeInt(mNetworkType);
- dest.writeParcelable(mCallQuality, flags);
- dest.writeInt(mCallClassification);
- dest.writeString(mImsCallId);
- dest.writeInt(mImsCallServiceType);
- dest.writeInt(mImsCallType);
- }
-
- public static final @NonNull Creator<CallState> CREATOR = new Creator() {
- public CallState createFromParcel(Parcel in) {
- return new CallState(in);
- }
-
- public CallState[] newArray(int size) {
- return new CallState[size];
- }
- };
-
- /**
- * Builder of {@link CallState}
- *
- * <p>The example below shows how you might create a new {@code CallState}:
- *
- * <pre><code>
- *
- * CallState = new CallState.Builder()
- * .setCallState(3)
- * .setNetworkType({@link TelephonyManager#NETWORK_TYPE_LTE})
- * .setCallQuality({@link CallQuality})
- * .setImsCallSessionId({@link String})
- * .setImsCallServiceType({@link ImsCallProfile#SERVICE_TYPE_NORMAL})
- * .setImsCallType({@link ImsCallProfile#CALL_TYPE_VOICE})
- * .build();
- * </code></pre>
- */
- public static final class Builder {
- private @PreciseCallStates int mPreciseCallState;
- private @NetworkType int mNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
- private CallQuality mCallQuality = null;
- private int mCallClassification = CALL_CLASSIFICATION_UNKNOWN;
- private String mImsCallId;
- private @ImsCallServiceType int mImsCallServiceType = ImsCallProfile.SERVICE_TYPE_NONE;
- private @ImsCallType int mImsCallType = ImsCallProfile.CALL_TYPE_NONE;
-
-
- /**
- * Default constructor for the Builder.
- */
- public Builder(@PreciseCallStates int preciseCallState) {
- mPreciseCallState = preciseCallState;
- }
-
- /**
- * Set network type of this call.
- *
- * @param networkType the transport type.
- * @return The same instance of the builder.
- */
- @NonNull
- public CallState.Builder setNetworkType(@NetworkType int networkType) {
- this.mNetworkType = networkType;
- return this;
- }
-
- /**
- * Set the call quality {@link CallQuality} of this call.
- *
- * @param callQuality call quality of active call.
- * @return The same instance of the builder.
- */
- @NonNull
- public CallState.Builder setCallQuality(@Nullable CallQuality callQuality) {
- this.mCallQuality = callQuality;
- return this;
- }
-
- /**
- * Set call classification for this call.
- *
- * @param classification call classification type defined in this class.
- * @return The same instance of the builder.
- * @hide
- */
- @NonNull
- public CallState.Builder setCallClassification(int classification) {
- this.mCallClassification = classification;
- return this;
- }
-
- /**
- * Set IMS call session ID of this call.
- *
- * @param imsCallId IMS call session ID.
- * @return The same instance of the builder.
- */
- @NonNull
- public CallState.Builder setImsCallSessionId(@Nullable String imsCallId) {
- this.mImsCallId = imsCallId;
- return this;
- }
-
- /**
- * Set IMS call service type of this call.
- *
- * @param serviceType IMS call service type defined in {@link ImsCallProfile}.
- * @return The same instance of the builder.
- */
- @NonNull
- public CallState.Builder setImsCallServiceType(@ImsCallServiceType int serviceType) {
- this.mImsCallServiceType = serviceType;
- return this;
- }
-
- /**
- * Set IMS call type of this call.
- *
- * @param callType IMS call type defined in {@link ImsCallProfile}.
- * @return The same instance of the builder.
- */
- @NonNull
- public CallState.Builder setImsCallType(@ImsCallType int callType) {
- this.mImsCallType = callType;
- return this;
- }
-
- /**
- * Build the {@link CallState}
- *
- * @return the {@link CallState} object
- */
- @NonNull
- public CallState build() {
- return new CallState(
- mPreciseCallState,
- mNetworkType,
- mCallQuality,
- mCallClassification,
- mImsCallId,
- mImsCallServiceType,
- mImsCallType);
- }
- }
-}
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 1ea7fdc..e6d7df3 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -78,9 +78,8 @@
public static final int SERVICE_TYPE_EMERGENCY = 2;
/**
- * Call type none
+ * Call types
*/
- public static final int CALL_TYPE_NONE = 0;
/**
* IMSPhone to support IR.92 & IR.94 (voice + video upgrade/downgrade)
*/
diff --git a/tools/lint/common/Android.bp b/tools/lint/common/Android.bp
new file mode 100644
index 0000000..898f88b
--- /dev/null
+++ b/tools/lint/common/Android.bp
@@ -0,0 +1,29 @@
+// 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+java_library_host {
+ name: "AndroidCommonLint",
+ srcs: ["src/main/java/**/*.kt"],
+ libs: ["lint_api"],
+ kotlincflags: ["-Xjvm-default=all"],
+}
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/Constants.kt b/tools/lint/common/src/main/java/com/google/android/lint/Constants.kt
similarity index 100%
rename from tools/lint/checks/src/main/java/com/google/android/lint/Constants.kt
rename to tools/lint/common/src/main/java/com/google/android/lint/Constants.kt
diff --git a/tools/lint/common/src/main/java/com/google/android/lint/PermissionMethodUtils.kt b/tools/lint/common/src/main/java/com/google/android/lint/PermissionMethodUtils.kt
new file mode 100644
index 0000000..720f835
--- /dev/null
+++ b/tools/lint/common/src/main/java/com/google/android/lint/PermissionMethodUtils.kt
@@ -0,0 +1,36 @@
+/*
+ * 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.google.android.lint
+
+import com.android.tools.lint.detector.api.getUMethod
+import org.jetbrains.uast.UCallExpression
+import org.jetbrains.uast.UMethod
+import org.jetbrains.uast.UParameter
+
+fun isPermissionMethodCall(callExpression: UCallExpression): Boolean {
+ val method = callExpression.resolve()?.getUMethod() ?: return false
+ return hasPermissionMethodAnnotation(method)
+}
+
+fun hasPermissionMethodAnnotation(method: UMethod): Boolean = method.annotations
+ .any {
+ it.hasQualifiedName(ANNOTATION_PERMISSION_METHOD)
+ }
+
+fun hasPermissionNameAnnotation(parameter: UParameter) = parameter.annotations.any {
+ it.hasQualifiedName(ANNOTATION_PERMISSION_NAME)
+}
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/model/Method.kt b/tools/lint/common/src/main/java/com/google/android/lint/model/Method.kt
similarity index 100%
rename from tools/lint/checks/src/main/java/com/google/android/lint/model/Method.kt
rename to tools/lint/common/src/main/java/com/google/android/lint/model/Method.kt
diff --git a/tools/lint/fix/Android.bp b/tools/lint/fix/Android.bp
new file mode 100644
index 0000000..5f6c6f7
--- /dev/null
+++ b/tools/lint/fix/Android.bp
@@ -0,0 +1,28 @@
+// 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+python_binary_host {
+ name: "lint_fix",
+ main: "lint_fix.py",
+ srcs: ["lint_fix.py"],
+}
diff --git a/tools/lint/Android.bp b/tools/lint/framework/Android.bp
similarity index 87%
rename from tools/lint/Android.bp
rename to tools/lint/framework/Android.bp
index 96618f4..7f27e8a 100644
--- a/tools/lint/Android.bp
+++ b/tools/lint/framework/Android.bp
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Android Open Source Project
+// 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.
@@ -29,6 +29,11 @@
"auto_service_annotations",
"lint_api",
],
+ static_libs: [
+ "AndroidCommonLint",
+ // TODO: remove once b/236558918 is resolved and the below checks actually run globally
+ "AndroidGlobalLintChecker",
+ ],
kotlincflags: ["-Xjvm-default=all"],
}
@@ -51,9 +56,3 @@
unit_test: true,
},
}
-
-python_binary_host {
- name: "lint_fix",
- main: "fix/lint_fix.py",
- srcs: ["fix/lint_fix.py"],
-}
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt b/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt
similarity index 100%
rename from tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt
rename to tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/CallingIdentityTokenDetector.kt b/tools/lint/framework/checks/src/main/java/com/google/android/lint/CallingIdentityTokenDetector.kt
similarity index 100%
rename from tools/lint/checks/src/main/java/com/google/android/lint/CallingIdentityTokenDetector.kt
rename to tools/lint/framework/checks/src/main/java/com/google/android/lint/CallingIdentityTokenDetector.kt
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsDetector.kt b/tools/lint/framework/checks/src/main/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsDetector.kt
similarity index 100%
rename from tools/lint/checks/src/main/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsDetector.kt
rename to tools/lint/framework/checks/src/main/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsDetector.kt
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/PackageVisibilityDetector.kt b/tools/lint/framework/checks/src/main/java/com/google/android/lint/PackageVisibilityDetector.kt
similarity index 100%
rename from tools/lint/checks/src/main/java/com/google/android/lint/PackageVisibilityDetector.kt
rename to tools/lint/framework/checks/src/main/java/com/google/android/lint/PackageVisibilityDetector.kt
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/PermissionMethodDetector.kt b/tools/lint/framework/checks/src/main/java/com/google/android/lint/PermissionMethodDetector.kt
similarity index 97%
rename from tools/lint/checks/src/main/java/com/google/android/lint/PermissionMethodDetector.kt
rename to tools/lint/framework/checks/src/main/java/com/google/android/lint/PermissionMethodDetector.kt
index 1b0f035..e12ec3d 100644
--- a/tools/lint/checks/src/main/java/com/google/android/lint/PermissionMethodDetector.kt
+++ b/tools/lint/framework/checks/src/main/java/com/google/android/lint/PermissionMethodDetector.kt
@@ -26,7 +26,6 @@
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.SourceCodeScanner
import com.android.tools.lint.detector.api.getUMethod
-import com.google.android.lint.aidl.hasPermissionMethodAnnotation
import com.intellij.psi.PsiType
import org.jetbrains.uast.UAnnotation
import org.jetbrains.uast.UBlockExpression
@@ -193,5 +192,8 @@
else -> false
}
}
+
+ private fun hasPermissionMethodAnnotation(method: UMethod): Boolean = method.annotations
+ .any { it.hasQualifiedName(ANNOTATION_PERMISSION_METHOD) }
}
}
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/RegisterReceiverFlagDetector.kt b/tools/lint/framework/checks/src/main/java/com/google/android/lint/RegisterReceiverFlagDetector.kt
similarity index 100%
rename from tools/lint/checks/src/main/java/com/google/android/lint/RegisterReceiverFlagDetector.kt
rename to tools/lint/framework/checks/src/main/java/com/google/android/lint/RegisterReceiverFlagDetector.kt
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/parcel/CallMigrators.kt b/tools/lint/framework/checks/src/main/java/com/google/android/lint/parcel/CallMigrators.kt
similarity index 100%
rename from tools/lint/checks/src/main/java/com/google/android/lint/parcel/CallMigrators.kt
rename to tools/lint/framework/checks/src/main/java/com/google/android/lint/parcel/CallMigrators.kt
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/parcel/Method.kt b/tools/lint/framework/checks/src/main/java/com/google/android/lint/parcel/Method.kt
similarity index 100%
rename from tools/lint/checks/src/main/java/com/google/android/lint/parcel/Method.kt
rename to tools/lint/framework/checks/src/main/java/com/google/android/lint/parcel/Method.kt
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/parcel/SaferParcelChecker.kt b/tools/lint/framework/checks/src/main/java/com/google/android/lint/parcel/SaferParcelChecker.kt
similarity index 100%
rename from tools/lint/checks/src/main/java/com/google/android/lint/parcel/SaferParcelChecker.kt
rename to tools/lint/framework/checks/src/main/java/com/google/android/lint/parcel/SaferParcelChecker.kt
diff --git a/tools/lint/checks/src/test/java/com/google/android/lint/CallingIdentityTokenDetectorTest.kt b/tools/lint/framework/checks/src/test/java/com/google/android/lint/CallingIdentityTokenDetectorTest.kt
similarity index 100%
rename from tools/lint/checks/src/test/java/com/google/android/lint/CallingIdentityTokenDetectorTest.kt
rename to tools/lint/framework/checks/src/test/java/com/google/android/lint/CallingIdentityTokenDetectorTest.kt
diff --git a/tools/lint/checks/src/test/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsIssueDetectorTest.kt b/tools/lint/framework/checks/src/test/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsIssueDetectorTest.kt
similarity index 100%
rename from tools/lint/checks/src/test/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsIssueDetectorTest.kt
rename to tools/lint/framework/checks/src/test/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsIssueDetectorTest.kt
diff --git a/tools/lint/checks/src/test/java/com/google/android/lint/PackageVisibilityDetectorTest.kt b/tools/lint/framework/checks/src/test/java/com/google/android/lint/PackageVisibilityDetectorTest.kt
similarity index 100%
rename from tools/lint/checks/src/test/java/com/google/android/lint/PackageVisibilityDetectorTest.kt
rename to tools/lint/framework/checks/src/test/java/com/google/android/lint/PackageVisibilityDetectorTest.kt
diff --git a/tools/lint/checks/src/test/java/com/google/android/lint/RegisterReceiverFlagDetectorTest.kt b/tools/lint/framework/checks/src/test/java/com/google/android/lint/RegisterReceiverFlagDetectorTest.kt
similarity index 100%
rename from tools/lint/checks/src/test/java/com/google/android/lint/RegisterReceiverFlagDetectorTest.kt
rename to tools/lint/framework/checks/src/test/java/com/google/android/lint/RegisterReceiverFlagDetectorTest.kt
diff --git a/tools/lint/checks/src/test/java/com/google/android/lint/parcel/SaferParcelCheckerTest.kt b/tools/lint/framework/checks/src/test/java/com/google/android/lint/parcel/SaferParcelCheckerTest.kt
similarity index 100%
rename from tools/lint/checks/src/test/java/com/google/android/lint/parcel/SaferParcelCheckerTest.kt
rename to tools/lint/framework/checks/src/test/java/com/google/android/lint/parcel/SaferParcelCheckerTest.kt
diff --git a/tools/lint/Android.bp b/tools/lint/global/Android.bp
similarity index 84%
copy from tools/lint/Android.bp
copy to tools/lint/global/Android.bp
index 96618f4..3756abe 100644
--- a/tools/lint/Android.bp
+++ b/tools/lint/global/Android.bp
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Android Open Source Project
+// 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.
@@ -22,18 +22,22 @@
}
java_library_host {
- name: "AndroidFrameworkLintChecker",
+ name: "AndroidGlobalLintChecker",
srcs: ["checks/src/main/java/**/*.kt"],
plugins: ["auto_service_plugin"],
libs: [
"auto_service_annotations",
"lint_api",
],
+ static_libs: ["AndroidCommonLint"],
kotlincflags: ["-Xjvm-default=all"],
+ dist: {
+ targets: ["droid"],
+ },
}
java_test_host {
- name: "AndroidFrameworkLintCheckerTest",
+ name: "AndroidGlobalLintCheckerTest",
// TODO(b/239881504): Since this test was written, Android
// Lint was updated, and now includes classes that were
// compiled for java 15. The soong build doesn't support
@@ -42,7 +46,7 @@
enabled: false,
srcs: ["checks/src/test/java/**/*.kt"],
static_libs: [
- "AndroidFrameworkLintChecker",
+ "AndroidGlobalLintChecker",
"junit",
"lint",
"lint_tests",
@@ -51,9 +55,3 @@
unit_test: true,
},
}
-
-python_binary_host {
- name: "lint_fix",
- main: "fix/lint_fix.py",
- srcs: ["fix/lint_fix.py"],
-}
diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/AndroidGlobalIssueRegistry.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/AndroidGlobalIssueRegistry.kt
new file mode 100644
index 0000000..b377d50
--- /dev/null
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/AndroidGlobalIssueRegistry.kt
@@ -0,0 +1,48 @@
+/*
+ * 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.google.android.lint
+
+import com.android.tools.lint.client.api.IssueRegistry
+import com.android.tools.lint.client.api.Vendor
+import com.android.tools.lint.detector.api.CURRENT_API
+import com.google.android.lint.aidl.EnforcePermissionDetector
+import com.google.android.lint.aidl.EnforcePermissionHelperDetector
+import com.google.android.lint.aidl.SimpleManualPermissionEnforcementDetector
+import com.google.auto.service.AutoService
+
+@AutoService(IssueRegistry::class)
+@Suppress("UnstableApiUsage")
+class AndroidGlobalIssueRegistry : IssueRegistry() {
+ override val issues = listOf(
+ EnforcePermissionDetector.ISSUE_MISSING_ENFORCE_PERMISSION,
+ EnforcePermissionDetector.ISSUE_MISMATCHING_ENFORCE_PERMISSION,
+ EnforcePermissionHelperDetector.ISSUE_ENFORCE_PERMISSION_HELPER,
+ SimpleManualPermissionEnforcementDetector.ISSUE_USE_ENFORCE_PERMISSION_ANNOTATION,
+ )
+
+ override val api: Int
+ get() = CURRENT_API
+
+ override val minApi: Int
+ get() = 8
+
+ override val vendor: Vendor = Vendor(
+ vendorName = "Android",
+ feedbackUrl = "http://b/issues/new?component=315013",
+ contact = "repsonsible-apis@google.com"
+ )
+}
\ No newline at end of file
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/aidl/AidlImplementationDetector.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/AidlImplementationDetector.kt
similarity index 100%
rename from tools/lint/checks/src/main/java/com/google/android/lint/aidl/AidlImplementationDetector.kt
rename to tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/AidlImplementationDetector.kt
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/aidl/Constants.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt
similarity index 100%
rename from tools/lint/checks/src/main/java/com/google/android/lint/aidl/Constants.kt
rename to tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionDetector.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionDetector.kt
similarity index 100%
rename from tools/lint/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionDetector.kt
rename to tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionDetector.kt
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt
similarity index 97%
rename from tools/lint/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt
rename to tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt
index d120e1d..f1b6348 100644
--- a/tools/lint/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt
@@ -19,6 +19,8 @@
import com.android.tools.lint.detector.api.JavaContext
import com.android.tools.lint.detector.api.Location
import com.android.tools.lint.detector.api.getUMethod
+import com.google.android.lint.hasPermissionNameAnnotation
+import com.google.android.lint.isPermissionMethodCall
import org.jetbrains.kotlin.psi.psiUtil.parameterIndex
import org.jetbrains.uast.UCallExpression
import org.jetbrains.uast.evaluateString
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionHelperDetector.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionHelperDetector.kt
similarity index 100%
rename from tools/lint/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionHelperDetector.kt
rename to tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionHelperDetector.kt
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt
similarity index 69%
rename from tools/lint/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt
rename to tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt
index edbdd8d..250ca78 100644
--- a/tools/lint/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt
@@ -16,14 +16,9 @@
package com.google.android.lint.aidl
-import com.android.tools.lint.detector.api.getUMethod
-import com.google.android.lint.ANNOTATION_PERMISSION_METHOD
-import com.google.android.lint.ANNOTATION_PERMISSION_NAME
import com.google.android.lint.CLASS_STUB
import com.intellij.psi.PsiAnonymousClass
-import org.jetbrains.uast.UCallExpression
import org.jetbrains.uast.UMethod
-import org.jetbrains.uast.UParameter
/**
* Given a UMethod, determine if this method is
@@ -51,17 +46,3 @@
it.referenceName == CLASS_STUB
} ?: false
}
-
-fun isPermissionMethodCall(callExpression: UCallExpression): Boolean {
- val method = callExpression.resolve()?.getUMethod() ?: return false
- return hasPermissionMethodAnnotation(method)
-}
-
-fun hasPermissionMethodAnnotation(method: UMethod): Boolean = method.annotations
- .any {
- it.hasQualifiedName(ANNOTATION_PERMISSION_METHOD)
- }
-
-fun hasPermissionNameAnnotation(parameter: UParameter) = parameter.annotations.any {
- it.hasQualifiedName(ANNOTATION_PERMISSION_NAME)
-}
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt
similarity index 100%
rename from tools/lint/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt
rename to tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt
diff --git a/tools/lint/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionDetectorTest.kt b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionDetectorTest.kt
similarity index 100%
rename from tools/lint/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionDetectorTest.kt
rename to tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionDetectorTest.kt
diff --git a/tools/lint/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionHelperDetectorTest.kt b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionHelperDetectorTest.kt
similarity index 100%
rename from tools/lint/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionHelperDetectorTest.kt
rename to tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionHelperDetectorTest.kt
diff --git a/tools/lint/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt
similarity index 100%
rename from tools/lint/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt
rename to tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt
diff --git a/tools/lint/checks/src/test/java/com/google/android/lint/aidl/Stubs.kt b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/Stubs.kt
similarity index 100%
rename from tools/lint/checks/src/test/java/com/google/android/lint/aidl/Stubs.kt
rename to tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/Stubs.kt