Merge "Move recentsAnimationController to shell" into udc-dev
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 5a84b97..fb5d189 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2033,6 +2033,7 @@
public abstract class SharedConnectivityService extends android.app.Service {
method public void onBind();
+ method public final void setCountdownLatch(@Nullable java.util.concurrent.CountDownLatch);
}
}
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index c95d081..dfb9cf6 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -2550,41 +2550,15 @@
* <ul>
* <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED UNSPECIFIED}</li>
* <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SRGB SRGB}</li>
- * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_LINEAR_SRGB LINEAR_SRGB}</li>
- * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_EXTENDED_SRGB EXTENDED_SRGB}</li>
- * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_LINEAR_EXTENDED_SRGB LINEAR_EXTENDED_SRGB}</li>
- * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT709 BT709}</li>
- * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT2020 BT2020}</li>
- * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DCI_P3 DCI_P3}</li>
* <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DISPLAY_P3 DISPLAY_P3}</li>
- * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_NTSC_1953 NTSC_1953}</li>
- * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SMPTE_C SMPTE_C}</li>
- * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_ADOBE_RGB ADOBE_RGB}</li>
- * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_PRO_PHOTO_RGB PRO_PHOTO_RGB}</li>
- * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_ACES ACES}</li>
- * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_ACESCG ACESCG}</li>
- * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_CIE_XYZ CIE_XYZ}</li>
- * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_CIE_LAB CIE_LAB}</li>
+ * <li>{@link #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT2020_HLG BT2020_HLG}</li>
* </ul>
*
* <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
* @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED
* @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SRGB
- * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_LINEAR_SRGB
- * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_EXTENDED_SRGB
- * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_LINEAR_EXTENDED_SRGB
- * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT709
- * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT2020
- * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DCI_P3
* @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DISPLAY_P3
- * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_NTSC_1953
- * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SMPTE_C
- * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_ADOBE_RGB
- * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_PRO_PHOTO_RGB
- * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_ACES
- * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_ACESCG
- * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_CIE_XYZ
- * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_CIE_LAB
+ * @see #REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT2020_HLG
* @hide
*/
public static final Key<long[]> REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP =
diff --git a/core/tests/coretests/src/android/hardware/face/FaceManagerTest.java b/core/tests/coretests/src/android/hardware/face/FaceManagerTest.java
index 9b1f0cd..9a202ae 100644
--- a/core/tests/coretests/src/android/hardware/face/FaceManagerTest.java
+++ b/core/tests/coretests/src/android/hardware/face/FaceManagerTest.java
@@ -112,7 +112,7 @@
mCaptor.getValue().onAllAuthenticatorsRegistered(mProps);
List<FaceSensorPropertiesInternal> actual = mFaceManager.getSensorPropertiesInternal();
- assertThat(actual).isEqualTo(mProps);
+ assertThat(actual).containsExactlyElementsIn(mProps);
verify(mService, never()).getSensorPropertiesInternal(any());
}
diff --git a/core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java b/core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java
index f31903a..5058065 100644
--- a/core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java
+++ b/core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java
@@ -113,7 +113,7 @@
List<FingerprintSensorPropertiesInternal> actual =
mFingerprintManager.getSensorPropertiesInternal();
- assertThat(actual).isEqualTo(mProps);
+ assertThat(actual).containsExactlyElementsIn(mProps);
verify(mService, never()).getSensorPropertiesInternal(any());
}
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 9dc37c9..8b38deb 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -195,7 +195,6 @@
"lottie",
"LowLightDreamLib",
"motion_tool_lib",
- "renderscript_toolkit",
],
manifest: "AndroidManifest.xml",
@@ -329,7 +328,6 @@
"WindowManager-Shell",
"LowLightDreamLib",
"motion_tool_lib",
- "renderscript_toolkit",
"androidx.core_core-animation-testing-nodeps",
"androidx.compose.ui_ui",
],
@@ -370,6 +368,7 @@
plugins: ["dagger2-compiler"],
lint: {
test: true,
+ extra_check_modules: ["SystemUILintChecker"],
},
}
diff --git a/packages/SystemUI/res/layout/dream_overlay_home_controls_chip.xml b/packages/SystemUI/res/layout/dream_overlay_home_controls_chip.xml
index 5b2ec48..0cd0623 100644
--- a/packages/SystemUI/res/layout/dream_overlay_home_controls_chip.xml
+++ b/packages/SystemUI/res/layout/dream_overlay_home_controls_chip.xml
@@ -14,22 +14,15 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<FrameLayout
+<com.android.systemui.animation.view.LaunchableImageView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:paddingVertical="@dimen/dream_overlay_complication_home_controls_padding">
-
- <com.android.systemui.animation.view.LaunchableImageView
- android:id="@+id/home_controls_chip"
- android:layout_height="@dimen/dream_overlay_bottom_affordance_height"
- android:layout_width="@dimen/dream_overlay_bottom_affordance_width"
- android:layout_gravity="bottom|start"
- android:padding="@dimen/dream_overlay_bottom_affordance_padding"
- android:background="@drawable/dream_overlay_bottom_affordance_bg"
- android:scaleType="fitCenter"
- android:tint="?android:attr/textColorPrimary"
- android:src="@drawable/controls_icon"
- android:contentDescription="@string/quick_controls_title" />
-
-</FrameLayout>
+ android:id="@+id/home_controls_chip"
+ android:layout_height="@dimen/dream_overlay_bottom_affordance_height"
+ android:layout_width="@dimen/dream_overlay_bottom_affordance_width"
+ android:layout_gravity="bottom|start"
+ android:padding="@dimen/dream_overlay_bottom_affordance_padding"
+ android:background="@drawable/dream_overlay_bottom_affordance_bg"
+ android:scaleType="fitCenter"
+ android:tint="?android:attr/textColorPrimary"
+ android:src="@drawable/controls_icon"
+ android:contentDescription="@string/quick_controls_title" />
diff --git a/packages/SystemUI/res/layout/dream_overlay_media_entry_chip.xml b/packages/SystemUI/res/layout/dream_overlay_media_entry_chip.xml
index 50f3ffc..b75c638 100644
--- a/packages/SystemUI/res/layout/dream_overlay_media_entry_chip.xml
+++ b/packages/SystemUI/res/layout/dream_overlay_media_entry_chip.xml
@@ -17,13 +17,12 @@
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/media_entry_chip"
- android:layout_height="@dimen/keyguard_affordance_fixed_height"
- android:layout_width="@dimen/keyguard_affordance_fixed_width"
+ android:layout_height="@dimen/dream_overlay_bottom_affordance_height"
+ android:layout_width="@dimen/dream_overlay_bottom_affordance_width"
android:layout_gravity="bottom|start"
- android:scaleType="center"
+ android:scaleType="fitCenter"
+ android:padding="@dimen/dream_overlay_bottom_affordance_padding"
android:tint="?android:attr/textColorPrimary"
android:src="@drawable/ic_music_note"
- android:background="@drawable/keyguard_bottom_affordance_bg"
- android:layout_marginStart="@dimen/keyguard_affordance_horizontal_offset"
- android:layout_marginBottom="@dimen/keyguard_affordance_vertical_offset"
+ android:background="@drawable/dream_overlay_bottom_affordance_bg"
android:contentDescription="@string/controls_media_title" />
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index ab304aa..ee9e07a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1632,7 +1632,6 @@
<dimen name="dream_overlay_bottom_affordance_padding">14dp</dimen>
<dimen name="dream_overlay_complication_clock_time_text_size">86dp</dimen>
<dimen name="dream_overlay_complication_clock_time_translation_y">28dp</dimen>
- <dimen name="dream_overlay_complication_home_controls_padding">28dp</dimen>
<dimen name="dream_overlay_complication_clock_subtitle_text_size">24sp</dimen>
<dimen name="dream_overlay_complication_preview_text_size">36sp</dimen>
<dimen name="dream_overlay_complication_preview_icon_padding">28dp</dimen>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index b3a641c..0e2f8f0 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -4125,6 +4125,19 @@
KeyguardFingerprintListenModel.TABLE_HEADERS,
mFingerprintListenBuffer.toList()
).printTableData(pw);
+ } else if (mFpm != null && mFingerprintSensorProperties.isEmpty()) {
+ final int userId = mUserTracker.getUserId();
+ pw.println(" Fingerprint state (user=" + userId + ")");
+ pw.println(" mFingerprintSensorProperties.isEmpty="
+ + mFingerprintSensorProperties.isEmpty());
+ pw.println(" mFpm.isHardwareDetected="
+ + mFpm.isHardwareDetected());
+
+ new DumpsysTableLogger(
+ "KeyguardFingerprintListen",
+ KeyguardFingerprintListenModel.TABLE_HEADERS,
+ mFingerprintListenBuffer.toList()
+ ).printTableData(pw);
}
if (mFaceManager != null && !mFaceSensorProperties.isEmpty()) {
final int userId = mUserTracker.getUserId();
@@ -4155,6 +4168,19 @@
KeyguardFaceListenModel.TABLE_HEADERS,
mFaceListenBuffer.toList()
).printTableData(pw);
+ } else if (mFaceManager != null && mFaceSensorProperties.isEmpty()) {
+ final int userId = mUserTracker.getUserId();
+ pw.println(" Face state (user=" + userId + ")");
+ pw.println(" mFaceSensorProperties.isEmpty="
+ + mFaceSensorProperties.isEmpty());
+ pw.println(" mFaceManager.isHardwareDetected="
+ + mFaceManager.isHardwareDetected());
+
+ new DumpsysTableLogger(
+ "KeyguardFaceListen",
+ KeyguardFingerprintListenModel.TABLE_HEADERS,
+ mFingerprintListenBuffer.toList()
+ ).printTableData(pw);
}
new DumpsysTableLogger(
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java
index 7f395d8..82a8858 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java
@@ -33,7 +33,6 @@
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.CoreStartable;
-import com.android.systemui.R;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.controls.ControlsServiceInfo;
import com.android.systemui.controls.dagger.ControlsComponent;
@@ -157,14 +156,14 @@
* Contains values/logic associated with the dream complication view.
*/
public static class DreamHomeControlsChipViewHolder implements ViewHolder {
- private final View mView;
+ private final ImageView mView;
private final ComplicationLayoutParams mLayoutParams;
private final DreamHomeControlsChipViewController mViewController;
@Inject
DreamHomeControlsChipViewHolder(
DreamHomeControlsChipViewController dreamHomeControlsChipViewController,
- @Named(DREAM_HOME_CONTROLS_CHIP_VIEW) View view,
+ @Named(DREAM_HOME_CONTROLS_CHIP_VIEW) ImageView view,
@Named(DREAM_HOME_CONTROLS_CHIP_LAYOUT_PARAMS) ComplicationLayoutParams layoutParams
) {
mView = view;
@@ -174,7 +173,7 @@
}
@Override
- public View getView() {
+ public ImageView getView() {
return mView;
}
@@ -187,7 +186,7 @@
/**
* Controls behavior of the dream complication.
*/
- static class DreamHomeControlsChipViewController extends ViewController<View> {
+ static class DreamHomeControlsChipViewController extends ViewController<ImageView> {
private static final String TAG = "DreamHomeControlsCtrl";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -216,7 +215,7 @@
@Inject
DreamHomeControlsChipViewController(
- @Named(DREAM_HOME_CONTROLS_CHIP_VIEW) View view,
+ @Named(DREAM_HOME_CONTROLS_CHIP_VIEW) ImageView view,
ActivityStarter activityStarter,
Context context,
ControlsComponent controlsComponent,
@@ -231,10 +230,9 @@
@Override
protected void onViewAttached() {
- final ImageView chip = mView.findViewById(R.id.home_controls_chip);
- chip.setImageResource(mControlsComponent.getTileImageId());
- chip.setContentDescription(mContext.getString(mControlsComponent.getTileTitleId()));
- chip.setOnClickListener(this::onClickHomeControls);
+ mView.setImageResource(mControlsComponent.getTileImageId());
+ mView.setContentDescription(mContext.getString(mControlsComponent.getTileTitleId()));
+ mView.setOnClickListener(this::onClickHomeControls);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamHomeControlsComplicationComponent.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamHomeControlsComplicationComponent.java
index a7aa97f..cf05d2d 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamHomeControlsComplicationComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamHomeControlsComplicationComponent.java
@@ -19,7 +19,7 @@
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import android.view.LayoutInflater;
-import android.view.View;
+import android.widget.ImageView;
import com.android.systemui.R;
import com.android.systemui.dreams.complication.DreamHomeControlsComplication;
@@ -74,8 +74,8 @@
@Provides
@DreamHomeControlsComplicationScope
@Named(DREAM_HOME_CONTROLS_CHIP_VIEW)
- static View provideHomeControlsChipView(LayoutInflater layoutInflater) {
- return layoutInflater.inflate(R.layout.dream_overlay_home_controls_chip,
+ static ImageView provideHomeControlsChipView(LayoutInflater layoutInflater) {
+ return (ImageView) layoutInflater.inflate(R.layout.dream_overlay_home_controls_chip,
null, false);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java
index 616bd81..3be42cb 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java
@@ -101,8 +101,8 @@
@Named(DREAM_MEDIA_ENTRY_LAYOUT_PARAMS)
static ComplicationLayoutParams provideMediaEntryLayoutParams(@Main Resources res) {
return new ComplicationLayoutParams(
- res.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width),
- res.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height),
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT,
ComplicationLayoutParams.POSITION_BOTTOM
| ComplicationLayoutParams.POSITION_START,
ComplicationLayoutParams.DIRECTION_END,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
index 00e5aac..a3bf652 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
@@ -151,7 +151,7 @@
private static final float REC_MEDIA_COVER_SCALE_FACTOR = 1.25f;
private static final float MEDIA_SCRIM_START_ALPHA = 0.25f;
private static final float MEDIA_REC_SCRIM_START_ALPHA = 0.15f;
- private static final float MEDIA_PLAYER_SCRIM_END_ALPHA = 0.9f;
+ private static final float MEDIA_PLAYER_SCRIM_END_ALPHA = 1.0f;
private static final float MEDIA_REC_SCRIM_END_ALPHA = 1.0f;
private static final Intent SETTINGS_INTENT = new Intent(ACTION_MEDIA_CONTROLS_SETTINGS);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
index dd713ae..750272d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
@@ -21,17 +21,20 @@
import android.graphics.Canvas
import android.graphics.Point
import android.graphics.Rect
+import android.renderscript.Allocation
+import android.renderscript.Element
+import android.renderscript.RenderScript
+import android.renderscript.ScriptIntrinsicBlur
import android.util.Log
import android.util.MathUtils
import com.android.internal.graphics.ColorUtils
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.notification.MediaNotificationProcessor
-import com.google.android.renderscript.Toolkit
import javax.inject.Inject
private const val TAG = "MediaArtworkProcessor"
private const val COLOR_ALPHA = (255 * 0.7f).toInt()
-private const val BLUR_RADIUS = 25
+private const val BLUR_RADIUS = 25f
private const val DOWNSAMPLE = 6
@SysUISingleton
@@ -44,6 +47,10 @@
if (mArtworkCache != null) {
return mArtworkCache
}
+ val renderScript = RenderScript.create(context)
+ val blur = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript))
+ var input: Allocation? = null
+ var output: Allocation? = null
var inBitmap: Bitmap? = null
try {
@Suppress("DEPRECATION")
@@ -59,8 +66,18 @@
inBitmap = oldIn.copy(Bitmap.Config.ARGB_8888, false /* isMutable */)
oldIn.recycle()
}
+ val outBitmap = Bitmap.createBitmap(inBitmap.width, inBitmap.height,
+ Bitmap.Config.ARGB_8888)
- val outBitmap = Toolkit.blur(inBitmap, BLUR_RADIUS)
+ input = Allocation.createFromBitmap(renderScript, inBitmap,
+ Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_GRAPHICS_TEXTURE)
+ output = Allocation.createFromBitmap(renderScript, outBitmap)
+
+ blur.setRadius(BLUR_RADIUS)
+ blur.setInput(input)
+ blur.forEach(output)
+ output.copyTo(outBitmap)
+
val swatch = MediaNotificationProcessor.findBackgroundSwatch(artwork)
val canvas = Canvas(outBitmap)
@@ -70,6 +87,9 @@
Log.e(TAG, "error while processing artwork", ex)
return null
} finally {
+ input?.destroy()
+ output?.destroy()
+ blur.destroy()
inBitmap?.recycle()
}
}
@@ -78,4 +98,4 @@
mArtworkCache?.recycle()
mArtworkCache = null
}
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
index a062e7b..492f231 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
@@ -77,8 +77,11 @@
private final FalsingManager mFalsingManager;
private final UiEventLogger mUiEventLogger;
- @VisibleForTesting String mSelectedCardId;
- @VisibleForTesting boolean mIsDismissed;
+
+ @VisibleForTesting
+ String mSelectedCardId;
+ @VisibleForTesting
+ boolean mIsDismissed;
public WalletScreenController(
Context context,
@@ -124,9 +127,20 @@
}
Log.i(TAG, "Successfully retrieved wallet cards.");
List<WalletCard> walletCards = response.getWalletCards();
- List<WalletCardViewInfo> data = new ArrayList<>(walletCards.size());
+
+ boolean allUnknown = true;
for (WalletCard card : walletCards) {
- data.add(new QAWalletCardViewInfo(mContext, card));
+ if (card.getCardType() != WalletCard.CARD_TYPE_UNKNOWN) {
+ allUnknown = false;
+ break;
+ }
+ }
+
+ List<WalletCardViewInfo> paymentCardData = new ArrayList<>();
+ for (WalletCard card : walletCards) {
+ if (allUnknown || card.getCardType() == WalletCard.CARD_TYPE_PAYMENT) {
+ paymentCardData.add(new QAWalletCardViewInfo(mContext, card));
+ }
}
// Get on main thread for UI updates.
@@ -134,18 +148,18 @@
if (mIsDismissed) {
return;
}
- if (data.isEmpty()) {
+ if (paymentCardData.isEmpty()) {
showEmptyStateView();
} else {
int selectedIndex = response.getSelectedIndex();
- if (selectedIndex >= data.size()) {
+ if (selectedIndex >= paymentCardData.size()) {
Log.w(TAG, "Invalid selected card index, showing empty state.");
showEmptyStateView();
} else {
boolean isUdfpsEnabled = mKeyguardUpdateMonitor.isUdfpsEnrolled()
&& mKeyguardUpdateMonitor.isFingerprintDetectionRunning();
mWalletView.showCardCarousel(
- data,
+ paymentCardData,
selectedIndex,
!mKeyguardStateController.isUnlocked(),
isUdfpsEnabled);
@@ -213,7 +227,6 @@
}
-
@Override
public void onCardClicked(@NonNull WalletCardViewInfo cardInfo) {
if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamHomeControlsComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamHomeControlsComplicationTest.java
index 3312c43..aad49f9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamHomeControlsComplicationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamHomeControlsComplicationTest.java
@@ -35,7 +35,6 @@
import androidx.test.filters.SmallTest;
import com.android.internal.logging.UiEventLogger;
-import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.view.LaunchableImageView;
import com.android.systemui.condition.SelfExecutingMonitor;
@@ -89,9 +88,6 @@
private ArgumentCaptor<ControlsListingController.ControlsListingCallback> mCallbackCaptor;
@Mock
- private View mView;
-
- @Mock
private LaunchableImageView mHomeControlsView;
@Mock
@@ -115,7 +111,6 @@
when(mControlsComponent.getControlsListingController()).thenReturn(
Optional.of(mControlsListingController));
when(mControlsComponent.getVisibility()).thenReturn(AVAILABLE);
- when(mView.findViewById(R.id.home_controls_chip)).thenReturn(mHomeControlsView);
mMonitor = SelfExecutingMonitor.createInstance();
}
@@ -223,7 +218,7 @@
public void testClick_logsUiEvent() {
final DreamHomeControlsComplication.DreamHomeControlsChipViewController viewController =
new DreamHomeControlsComplication.DreamHomeControlsChipViewController(
- mView,
+ mHomeControlsView,
mActivityStarter,
mContext,
mControlsComponent,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
index b1950ea..692af6a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
@@ -22,6 +22,9 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -63,6 +66,7 @@
import org.mockito.MockitoAnnotations;
import java.util.Collections;
+import java.util.List;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -99,6 +103,8 @@
ArgumentCaptor<PendingIntent> mIntentCaptor;
@Captor
ArgumentCaptor<QuickAccessWalletClient.OnWalletCardsRetrievedCallback> mCallbackCaptor;
+ @Captor
+ ArgumentCaptor<List<WalletCardViewInfo>> mPaymentCardDataCaptor;
private WalletScreenController mController;
private TestableLooper mTestableLooper;
@@ -107,7 +113,7 @@
MockitoAnnotations.initMocks(this);
mTestableLooper = TestableLooper.get(this);
when(mUserTracker.getUserContext()).thenReturn(mContext);
- mWalletView = new WalletView(mContext);
+ mWalletView = spy(new WalletView(mContext));
mWalletView.getCardCarousel().setExpectedViewWidth(CARD_CAROUSEL_WIDTH);
when(mWalletClient.getLogo()).thenReturn(mWalletLogo);
when(mWalletClient.getShortcutLongLabel()).thenReturn(SHORTCUT_LONG_LABEL);
@@ -430,6 +436,41 @@
assertEquals(GONE, mWalletView.getVisibility());
}
+ @Test
+ public void onWalletCardsRetrieved_cardDataAllUnknown_showsAllCards() {
+ List<WalletCard> walletCardList = List.of(
+ createWalletCardWithType(mContext, WalletCard.CARD_TYPE_UNKNOWN),
+ createWalletCardWithType(mContext, WalletCard.CARD_TYPE_UNKNOWN),
+ createWalletCardWithType(mContext, WalletCard.CARD_TYPE_UNKNOWN));
+ GetWalletCardsResponse response = new GetWalletCardsResponse(walletCardList, 0);
+ mController.onWalletCardsRetrieved(response);
+ mTestableLooper.processAllMessages();
+
+ verify(mWalletView).showCardCarousel(mPaymentCardDataCaptor.capture(), anyInt(),
+ anyBoolean(),
+ anyBoolean());
+ List<WalletCardViewInfo> paymentCardData = mPaymentCardDataCaptor.getValue();
+ assertEquals(paymentCardData.size(), walletCardList.size());
+ }
+
+ @Test
+ public void onWalletCardsRetrieved_cardDataDifferentTypes_onlyShowsPayment() {
+ List<WalletCard> walletCardList = List.of(createWalletCardWithType(mContext,
+ WalletCard.CARD_TYPE_UNKNOWN),
+ createWalletCardWithType(mContext, WalletCard.CARD_TYPE_PAYMENT),
+ createWalletCardWithType(mContext, WalletCard.CARD_TYPE_NON_PAYMENT)
+ );
+ GetWalletCardsResponse response = new GetWalletCardsResponse(walletCardList, 0);
+ mController.onWalletCardsRetrieved(response);
+ mTestableLooper.processAllMessages();
+
+ verify(mWalletView).showCardCarousel(mPaymentCardDataCaptor.capture(), anyInt(),
+ anyBoolean(),
+ anyBoolean());
+ List<WalletCardViewInfo> paymentCardData = mPaymentCardDataCaptor.getValue();
+ assertEquals(paymentCardData.size(), 1);
+ }
+
private WalletCard createNonActiveWalletCard(Context context) {
PendingIntent pendingIntent =
PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
@@ -457,6 +498,15 @@
.build();
}
+ private WalletCard createWalletCardWithType(Context context, int cardType) {
+ PendingIntent pendingIntent =
+ PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
+ return new WalletCard.Builder(CARD_ID_1, cardType, createIcon(), "•••• 1234", pendingIntent)
+ .setCardIcon(createIcon())
+ .setCardLabel("Hold to reader")
+ .build();
+ }
+
private WalletCard createCrazyWalletCard(Context context, boolean hasLabel) {
PendingIntent pendingIntent =
PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index d09ca5c..7c84b72 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -843,7 +843,10 @@
final long sessionStart = mBatteryUsageStatsStore
.getLastBatteryUsageStatsBeforeResetAtomPullTimestamp();
- final long sessionEnd = mStats.getStartClockTime();
+ final long sessionEnd;
+ synchronized (mStats) {
+ sessionEnd = mStats.getStartClockTime();
+ }
final BatteryUsageStatsQuery queryBeforeReset =
new BatteryUsageStatsQuery.Builder()
.setMaxStatsAgeMs(0)
diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
index 7591057..1f65730 100644
--- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
@@ -385,9 +385,11 @@
public void setProcess(@Nullable ProcessRecord app) {
this.app = app;
if (app != null) {
+ setProcessCached(app.isCached());
setProcessInstrumented(app.getActiveInstrumentation() != null);
setProcessPersistent(app.isPersistent());
} else {
+ setProcessCached(false);
setProcessInstrumented(false);
setProcessPersistent(false);
}
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index bef16b6..bc33158 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -1328,7 +1328,9 @@
synchronized (mService) {
BroadcastProcessQueue leaf = mProcessQueues.get(uid);
while (leaf != null) {
- leaf.setProcessCached(cached);
+ // Update internal state by refreshing values previously
+ // read from any known running process
+ leaf.setProcess(leaf.app);
updateQueueDeferred(leaf);
updateRunnableList(leaf);
leaf = leaf.processNameNext;
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index fa3f684..50d00b4 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1039,7 +1039,13 @@
mInFullBackup = inFullBackup;
}
+ @GuardedBy("mService")
+ public void setCached(boolean cached) {
+ mState.setCached(cached);
+ }
+
@Override
+ @GuardedBy("mService")
public boolean isCached() {
return mState.isCached();
}
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java b/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java
index 82444f0..6bd4880 100644
--- a/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java
+++ b/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java
@@ -16,14 +16,22 @@
package com.android.server.biometrics.log;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.IBiometricContextListener;
+import android.hardware.biometrics.common.AuthenticateReason;
+import android.hardware.biometrics.common.OperationContext;
import android.hardware.biometrics.common.OperationReason;
+import android.hardware.biometrics.common.WakeReason;
import android.util.Slog;
import android.view.Surface;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
+import java.util.stream.Stream;
+
/**
* Wrapper for {@link FrameworkStatsLog} to isolate the testable parts.
*/
@@ -63,7 +71,7 @@
orientationType(operationContext.getOrientation()),
foldType(operationContext.getFoldState()),
operationContext.getOrderAndIncrement(),
- BiometricsProtoEnums.WAKE_REASON_UNKNOWN);
+ toProtoWakeReason(operationContext));
}
/** {@see FrameworkStatsLog.BIOMETRIC_AUTHENTICATED}. */
@@ -89,7 +97,8 @@
orientationType(operationContext.getOrientation()),
foldType(operationContext.getFoldState()),
operationContext.getOrderAndIncrement(),
- BiometricsProtoEnums.WAKE_REASON_UNKNOWN);
+ toProtoWakeReason(operationContext),
+ toProtoWakeReasonDetails(operationContext));
}
/** {@see FrameworkStatsLog.BIOMETRIC_AUTHENTICATED}. */
@@ -137,7 +146,81 @@
orientationType(operationContext.getOrientation()),
foldType(operationContext.getFoldState()),
operationContext.getOrderAndIncrement(),
- BiometricsProtoEnums.WAKE_REASON_UNKNOWN);
+ toProtoWakeReason(operationContext),
+ toProtoWakeReasonDetails(operationContext));
+ }
+
+ @VisibleForTesting
+ static int[] toProtoWakeReasonDetails(@NonNull OperationContextExt operationContext) {
+ final OperationContext ctx = operationContext.toAidlContext();
+ return Stream.of(toProtoWakeReasonDetails(ctx.authenticateReason))
+ .mapToInt(i -> i)
+ .filter(i -> i != BiometricsProtoEnums.DETAILS_UNKNOWN)
+ .toArray();
+ }
+
+ @VisibleForTesting
+ static int toProtoWakeReason(@NonNull OperationContextExt operationContext) {
+ @WakeReason final int reason = operationContext.getWakeReason();
+ switch (reason) {
+ case WakeReason.POWER_BUTTON:
+ return BiometricsProtoEnums.WAKE_REASON_POWER_BUTTON;
+ case WakeReason.GESTURE:
+ return BiometricsProtoEnums.WAKE_REASON_GESTURE;
+ case WakeReason.WAKE_KEY:
+ return BiometricsProtoEnums.WAKE_REASON_WAKE_KEY;
+ case WakeReason.WAKE_MOTION:
+ return BiometricsProtoEnums.WAKE_REASON_WAKE_MOTION;
+ case WakeReason.LID:
+ return BiometricsProtoEnums.WAKE_REASON_LID;
+ case WakeReason.DISPLAY_GROUP_ADDED:
+ return BiometricsProtoEnums.WAKE_REASON_DISPLAY_GROUP_ADDED;
+ case WakeReason.TAP:
+ return BiometricsProtoEnums.WAKE_REASON_TAP;
+ case WakeReason.LIFT:
+ return BiometricsProtoEnums.WAKE_REASON_LIFT;
+ case WakeReason.BIOMETRIC:
+ return BiometricsProtoEnums.WAKE_REASON_BIOMETRIC;
+ default:
+ return BiometricsProtoEnums.WAKE_REASON_UNKNOWN;
+ }
+ }
+
+ private static int toProtoWakeReasonDetails(@Nullable AuthenticateReason reason) {
+ if (reason != null) {
+ switch (reason.getTag()) {
+ case AuthenticateReason.faceAuthenticateReason:
+ return toProtoWakeReasonDetailsFromFace(reason.getFaceAuthenticateReason());
+ }
+ }
+ return BiometricsProtoEnums.DETAILS_UNKNOWN;
+ }
+
+ private static int toProtoWakeReasonDetailsFromFace(@AuthenticateReason.Face int reason) {
+ switch (reason) {
+ case AuthenticateReason.Face.STARTED_WAKING_UP:
+ return BiometricsProtoEnums.DETAILS_FACE_STARTED_WAKING_UP;
+ case AuthenticateReason.Face.PRIMARY_BOUNCER_SHOWN:
+ return BiometricsProtoEnums.DETAILS_FACE_PRIMARY_BOUNCER_SHOWN;
+ case AuthenticateReason.Face.ASSISTANT_VISIBLE:
+ return BiometricsProtoEnums.DETAILS_FACE_ASSISTANT_VISIBLE;
+ case AuthenticateReason.Face.ALTERNATE_BIOMETRIC_BOUNCER_SHOWN:
+ return BiometricsProtoEnums.DETAILS_FACE_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN;
+ case AuthenticateReason.Face.NOTIFICATION_PANEL_CLICKED:
+ return BiometricsProtoEnums.DETAILS_FACE_NOTIFICATION_PANEL_CLICKED;
+ case AuthenticateReason.Face.OCCLUDING_APP_REQUESTED:
+ return BiometricsProtoEnums.DETAILS_FACE_OCCLUDING_APP_REQUESTED;
+ case AuthenticateReason.Face.PICK_UP_GESTURE_TRIGGERED:
+ return BiometricsProtoEnums.DETAILS_FACE_PICK_UP_GESTURE_TRIGGERED;
+ case AuthenticateReason.Face.QS_EXPANDED:
+ return BiometricsProtoEnums.DETAILS_FACE_QS_EXPANDED;
+ case AuthenticateReason.Face.SWIPE_UP_ON_BOUNCER:
+ return BiometricsProtoEnums.DETAILS_FACE_SWIPE_UP_ON_BOUNCER;
+ case AuthenticateReason.Face.UDFPS_POINTER_DOWN:
+ return BiometricsProtoEnums.DETAILS_FACE_UDFPS_POINTER_DOWN;
+ default:
+ return BiometricsProtoEnums.DETAILS_UNKNOWN;
+ }
}
/** {@see FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED}. */
diff --git a/services/core/java/com/android/server/biometrics/log/OperationContextExt.java b/services/core/java/com/android/server/biometrics/log/OperationContextExt.java
index ecb7e7c..2934339 100644
--- a/services/core/java/com/android/server/biometrics/log/OperationContextExt.java
+++ b/services/core/java/com/android/server/biometrics/log/OperationContextExt.java
@@ -188,10 +188,17 @@
}
/** {@link OperationContext#reason}. */
+ @OperationReason
public byte getReason() {
return mAidlContext.reason;
}
+ /** {@link OperationContext#wakeReason}. */
+ @WakeReason
+ public int getWakeReason() {
+ return mAidlContext.wakeReason;
+ }
+
/** If the screen is currently on. */
public boolean isDisplayOn() {
return mIsDisplayOn;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 46337a9..bb79c99 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2340,7 +2340,6 @@
mAppOps,
new SysUiStatsEvent.BuilderFactory(),
mShowReviewPermissionsNotification);
- mPreferencesHelper.updateFixedImportance(mUm.getUsers());
mRankingHelper = new RankingHelper(getContext(),
mRankingHandler,
mPreferencesHelper,
@@ -2771,6 +2770,9 @@
maybeShowInitialReviewPermissionsNotification();
} else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
mSnoozeHelper.scheduleRepostsForPersistedNotifications(System.currentTimeMillis());
+ } else if (phase == SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY) {
+ mPreferencesHelper.updateFixedImportance(mUm.getUsers());
+ mPreferencesHelper.migrateNotificationPermissions(mUm.getUsers());
}
}
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 4bafbc7..aa97aa3 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -237,7 +237,6 @@
Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
NotificationManagerService.REVIEW_NOTIF_STATE_SHOULD_SHOW);
}
- ArrayList<PermissionHelper.PackagePermission> pkgPerms = new ArrayList<>();
synchronized (mPackagePreferences) {
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
tag = parser.getName();
@@ -255,27 +254,18 @@
String name = parser.getAttributeValue(null, ATT_NAME);
if (!TextUtils.isEmpty(name)) {
restorePackage(parser, forRestore, userId, name, upgradeForBubbles,
- migrateToPermission, pkgPerms);
+ migrateToPermission);
}
}
}
}
}
- if (migrateToPermission) {
- for (PackagePermission p : pkgPerms) {
- try {
- mPermissionHelper.setNotificationPermission(p);
- } catch (Exception e) {
- Slog.e(TAG, "could not migrate setting for " + p.packageName, e);
- }
- }
- }
}
@GuardedBy("mPackagePreferences")
private void restorePackage(TypedXmlPullParser parser, boolean forRestore,
@UserIdInt int userId, String name, boolean upgradeForBubbles,
- boolean migrateToPermission, ArrayList<PermissionHelper.PackagePermission> pkgPerms) {
+ boolean migrateToPermission) {
try {
int uid = parser.getAttributeInt(null, ATT_UID, UNKNOWN_UID);
if (forRestore) {
@@ -379,14 +369,6 @@
if (migrateToPermission) {
r.importance = appImportance;
r.migrateToPm = true;
- if (r.uid != UNKNOWN_UID) {
- // Don't call into permission system until we have a valid uid
- PackagePermission pkgPerm = new PackagePermission(
- r.pkg, UserHandle.getUserId(r.uid),
- r.importance != IMPORTANCE_NONE,
- hasUserConfiguredSettings(r));
- pkgPerms.add(pkgPerm);
- }
}
} catch (Exception e) {
Slog.w(TAG, "Failed to restore pkg", e);
@@ -2663,6 +2645,31 @@
}
}
+ public void migrateNotificationPermissions(List<UserInfo> users) {
+ for (UserInfo user : users) {
+ List<PackageInfo> packages = mPm.getInstalledPackagesAsUser(
+ PackageManager.PackageInfoFlags.of(PackageManager.MATCH_ALL),
+ user.getUserHandle().getIdentifier());
+ for (PackageInfo pi : packages) {
+ synchronized (mPackagePreferences) {
+ PackagePreferences p = getOrCreatePackagePreferencesLocked(
+ pi.packageName, pi.applicationInfo.uid);
+ if (p.migrateToPm && p.uid != UNKNOWN_UID) {
+ try {
+ PackagePermission pkgPerm = new PackagePermission(
+ p.pkg, UserHandle.getUserId(p.uid),
+ p.importance != IMPORTANCE_NONE,
+ hasUserConfiguredSettings(p));
+ mPermissionHelper.setNotificationPermission(pkgPerm);
+ } catch (Exception e) {
+ Slog.e(TAG, "could not migrate setting for " + p.pkg, e);
+ }
+ }
+ }
+ }
+ }
+ }
+
private void updateConfig() {
mRankingHandler.requestSort();
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
index cf8460b..2d4f5ca 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
@@ -53,6 +53,7 @@
import android.app.BackgroundStartPrivileges;
import android.app.BroadcastOptions;
import android.app.IApplicationThread;
+import android.app.UidObserver;
import android.app.usage.UsageEvents.Event;
import android.app.usage.UsageStatsManagerInternal;
import android.content.ComponentName;
@@ -83,6 +84,7 @@
import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.server.AlarmManagerInternal;
import com.android.server.DropBoxManagerInternal;
import com.android.server.LocalServices;
import com.android.server.am.ActivityManagerService.Injector;
@@ -153,11 +155,14 @@
private PackageManagerInternal mPackageManagerInt;
@Mock
private UsageStatsManagerInternal mUsageStatsManagerInt;
+ @Mock
+ private AlarmManagerInternal mAlarmManagerInt;
private ActivityManagerService mAms;
private BroadcastQueue mQueue;
BroadcastConstants mConstants;
private BroadcastSkipPolicy mSkipPolicy;
+ private UidObserver mUidObserver;
/**
* Desired behavior of the next
@@ -204,6 +209,8 @@
LocalServices.addService(DropBoxManagerInternal.class, mDropBoxManagerInt);
LocalServices.removeServiceForTest(PackageManagerInternal.class);
LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt);
+ LocalServices.removeServiceForTest(AlarmManagerInternal.class);
+ LocalServices.addService(AlarmManagerInternal.class, mAlarmManagerInt);
doReturn(new ComponentName("", "")).when(mPackageManagerInt).getSystemUiServiceComponent();
doNothing().when(mPackageManagerInt).setPackageStoppedState(any(), anyBoolean(), anyInt());
doAnswer((invocation) -> {
@@ -281,6 +288,11 @@
}).when(mAms).getProcessRecordLocked(any(), anyInt());
doNothing().when(mAms).appNotResponding(any(), any());
+ doAnswer((invocation) -> {
+ mUidObserver = invocation.getArgument(0);
+ return null;
+ }).when(mAms).registerUidObserver(any(), anyInt(), anyInt(), any());
+
mConstants = new BroadcastConstants(Settings.Global.BROADCAST_FG_CONSTANTS);
mConstants.TIMEOUT = 100;
mConstants.ALLOW_BG_ACTIVITY_START_TIMEOUT = 0;
@@ -305,6 +317,8 @@
} else {
throw new UnsupportedOperationException();
}
+
+ mQueue.start(mContext.getContentResolver());
}
@After
@@ -683,12 +697,22 @@
anyInt(), anyInt(), any());
}
- private void verifyScheduleRegisteredReceiver(ProcessRecord app,
+ private void verifyScheduleRegisteredReceiver(ProcessRecord app, Intent intent)
+ throws Exception {
+ verifyScheduleRegisteredReceiver(times(1), app, intent, UserHandle.USER_SYSTEM);
+ }
+
+ private void verifyScheduleRegisteredReceiver(VerificationMode mode, ProcessRecord app,
Intent intent) throws Exception {
- verify(app.getThread()).scheduleRegisteredReceiver(
+ verifyScheduleRegisteredReceiver(mode, app, intent, UserHandle.USER_SYSTEM);
+ }
+
+ private void verifyScheduleRegisteredReceiver(VerificationMode mode, ProcessRecord app,
+ Intent intent, int userId) throws Exception {
+ verify(app.getThread(), mode).scheduleRegisteredReceiver(
any(), argThat(filterEqualsIgnoringComponent(intent)),
anyInt(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean(),
- eq(UserHandle.USER_SYSTEM), anyInt(), anyInt(), any());
+ eq(userId), anyInt(), anyInt(), any());
}
private void verifyScheduleRegisteredReceiver(VerificationMode mode, ProcessRecord app,
@@ -1934,4 +1958,49 @@
getUidForPackage(PACKAGE_ORANGE));
assertNull(receiverOrangeApp);
}
+
+ /**
+ * Verify broadcasts to runtime receivers in cached processes are deferred
+ * until that process leaves the cached state.
+ */
+ @Test
+ public void testDeferralPolicy_UntilActive() throws Exception {
+ // Legacy stack doesn't support deferral
+ Assume.assumeTrue(mImpl == Impl.MODERN);
+
+ final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
+ final ProcessRecord receiverGreenApp = makeActiveProcessRecord(PACKAGE_GREEN);
+ final ProcessRecord receiverBlueApp = makeActiveProcessRecord(PACKAGE_BLUE);
+ final ProcessRecord receiverYellowApp = makeActiveProcessRecord(PACKAGE_YELLOW);
+
+ receiverGreenApp.setCached(true);
+ receiverBlueApp.setCached(true);
+ receiverYellowApp.setCached(false);
+
+ final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ final BroadcastOptions opts = BroadcastOptions.makeBasic()
+ .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE);
+ enqueueBroadcast(makeBroadcastRecord(airplane, callerApp, opts,
+ List.of(makeRegisteredReceiver(receiverGreenApp),
+ makeRegisteredReceiver(receiverBlueApp),
+ makeManifestReceiver(PACKAGE_BLUE, CLASS_BLUE),
+ makeRegisteredReceiver(receiverYellowApp))));
+ waitForIdle();
+
+ // Green ignored since it's in cached state
+ verifyScheduleRegisteredReceiver(never(), receiverGreenApp, airplane);
+
+ // Blue delivered both since it has a manifest receiver
+ verifyScheduleReceiver(times(1), receiverBlueApp, airplane);
+ verifyScheduleRegisteredReceiver(times(1), receiverBlueApp, airplane);
+
+ // Yellow delivered since it's not cached
+ verifyScheduleRegisteredReceiver(times(1), receiverYellowApp, airplane);
+
+ // Shift green to be active and confirm that deferred broadcast is delivered
+ receiverGreenApp.setCached(false);
+ mUidObserver.onUidCachedChanged(getUidForPackage(PACKAGE_GREEN), false);
+ waitForIdle();
+ verifyScheduleRegisteredReceiver(times(1), receiverGreenApp, airplane);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricFrameworkStatsLoggerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricFrameworkStatsLoggerTest.java
new file mode 100644
index 0000000..5adf391
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricFrameworkStatsLoggerTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.log;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.hardware.biometrics.BiometricsProtoEnums;
+import android.hardware.biometrics.common.AuthenticateReason;
+import android.hardware.biometrics.common.OperationContext;
+import android.hardware.biometrics.common.WakeReason;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+@Presubmit
+@SmallTest
+public class BiometricFrameworkStatsLoggerTest {
+
+ @Test
+ public void testConvertsWakeReason_whenEmpty() {
+ final OperationContextExt ctx = new OperationContextExt();
+
+ final int reason = BiometricFrameworkStatsLogger.toProtoWakeReason(ctx);
+ final int[] reasonDetails = BiometricFrameworkStatsLogger
+ .toProtoWakeReasonDetails(ctx);
+
+ assertThat(reason).isEqualTo(BiometricsProtoEnums.WAKE_REASON_UNKNOWN);
+ assertThat(reasonDetails).isEmpty();
+ }
+
+ @Test
+ public void testConvertsWakeReason_whenPowerReason() {
+ final OperationContext context = new OperationContext();
+ context.wakeReason = WakeReason.WAKE_MOTION;
+ final OperationContextExt ctx = new OperationContextExt(context);
+
+ final int reason = BiometricFrameworkStatsLogger.toProtoWakeReason(ctx);
+ final int[] reasonDetails = BiometricFrameworkStatsLogger
+ .toProtoWakeReasonDetails(new OperationContextExt(context));
+
+ assertThat(reason).isEqualTo(BiometricsProtoEnums.WAKE_REASON_WAKE_MOTION);
+ assertThat(reasonDetails).isEmpty();
+ }
+
+ @Test
+ public void testConvertsWakeReason_whenFaceReason() {
+ final OperationContext context = new OperationContext();
+ context.authenticateReason = AuthenticateReason.faceAuthenticateReason(
+ AuthenticateReason.Face.ASSISTANT_VISIBLE);
+ final OperationContextExt ctx = new OperationContextExt(context);
+
+ final int reason = BiometricFrameworkStatsLogger.toProtoWakeReason(ctx);
+ final int[] reasonDetails = BiometricFrameworkStatsLogger
+ .toProtoWakeReasonDetails(ctx);
+
+ assertThat(reason).isEqualTo(BiometricsProtoEnums.WAKE_REASON_UNKNOWN);
+ assertThat(reasonDetails).asList().containsExactly(
+ BiometricsProtoEnums.DETAILS_FACE_ASSISTANT_VISIBLE);
+ }
+
+ @Test
+ public void testConvertsWakeReason_whenVendorReason() {
+ final OperationContext context = new OperationContext();
+ context.authenticateReason = AuthenticateReason.vendorAuthenticateReason(
+ new AuthenticateReason.Vendor());
+ final OperationContextExt ctx = new OperationContextExt(context);
+
+ final int reason = BiometricFrameworkStatsLogger.toProtoWakeReason(ctx);
+ final int[] reasonDetails = BiometricFrameworkStatsLogger
+ .toProtoWakeReasonDetails(ctx);
+
+ assertThat(reason).isEqualTo(BiometricsProtoEnums.WAKE_REASON_UNKNOWN);
+ assertThat(reasonDetails).isEmpty();
+ }
+
+
+ @Test
+ public void testConvertsWakeReason_whenPowerAndFaceReason() {
+ final OperationContext context = new OperationContext();
+ context.wakeReason = WakeReason.WAKE_KEY;
+ context.authenticateReason = AuthenticateReason.faceAuthenticateReason(
+ AuthenticateReason.Face.PRIMARY_BOUNCER_SHOWN);
+ final OperationContextExt ctx = new OperationContextExt(context);
+
+ final int reason = BiometricFrameworkStatsLogger.toProtoWakeReason(ctx);
+ final int[] reasonDetails = BiometricFrameworkStatsLogger
+ .toProtoWakeReasonDetails(ctx);
+
+ assertThat(reason).isEqualTo(BiometricsProtoEnums.WAKE_REASON_WAKE_KEY);
+ assertThat(reasonDetails).asList().containsExactly(
+ BiometricsProtoEnums.DETAILS_FACE_PRIMARY_BOUNCER_SHOWN);
+ }
+
+ @Test
+ public void testConvertsWakeReason_whenPowerAndVendorReason() {
+ final OperationContext context = new OperationContext();
+ context.wakeReason = WakeReason.LID;
+ context.authenticateReason = AuthenticateReason.vendorAuthenticateReason(
+ new AuthenticateReason.Vendor());
+ final OperationContextExt ctx = new OperationContextExt(context);
+
+ final int reason = BiometricFrameworkStatsLogger.toProtoWakeReason(ctx);
+ final int[] reasonDetails = BiometricFrameworkStatsLogger
+ .toProtoWakeReasonDetails(ctx);
+
+ assertThat(reason).isEqualTo(BiometricsProtoEnums.WAKE_REASON_LID);
+ assertThat(reasonDetails).isEmpty();
+ }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 06bcb91..50e5bbf 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -679,10 +679,6 @@
compareChannels(ido, mHelper.getNotificationChannel(PKG_O, UID_O, ido.getId(), false));
compareChannels(idp, mHelper.getNotificationChannel(PKG_P, UID_P, idp.getId(), false));
- verify(mPermissionHelper).setNotificationPermission(nMr1Expected);
- verify(mPermissionHelper).setNotificationPermission(oExpected);
- verify(mPermissionHelper).setNotificationPermission(pExpected);
-
// verify that we also write a state for review_permissions_notification to eventually
// show a notification
assertEquals(NotificationManagerService.REVIEW_NOTIF_STATE_SHOULD_SHOW,
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java b/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
index 87ca99f..06a86cc 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
@@ -46,6 +46,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.CountDownLatch;
/**
@@ -77,6 +78,8 @@
new KnownNetworkConnectionStatus.Builder()
.setStatus(KnownNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN)
.setExtras(Bundle.EMPTY).build();
+ // Used for testing
+ private CountDownLatch mCountDownLatch;
@Override
@Nullable
@@ -265,12 +268,24 @@
public void onBind() {
}
+ /** @hide */
+ @TestApi
+ public final void setCountdownLatch(@Nullable CountDownLatch latch) {
+ mCountDownLatch = latch;
+ }
+
private void onRegisterCallback(ISharedConnectivityCallback callback) {
mRemoteCallbackList.register(callback);
+ if (mCountDownLatch != null) {
+ mCountDownLatch.countDown();
+ }
}
private void onUnregisterCallback(ISharedConnectivityCallback callback) {
mRemoteCallbackList.unregister(callback);
+ if (mCountDownLatch != null) {
+ mCountDownLatch.countDown();
+ }
}
/**
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
index 514ba3c..4a293cb 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
@@ -26,7 +26,10 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -39,6 +42,7 @@
import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo;
import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
import android.os.Bundle;
+import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
@@ -51,12 +55,16 @@
import org.mockito.MockitoAnnotations;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* Unit tests for {@link SharedConnectivityService}.
*/
@SmallTest
public class SharedConnectivityServiceTest {
+ private static final int LATCH_TIMEOUT = 2;
+
private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
.setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
@@ -75,7 +83,7 @@
.addSecurityType(SECURITY_TYPE_EAP).setNetworkProviderInfo(
NETWORK_PROVIDER_INFO).build();
private static final List<KnownNetwork> KNOWN_NETWORKS = List.of(KNOWN_NETWORK);
- private static final HotspotNetworkConnectionStatus TETHER_NETWORK_CONNECTION_STATUS =
+ private static final HotspotNetworkConnectionStatus HOTSPOT_NETWORK_CONNECTION_STATUS =
new HotspotNetworkConnectionStatus.Builder().setStatus(CONNECTION_STATUS_UNKNOWN)
.setHotspotNetwork(HOTSPOT_NETWORK).setExtras(Bundle.EMPTY).build();
private static final KnownNetworkConnectionStatus KNOWN_NETWORK_CONNECTION_STATUS =
@@ -88,25 +96,77 @@
@Mock
Resources mResources;
+ @Mock
+ ISharedConnectivityCallback mCallback;
+
+ @Mock
+ IBinder mBinder;
+
static class FakeSharedConnectivityService extends SharedConnectivityService {
public void attachBaseContext(Context context) {
super.attachBaseContext(context);
}
+ private HotspotNetwork mConnectedHotspotNetwork;
+ private HotspotNetwork mDisconnectedHotspotNetwork;
+ private KnownNetwork mConnectedKnownNetwork;
+ private KnownNetwork mForgottenKnownNetwork;
+ private CountDownLatch mLatch;
+
+ public HotspotNetwork getConnectedHotspotNetwork() {
+ return mConnectedHotspotNetwork;
+ }
+
+ public HotspotNetwork getDisconnectedHotspotNetwork() {
+ return mDisconnectedHotspotNetwork;
+ }
+
+ public KnownNetwork getConnectedKnownNetwork() {
+ return mConnectedKnownNetwork;
+ }
+
+ public KnownNetwork getForgottenKnownNetwork() {
+ return mForgottenKnownNetwork;
+ }
+
+ public void initializeLatch() {
+ mLatch = new CountDownLatch(1);
+ }
+
+ public CountDownLatch getLatch() {
+ return mLatch;
+ }
+
@Override
public void onConnectHotspotNetwork(@NonNull HotspotNetwork network) {
+ mConnectedHotspotNetwork = network;
+ if (mLatch != null) {
+ mLatch.countDown();
+ }
}
@Override
public void onDisconnectHotspotNetwork(@NonNull HotspotNetwork network) {
+ mDisconnectedHotspotNetwork = network;
+ if (mLatch != null) {
+ mLatch.countDown();
+ }
}
@Override
public void onConnectKnownNetwork(@NonNull KnownNetwork network) {
+ mConnectedKnownNetwork = network;
+ if (mLatch != null) {
+ mLatch.countDown();
+ }
}
@Override
public void onForgetKnownNetwork(@NonNull KnownNetwork network) {
+ mForgottenKnownNetwork = network;
+ if (mLatch != null) {
+ mLatch.countDown();
+ }
}
}
@@ -165,10 +225,10 @@
ISharedConnectivityService.Stub binder =
(ISharedConnectivityService.Stub) service.onBind(new Intent());
- service.updateHotspotNetworkConnectionStatus(TETHER_NETWORK_CONNECTION_STATUS);
+ service.updateHotspotNetworkConnectionStatus(HOTSPOT_NETWORK_CONNECTION_STATUS);
assertThat(binder.getHotspotNetworkConnectionStatus())
- .isEqualTo(TETHER_NETWORK_CONNECTION_STATUS);
+ .isEqualTo(HOTSPOT_NETWORK_CONNECTION_STATUS);
}
@Test
@@ -225,7 +285,115 @@
assertThat(SharedConnectivityService.areKnownNetworksEnabledForService(mContext)).isFalse();
}
- private SharedConnectivityService createService() {
+ @Test
+ public void connectHotspotNetwork() throws RemoteException, InterruptedException {
+ FakeSharedConnectivityService service = createService();
+ ISharedConnectivityService.Stub binder =
+ (ISharedConnectivityService.Stub) service.onBind(new Intent());
+ service.initializeLatch();
+
+ binder.connectHotspotNetwork(HOTSPOT_NETWORK);
+
+ assertThat(service.getLatch().await(LATCH_TIMEOUT, TimeUnit.SECONDS)).isTrue();
+ assertThat(service.getConnectedHotspotNetwork()).isEqualTo(HOTSPOT_NETWORK);
+ }
+
+ @Test
+ public void disconnectHotspotNetwork() throws RemoteException, InterruptedException {
+ FakeSharedConnectivityService service = createService();
+ ISharedConnectivityService.Stub binder =
+ (ISharedConnectivityService.Stub) service.onBind(new Intent());
+ service.initializeLatch();
+
+ binder.disconnectHotspotNetwork(HOTSPOT_NETWORK);
+
+ assertThat(service.getLatch().await(LATCH_TIMEOUT, TimeUnit.SECONDS)).isTrue();
+ assertThat(service.getDisconnectedHotspotNetwork()).isEqualTo(HOTSPOT_NETWORK);
+ }
+
+ @Test
+ public void connectKnownNetwork() throws RemoteException , InterruptedException {
+ FakeSharedConnectivityService service = createService();
+ ISharedConnectivityService.Stub binder =
+ (ISharedConnectivityService.Stub) service.onBind(new Intent());
+ service.initializeLatch();
+
+ binder.connectKnownNetwork(KNOWN_NETWORK);
+
+ assertThat(service.getLatch().await(LATCH_TIMEOUT, TimeUnit.SECONDS)).isTrue();
+ assertThat(service.getConnectedKnownNetwork()).isEqualTo(KNOWN_NETWORK);
+ }
+
+ @Test
+ public void forgetKnownNetwork() throws RemoteException, InterruptedException {
+ FakeSharedConnectivityService service = createService();
+ ISharedConnectivityService.Stub binder =
+ (ISharedConnectivityService.Stub) service.onBind(new Intent());
+ service.initializeLatch();
+
+ binder.forgetKnownNetwork(KNOWN_NETWORK);
+
+ assertThat(service.getLatch().await(LATCH_TIMEOUT, TimeUnit.SECONDS)).isTrue();
+ assertThat(service.getForgottenKnownNetwork()).isEqualTo(KNOWN_NETWORK);
+ }
+
+ @Test
+ public void registerCallback() throws RemoteException, InterruptedException {
+ SharedConnectivityService service = createService();
+ ISharedConnectivityService.Stub binder =
+ (ISharedConnectivityService.Stub) service.onBind(new Intent());
+ when(mCallback.asBinder()).thenReturn(mBinder);
+ when(mContext.getPackageName()).thenReturn("android.net.wifi.nonupdatable.test");
+ SharedConnectivitySettingsState state = buildSettingsState();
+
+ CountDownLatch latch = new CountDownLatch(1);
+ service.setCountdownLatch(latch);
+ binder.registerCallback(mCallback);
+ assertThat(latch.await(LATCH_TIMEOUT, TimeUnit.SECONDS)).isTrue();
+ service.setHotspotNetworks(HOTSPOT_NETWORKS);
+ service.setKnownNetworks(KNOWN_NETWORKS);
+ service.setSettingsState(state);
+ service.updateHotspotNetworkConnectionStatus(HOTSPOT_NETWORK_CONNECTION_STATUS);
+ service.updateKnownNetworkConnectionStatus(KNOWN_NETWORK_CONNECTION_STATUS);
+
+ verify(mCallback).onHotspotNetworksUpdated(HOTSPOT_NETWORKS);
+ verify(mCallback).onKnownNetworksUpdated(KNOWN_NETWORKS);
+ verify(mCallback).onSharedConnectivitySettingsChanged(state);
+ verify(mCallback).onHotspotNetworkConnectionStatusChanged(
+ HOTSPOT_NETWORK_CONNECTION_STATUS);
+ verify(mCallback).onKnownNetworkConnectionStatusChanged(KNOWN_NETWORK_CONNECTION_STATUS);
+ }
+
+ @Test
+ public void unregisterCallback() throws RemoteException, InterruptedException {
+ SharedConnectivityService service = createService();
+ ISharedConnectivityService.Stub binder =
+ (ISharedConnectivityService.Stub) service.onBind(new Intent());
+ when(mCallback.asBinder()).thenReturn(mBinder);
+ when(mContext.getPackageName()).thenReturn("android.net.wifi.nonupdatable.test");
+
+ CountDownLatch latch = new CountDownLatch(1);
+ service.setCountdownLatch(latch);
+ binder.registerCallback(mCallback);
+ assertThat(latch.await(LATCH_TIMEOUT, TimeUnit.SECONDS)).isTrue();
+ latch = new CountDownLatch(1);
+ service.setCountdownLatch(latch);
+ binder.unregisterCallback(mCallback);
+ assertThat(latch.await(LATCH_TIMEOUT, TimeUnit.SECONDS)).isTrue();
+ service.setHotspotNetworks(HOTSPOT_NETWORKS);
+ service.setKnownNetworks(KNOWN_NETWORKS);
+ service.setSettingsState(buildSettingsState());
+ service.updateHotspotNetworkConnectionStatus(HOTSPOT_NETWORK_CONNECTION_STATUS);
+ service.updateKnownNetworkConnectionStatus(KNOWN_NETWORK_CONNECTION_STATUS);
+
+ verify(mCallback, never()).onHotspotNetworksUpdated(any());
+ verify(mCallback, never()).onKnownNetworksUpdated(any());
+ verify(mCallback, never()).onSharedConnectivitySettingsChanged(any());
+ verify(mCallback, never()).onHotspotNetworkConnectionStatusChanged(any());
+ verify(mCallback, never()).onKnownNetworkConnectionStatusChanged(any());
+ }
+
+ private FakeSharedConnectivityService createService() {
FakeSharedConnectivityService service = new FakeSharedConnectivityService();
service.attachBaseContext(mContext);
return service;