diff options
9 files changed, 179 insertions, 87 deletions
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/LauncherPackagesLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/LauncherPackagesLiveData.kt index da0f26000..f0d811821 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/data/LauncherPackagesLiveData.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/data/LauncherPackagesLiveData.kt @@ -19,6 +19,7 @@ package com.android.permissioncontroller.permission.data import android.content.Intent import android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE import android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE +import android.content.pm.PackageManager.FEATURE_LEANBACK import com.android.permissioncontroller.PermissionControllerApplication import kotlinx.coroutines.Job @@ -31,14 +32,26 @@ object LauncherPackagesLiveData : SmartAsyncMediatorLiveData<Set<String>>(), private val LAUNCHER_INTENT = Intent(Intent.ACTION_MAIN, null) .addCategory(Intent.CATEGORY_LAUNCHER) + // On ATV some apps may have a leanback launcher icon but no regular launcher icon + private val LEANBACK_LAUNCHER_INTENT = Intent(Intent.ACTION_MAIN, null) + .addCategory(Intent.CATEGORY_LEANBACK_LAUNCHER) + override suspend fun loadDataAndPostValue(job: Job) { val launcherPkgs = mutableSetOf<String>() + + loadPkgsFromIntent(launcherPkgs, LAUNCHER_INTENT) + if (PermissionControllerApplication.get().packageManager + .hasSystemFeature(FEATURE_LEANBACK)) { + loadPkgsFromIntent(launcherPkgs, LEANBACK_LAUNCHER_INTENT) + } + postValue(launcherPkgs) + } + + private fun loadPkgsFromIntent(launcherPkgs: MutableSet<String>, intent: Intent) { for (info in PermissionControllerApplication.get().packageManager.queryIntentActivities( - LAUNCHER_INTENT, MATCH_DIRECT_BOOT_AWARE or MATCH_DIRECT_BOOT_UNAWARE)) { + intent, MATCH_DIRECT_BOOT_AWARE or MATCH_DIRECT_BOOT_UNAWARE)) { launcherPkgs.add(info.activityInfo.packageName) } - - postValue(launcherPkgs) } override fun onPackageUpdate(packageName: String) { diff --git a/PermissionController/src/com/android/permissioncontroller/role/RolePermissionProtection.md b/PermissionController/src/com/android/permissioncontroller/role/RolePermissionProtection.md index 975840aaa..f632332f3 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/RolePermissionProtection.md +++ b/PermissionController/src/com/android/permissioncontroller/role/RolePermissionProtection.md @@ -93,8 +93,8 @@ overlay. Since role is modularized, we also need to make this config resource a system API for access by role. -Edit `frameworks/base/core/res/res/values/public.xml` to expose the new config resource as a system -API: +Edit `frameworks/base/core/res/res/values/public-staging.xml` to expose the new config resource as +a system API: ```xml <staging-public-group type="string" first-id="0xXXXXXXXX"> diff --git a/framework-s/api/system-current.txt b/framework-s/api/system-current.txt index 67c2b85b4..764c3774f 100644 --- a/framework-s/api/system-current.txt +++ b/framework-s/api/system-current.txt @@ -170,7 +170,7 @@ package android.safetycenter { method @NonNull public android.app.PendingIntent getPendingIntent(); method @Nullable public CharSequence getSuccessMessage(); method public boolean isInFlight(); - method public boolean isResolving(); + method public boolean willResolve(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.safetycenter.SafetyCenterIssue.Action> CREATOR; } @@ -178,11 +178,11 @@ package android.safetycenter { public static final class SafetyCenterIssue.Action.Builder { ctor public SafetyCenterIssue.Action.Builder(@NonNull String); method @NonNull public android.safetycenter.SafetyCenterIssue.Action build(); - method @NonNull public android.safetycenter.SafetyCenterIssue.Action.Builder setInFlight(boolean); + method @NonNull public android.safetycenter.SafetyCenterIssue.Action.Builder setIsInFlight(boolean); method @NonNull public android.safetycenter.SafetyCenterIssue.Action.Builder setLabel(@NonNull CharSequence); method @NonNull public android.safetycenter.SafetyCenterIssue.Action.Builder setPendingIntent(@NonNull android.app.PendingIntent); - method @NonNull public android.safetycenter.SafetyCenterIssue.Action.Builder setResolving(boolean); method @NonNull public android.safetycenter.SafetyCenterIssue.Action.Builder setSuccessMessage(@Nullable CharSequence); + method @NonNull public android.safetycenter.SafetyCenterIssue.Action.Builder setWillResolve(boolean); } public static final class SafetyCenterIssue.Builder { diff --git a/framework-s/java/android/safetycenter/SafetyCenterIssue.java b/framework-s/java/android/safetycenter/SafetyCenterIssue.java index 9f5b83c55..3371bc852 100644 --- a/framework-s/java/android/safetycenter/SafetyCenterIssue.java +++ b/framework-s/java/android/safetycenter/SafetyCenterIssue.java @@ -23,6 +23,7 @@ import static java.util.Objects.requireNonNull; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.app.PendingIntent; import android.os.Parcel; @@ -370,7 +371,7 @@ public final class SafetyCenterIssue implements Parcelable { private final CharSequence mLabel; @NonNull private final PendingIntent mPendingIntent; - private final boolean mResolving; + private final boolean mWillResolve; private final boolean mInFlight; @Nullable private final CharSequence mSuccessMessage; @@ -379,13 +380,13 @@ public final class SafetyCenterIssue implements Parcelable { @NonNull String id, @NonNull CharSequence label, @NonNull PendingIntent pendingIntent, - boolean resolving, + boolean willResolve, boolean inFlight, @Nullable CharSequence successMessage) { mId = requireNonNull(id); mLabel = requireNonNull(label); mPendingIntent = requireNonNull(pendingIntent); - mResolving = resolving; + mWillResolve = willResolve; mInFlight = inFlight; mSuccessMessage = successMessage; } @@ -410,14 +411,18 @@ public final class SafetyCenterIssue implements Parcelable { /** * Returns whether invoking this action will fix or address the issue sufficiently for it - * to be considered resolved i.e. the issue will no longer need to be conveyed to the user - * in the UI. + * to be considered resolved (i.e. the issue will no longer need to be conveyed to the user + * in the UI). */ - public boolean isResolving() { - return mResolving; + public boolean willResolve() { + return mWillResolve; } - /** Returns whether or not this action is currently being executed. */ + /** + * Returns whether or not this action is currently being executed (i.e. the user clicked + * on a button that triggered this action, and now the Safety Center is waiting for the + * action's result). + */ public boolean isInFlight() { return mInFlight; } @@ -439,7 +444,7 @@ public final class SafetyCenterIssue implements Parcelable { return Objects.equals(mId, action.mId) && TextUtils.equals(mLabel, action.mLabel) && Objects.equals(mPendingIntent, action.mPendingIntent) - && mResolving == action.mResolving + && mWillResolve == action.mWillResolve && mInFlight == action.mInFlight && TextUtils.equals(mSuccessMessage, action.mSuccessMessage); } @@ -447,7 +452,7 @@ public final class SafetyCenterIssue implements Parcelable { @Override public int hashCode() { return Objects.hash( - mId, mLabel, mSuccessMessage, mResolving, mInFlight, mPendingIntent); + mId, mLabel, mSuccessMessage, mWillResolve, mInFlight, mPendingIntent); } @Override @@ -456,7 +461,7 @@ public final class SafetyCenterIssue implements Parcelable { + "mId=" + mId + ", mLabel=" + mLabel + ", mPendingIntent=" + mPendingIntent - + ", mResolving=" + mResolving + + ", mWillResolve=" + mWillResolve + ", mInFlight=" + mInFlight + ", mSuccessMessage=" + mSuccessMessage + '}'; @@ -472,7 +477,7 @@ public final class SafetyCenterIssue implements Parcelable { dest.writeString(mId); TextUtils.writeToParcel(mLabel, dest, flags); dest.writeParcelable(mPendingIntent, flags); - dest.writeBoolean(mResolving); + dest.writeBoolean(mWillResolve); dest.writeBoolean(mInFlight); TextUtils.writeToParcel(mSuccessMessage, dest, flags); } @@ -486,8 +491,8 @@ public final class SafetyCenterIssue implements Parcelable { .setPendingIntent( in.readParcelable( PendingIntent.class.getClassLoader(), PendingIntent.class)) - .setResolving(in.readBoolean()) - .setInFlight(in.readBoolean()) + .setWillResolve(in.readBoolean()) + .setIsInFlight(in.readBoolean()) .setSuccessMessage(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in)) .build(); } @@ -503,7 +508,7 @@ public final class SafetyCenterIssue implements Parcelable { private String mId; private CharSequence mLabel; private PendingIntent mPendingIntent; - private boolean mResolving; + private boolean mWillResolve; private boolean mInFlight; private CharSequence mSuccessMessage; @@ -529,23 +534,28 @@ public final class SafetyCenterIssue implements Parcelable { } /** - * Sets whether or not this action is resolving. Defaults to false. + * Sets whether or not this action will resolve the issue when executed. Defaults to + * false. * - * @see #isResolving() + * @see #willResolve() */ + @SuppressLint("MissingGetterMatchingBuilder") @NonNull - public Builder setResolving(boolean resolving) { - mResolving = resolving; + public Builder setWillResolve(boolean willResolve) { + mWillResolve = willResolve; return this; } /** - * Sets whether or not this action is in flight. Defaults to false. + * Sets a boolean that indicates whether or not this action is currently being executed + * (i.e. the user clicked on a button that triggered this action, and now the Safety + * Center is waiting for the action's result). Defaults to false. * * @see #isInFlight() */ + @SuppressLint("MissingGetterMatchingBuilder") @NonNull - public Builder setInFlight(boolean inFlight) { + public Builder setIsInFlight(boolean inFlight) { mInFlight = inFlight; return this; } @@ -564,7 +574,7 @@ public final class SafetyCenterIssue implements Parcelable { @NonNull public Action build() { return new Action( - mId, mLabel, mPendingIntent, mResolving, mInFlight, mSuccessMessage); + mId, mLabel, mPendingIntent, mWillResolve, mInFlight, mSuccessMessage); } } } diff --git a/service/java/com/android/safetycenter/SafetyCenterListeners.java b/service/java/com/android/safetycenter/SafetyCenterListeners.java index 184d23429..f1bb012e3 100644 --- a/service/java/com/android/safetycenter/SafetyCenterListeners.java +++ b/service/java/com/android/safetycenter/SafetyCenterListeners.java @@ -21,11 +21,11 @@ import static android.os.Build.VERSION_CODES.TIRAMISU; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; -import android.os.Binder; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.safetycenter.IOnSafetyCenterDataChangedListener; import android.safetycenter.SafetyCenterData; +import android.safetycenter.SafetyCenterErrorDetails; import android.util.Log; import android.util.SparseArray; @@ -56,13 +56,10 @@ final class SafetyCenterListeners { static void deliverUpdate( @NonNull IOnSafetyCenterDataChangedListener listener, @NonNull SafetyCenterData safetyCenterData) { - final long identity = Binder.clearCallingIdentity(); try { listener.onSafetyCenterDataChanged(safetyCenterData); } catch (RemoteException e) { - Log.e(TAG, "Error delivering SafetyCenterData update to listener", e); - } finally { - Binder.restoreCallingIdentity(identity); + Log.e(TAG, "Error delivering SafetyCenterData to listener", e); } } @@ -85,6 +82,39 @@ final class SafetyCenterListeners { listeners.finishBroadcast(); } + /** + * Delivers a {@link SafetyCenterErrorDetails} update to a single {@link + * IOnSafetyCenterDataChangedListener}. + */ + private static void deliverError( + @NonNull IOnSafetyCenterDataChangedListener listener, + @NonNull SafetyCenterErrorDetails safetyCenterErrorDetails) { + try { + listener.onError(safetyCenterErrorDetails); + } catch (RemoteException e) { + Log.e(TAG, "Error delivering SafetyCenterErrorDetails to listener", e); + } + } + + /** + * Delivers a {@link SafetyCenterErrorDetails} update to a {@link RemoteCallbackList} of {@link + * IOnSafetyCenterDataChangedListener}. + * + * <p>Registering or unregistering {@link IOnSafetyCenterDataChangedListener} on the underlying + * {@link RemoteCallbackList} on another thread while an update is happening is safe as this is + * handled by the {@link RemoteCallbackList} already (as well as listeners death). + */ + static void deliverError( + @NonNull RemoteCallbackList<IOnSafetyCenterDataChangedListener> listeners, + @NonNull SafetyCenterErrorDetails safetyCenterErrorDetails) { + int i = listeners.beginBroadcast(); + while (i > 0) { + i--; + deliverError(listeners.getBroadcastItem(i), safetyCenterErrorDetails); + } + listeners.finishBroadcast(); + } + /** Adds a {@link IOnSafetyCenterDataChangedListener} for the given {@code userId}. */ void addListener( @NonNull IOnSafetyCenterDataChangedListener listener, diff --git a/service/java/com/android/safetycenter/SafetyCenterService.java b/service/java/com/android/safetycenter/SafetyCenterService.java index cea0ae404..6096925b8 100644 --- a/service/java/com/android/safetycenter/SafetyCenterService.java +++ b/service/java/com/android/safetycenter/SafetyCenterService.java @@ -39,6 +39,7 @@ import android.provider.DeviceConfig; import android.safetycenter.IOnSafetyCenterDataChangedListener; import android.safetycenter.ISafetyCenterManager; import android.safetycenter.SafetyCenterData; +import android.safetycenter.SafetyCenterErrorDetails; import android.safetycenter.SafetyEvent; import android.safetycenter.SafetySourceData; import android.safetycenter.SafetySourceErrorDetails; @@ -194,7 +195,14 @@ public final class SafetyCenterService extends SystemService { if (!checkApiEnabled("reportSafetySourceError")) { return; } + // TODO(b/218379298): Add implementation + RemoteCallbackList<IOnSafetyCenterDataChangedListener> listeners; + synchronized (mApiLock) { + listeners = mSafetyCenterListeners.getListeners(userId); + } + + SafetyCenterListeners.deliverError(listeners, new SafetyCenterErrorDetails("Error")); } @Override diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterIssueTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterIssueTest.kt index a8428049c..819124611 100644 --- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterIssueTest.kt +++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterIssueTest.kt @@ -48,15 +48,15 @@ class SafetyCenterIssueTest { val action1 = SafetyCenterIssue.Action.Builder("action_id_1") .setLabel("an action") .setPendingIntent(pendingIntent1) - .setResolving(true) - .setInFlight(true) + .setWillResolve(true) + .setIsInFlight(true) .setSuccessMessage("a success message") .build() val action2 = SafetyCenterIssue.Action.Builder("action_id_2") .setLabel("another action") .setPendingIntent(pendingIntent2) - .setResolving(false) - .setInFlight(false) + .setWillResolve(false) + .setIsInFlight(false) .build() val issue1 = SafetyCenterIssue.Builder("issue_id") @@ -330,9 +330,9 @@ class SafetyCenterIssueTest { } @Test - fun action_isResolving_returnsIsResolving() { - assertThat(action1.isResolving).isTrue() - assertThat(action2.isResolving).isFalse() + fun action_willResolve_returnsWillResolve() { + assertThat(action1.willResolve()).isTrue() + assertThat(action2.willResolve()).isFalse() } @Test @@ -377,15 +377,15 @@ class SafetyCenterIssueTest { val action = SafetyCenterIssue.Action.Builder("an_id") .setLabel("a label") .setPendingIntent(pendingIntent1) - .setResolving(true) - .setInFlight(true) + .setWillResolve(true) + .setIsInFlight(true) .setSuccessMessage("a success message") .build() val equivalentAction = SafetyCenterIssue.Action.Builder("an_id") .setLabel("a label") .setPendingIntent(pendingIntent1) - .setResolving(true) - .setInFlight(true) + .setWillResolve(true) + .setIsInFlight(true) .setSuccessMessage("a success message") .build() @@ -445,17 +445,17 @@ class SafetyCenterIssueTest { } @Test - fun action_equals_toString_differentResovlingValues_areNotEqual() { + fun action_equals_toString_differentWillResolveValues_areNotEqual() { val action = SafetyCenterIssue.Action.Builder("an_id") .setLabel("a label") .setPendingIntent(pendingIntent1) - .setResolving(true) + .setWillResolve(true) .setSuccessMessage("a success message") .build() val differentAction = SafetyCenterIssue.Action.Builder("an_id") .setLabel("a label") .setPendingIntent(pendingIntent1) - .setResolving(false) + .setWillResolve(false) .setSuccessMessage("a success message") .build() @@ -468,15 +468,15 @@ class SafetyCenterIssueTest { val action = SafetyCenterIssue.Action.Builder("an_id") .setLabel("a label") .setPendingIntent(pendingIntent1) - .setResolving(true) - .setInFlight(true) + .setWillResolve(true) + .setIsInFlight(true) .setSuccessMessage("a success message") .build() val differentAction = SafetyCenterIssue.Action.Builder("an_id") .setLabel("a label") .setPendingIntent(pendingIntent1) - .setResolving(true) - .setInFlight(false) + .setWillResolve(true) + .setIsInFlight(false) .setSuccessMessage("a success message") .build() diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt index a574a7892..af785eecf 100644 --- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt +++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt @@ -25,6 +25,7 @@ import android.content.Intent import android.content.Intent.ACTION_SAFETY_CENTER import android.os.Build.VERSION_CODES.TIRAMISU import android.safetycenter.SafetyCenterData +import android.safetycenter.SafetyCenterErrorDetails import android.safetycenter.SafetyCenterManager import android.safetycenter.SafetyCenterManager.OnSafetyCenterDataChangedListener import android.safetycenter.SafetyCenterManager.REFRESH_REASON_PAGE_OPEN @@ -56,6 +57,7 @@ import android.safetycenter.testing.getSafetySourceDataWithPermission import android.safetycenter.testing.isSafetyCenterEnabledWithPermission import android.safetycenter.testing.refreshSafetySourcesWithPermission import android.safetycenter.testing.removeOnSafetyCenterDataChangedListenerWithPermission +import android.safetycenter.testing.reportSafetySourceErrorWithPermission import android.safetycenter.testing.setSafetyCenterConfigOverrideWithPermission import android.safetycenter.testing.setSafetySourceDataWithPermission import androidx.test.core.app.ApplicationProvider.getApplicationContext @@ -135,13 +137,28 @@ class SafetyCenterManagerTest { .build() ) .build() - private val listenerChannel = Channel<SafetyCenterData>() + private val listener = object : OnSafetyCenterDataChangedListener { + private val dataChannel = Channel<SafetyCenterData>() + private val errorChannel = Channel<SafetyCenterErrorDetails>() - // The lambda has to be wrapped to the right type because kotlin wraps lambdas in a new Java - // functional interface implementation each time they are referenced/cast to a Java interface: - // b/215569072. - private val listener = OnSafetyCenterDataChangedListener { - runBlockingWithTimeout { listenerChannel.send(it) } + override fun onSafetyCenterDataChanged(data: SafetyCenterData) { + runBlockingWithTimeout { dataChannel.send(data) } + } + + override fun onError(errorDetails: SafetyCenterErrorDetails) { + runBlockingWithTimeout { errorChannel.send(errorDetails) } + } + + fun receiveSafetyCenterData(timeout: Duration = TIMEOUT_LONG) = + runBlockingWithTimeout(timeout) { dataChannel.receive() } + + fun receiveSafetyCenterErrorDetails(timeout: Duration = TIMEOUT_LONG) = + runBlockingWithTimeout(timeout) { errorChannel.receive() } + + fun cancelChannels() { + dataChannel.cancel() + errorChannel.cancel() + } } @Before @@ -160,8 +177,8 @@ class SafetyCenterManagerTest { } @After - fun cancelChannelAfterTest() { - listenerChannel.cancel() + fun cancelChannelsAfterTest() { + listener.cancelChannels() } @Test @@ -284,6 +301,23 @@ class SafetyCenterManagerTest { } @Test + fun reportSafetySourceError_callsErrorListener() { + safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission( + directExecutor(), + listener + ) + + safetyCenterManager.reportSafetySourceErrorWithPermission( + CTS_SOURCE_ID, + SafetySourceErrorDetails(EVENT_SOURCE_STATE_CHANGED) + ) + val safetyCenterErrorDetailsFromListener = listener.receiveSafetyCenterErrorDetails() + + assertThat(safetyCenterErrorDetailsFromListener).isEqualTo( + SafetyCenterErrorDetails("Error")) + } + + @Test fun reportSafetySourceError_withoutPermission_throwsSecurityException() { assertFailsWith(SecurityException::class) { safetyCenterManager.reportSafetySourceError( @@ -448,7 +482,7 @@ class SafetyCenterManagerTest { directExecutor(), listener ) - val safetyCenterDataFromListener = receiveListenerUpdate() + val safetyCenterDataFromListener = listener.receiveSafetyCenterData() // TODO(b/218830137): Assert on content. assertThat(safetyCenterDataFromListener).isNotNull() @@ -462,14 +496,14 @@ class SafetyCenterManagerTest { listener ) // Receive initial data. - receiveListenerUpdate() + listener.receiveSafetyCenterData() safetyCenterManager.setSafetySourceDataWithPermission( CTS_SOURCE_ID, safetySourceDataOk, EVENT_SOURCE_STATE_CHANGED ) - val safetyCenterDataFromListener = receiveListenerUpdate() + val safetyCenterDataFromListener = listener.receiveSafetyCenterData() // TODO(b/218830137): Assert on content. assertThat(safetyCenterDataFromListener).isNotNull() @@ -483,21 +517,21 @@ class SafetyCenterManagerTest { listener ) // Receive initial data. - receiveListenerUpdate() + listener.receiveSafetyCenterData() safetyCenterManager.setSafetySourceDataWithPermission( CTS_SOURCE_ID, safetySourceDataOk, EVENT_SOURCE_STATE_CHANGED ) // Receive update from #setSafetySourceData call. - receiveListenerUpdate() + listener.receiveSafetyCenterData() safetyCenterManager.setSafetySourceDataWithPermission( CTS_SOURCE_ID, safetySourceDataCritical, EVENT_SOURCE_STATE_CHANGED ) - val safetyCenterDataFromListener = receiveListenerUpdate() + val safetyCenterDataFromListener = listener.receiveSafetyCenterData() // TODO(b/218830137): Assert on content. assertThat(safetyCenterDataFromListener).isNotNull() @@ -511,21 +545,21 @@ class SafetyCenterManagerTest { listener ) // Receive initial data. - receiveListenerUpdate() + listener.receiveSafetyCenterData() safetyCenterManager.setSafetySourceDataWithPermission( CTS_SOURCE_ID, safetySourceDataOk, EVENT_SOURCE_STATE_CHANGED ) // Receive update from #setSafetySourceData call. - receiveListenerUpdate() + listener.receiveSafetyCenterData() safetyCenterManager.setSafetySourceDataWithPermission( CTS_SOURCE_ID, safetySourceData = null, EVENT_SOURCE_STATE_CHANGED ) - val safetyCenterDataFromListener = receiveListenerUpdate() + val safetyCenterDataFromListener = listener.receiveSafetyCenterData() // TODO(b/218830137): Assert on content. assertThat(safetyCenterDataFromListener).isNotNull() @@ -539,7 +573,7 @@ class SafetyCenterManagerTest { listener ) // Receive initial data. - receiveListenerUpdate() + listener.receiveSafetyCenterData() safetyCenterManager.setSafetySourceDataWithPermission( CTS_SOURCE_ID, @@ -548,7 +582,7 @@ class SafetyCenterManagerTest { ) assertFailsWith(TimeoutCancellationException::class) { - receiveListenerUpdate(TIMEOUT_SHORT) + listener.receiveSafetyCenterData(TIMEOUT_SHORT) } } @@ -560,14 +594,14 @@ class SafetyCenterManagerTest { listener ) // Receive initial data. - receiveListenerUpdate() + listener.receiveSafetyCenterData() safetyCenterManager.setSafetySourceDataWithPermission( CTS_SOURCE_ID, safetySourceDataOk, EVENT_SOURCE_STATE_CHANGED ) // Receive update from #setSafetySourceData call. - receiveListenerUpdate() + listener.receiveSafetyCenterData() safetyCenterManager.setSafetySourceDataWithPermission( CTS_SOURCE_ID, @@ -576,7 +610,7 @@ class SafetyCenterManagerTest { ) assertFailsWith(TimeoutCancellationException::class) { - receiveListenerUpdate(TIMEOUT_SHORT) + listener.receiveSafetyCenterData(TIMEOUT_SHORT) } } @@ -591,7 +625,7 @@ class SafetyCenterManagerTest { ) assertFailsWith(TimeoutCancellationException::class) { - receiveListenerUpdate(TIMEOUT_SHORT) + listener.receiveSafetyCenterData(TIMEOUT_SHORT) } } @@ -608,7 +642,7 @@ class SafetyCenterManagerTest { object : OnSafetyCenterDataChangedListener { override fun onSafetyCenterDataChanged(safetyCenterData: SafetyCenterData) { safetyCenterManager.removeOnSafetyCenterDataChangedListenerWithPermission(this) - runBlockingWithTimeout { listenerChannel.send(safetyCenterData) } + listener.onSafetyCenterDataChanged(safetyCenterData) } } safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission( @@ -619,7 +653,7 @@ class SafetyCenterManagerTest { // Check that we don't deadlock when using a one-shot listener: this is because adding the // listener could call the listener while holding a lock on the binder thread-pool; causing // a deadlock when attempting to call the `SafetyCenterManager` from that listener. - receiveListenerUpdate() + listener.receiveSafetyCenterData() } @Test @@ -630,7 +664,7 @@ class SafetyCenterManagerTest { listener ) // Receive initial data. - receiveListenerUpdate() + listener.receiveSafetyCenterData() safetyCenterManager.removeOnSafetyCenterDataChangedListenerWithPermission(listener) safetyCenterManager.setSafetySourceDataWithPermission( @@ -640,7 +674,7 @@ class SafetyCenterManagerTest { ) assertFailsWith(TimeoutCancellationException::class) { - receiveListenerUpdate(TIMEOUT_SHORT) + listener.receiveSafetyCenterData(TIMEOUT_SHORT) } } @@ -703,9 +737,6 @@ class SafetyCenterManagerTest { ) } - private fun receiveListenerUpdate(timeout: Duration = TIMEOUT_LONG): SafetyCenterData = - runBlockingWithTimeout(timeout) { listenerChannel.receive() } - private fun <T> runBlockingWithTimeout( timeout: Duration = TIMEOUT_LONG, block: suspend () -> T diff --git a/tests/cts/safetycenter/src/android/safetycenter/testing/SafetyCenterApisWithShellPermissions.kt b/tests/cts/safetycenter/src/android/safetycenter/testing/SafetyCenterApisWithShellPermissions.kt index 153390492..b874b8219 100644 --- a/tests/cts/safetycenter/src/android/safetycenter/testing/SafetyCenterApisWithShellPermissions.kt +++ b/tests/cts/safetycenter/src/android/safetycenter/testing/SafetyCenterApisWithShellPermissions.kt @@ -57,7 +57,7 @@ fun SafetyCenterManager.getSafetySourceDataWithPermission(id: String) = callWithShellPermissionIdentity({ getSafetySourceData(id) }, SEND_SAFETY_CENTER_UPDATE) /** - * Calls [SafetyCenterManager.reportSafetySourceError] adopting Shell's [MANAGE_SAFETY_CENTER] + * Calls [SafetyCenterManager.reportSafetySourceError] adopting Shell's [SEND_SAFETY_CENTER_UPDATE] * permission. */ fun SafetyCenterManager.reportSafetySourceErrorWithPermission( @@ -66,7 +66,7 @@ fun SafetyCenterManager.reportSafetySourceErrorWithPermission( ) = callWithShellPermissionIdentity( { reportSafetySourceError(safetySourceId, safetySourceErrorDetails) }, - MANAGE_SAFETY_CENTER + SEND_SAFETY_CENTER_UPDATE ) /** @@ -112,7 +112,7 @@ fun SafetyCenterManager.removeOnSafetyCenterDataChangedListenerWithPermission( * Calls [SafetyCenterManager.dismissSafetyCenterIssue] adopting Shell's [MANAGE_SAFETY_CENTER] * permission. */ -fun SafetyCenterManager.dismissSafetyIssueWithPermission(safetyCenterIssueId: String) = +fun SafetyCenterManager.dismissSafetyCenterIssueWithPermission(safetyCenterIssueId: String) = callWithShellPermissionIdentity({ dismissSafetyCenterIssue(safetyCenterIssueId) }, MANAGE_SAFETY_CENTER) @@ -120,7 +120,7 @@ fun SafetyCenterManager.dismissSafetyIssueWithPermission(safetyCenterIssueId: St * Calls [SafetyCenterManager.executeSafetyCenterIssueAction] adopting Shell's * [MANAGE_SAFETY_CENTER] permission. */ -fun SafetyCenterManager.executeSafetyCenterActionWithPermission( +fun SafetyCenterManager.executeSafetyCenterIssueActionWithPermission( safetyCenterIssueId: String, safetyCenterIssueActionId: String ) = |