aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJovana Knezevic <jovanak@google.com>2018-06-25 22:14:32 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2018-06-25 22:14:32 +0000
commit4aff01310e105f5a26a418e1a1cd8596ca262b69 (patch)
treef2245b8db881ca0c74b31bfea0463474dc0d2ed5
parentd50321314e309f0062850733a6e7b5f582af5f8c (diff)
parent32c0c703325c07bca115bfd17a5620989f03e6d0 (diff)
downloadCar-4aff01310e105f5a26a418e1a1cd8596ca262b69.tar.gz
Merge "Enables registering/unregistering multiple update listeners." into pi-dev
-rw-r--r--car-lib/src/android/car/user/CarUserManagerHelper.java49
-rw-r--r--tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java109
2 files changed, 142 insertions, 16 deletions
diff --git a/car-lib/src/android/car/user/CarUserManagerHelper.java b/car-lib/src/android/car/user/CarUserManagerHelper.java
index db28d21cba..c5885477ab 100644
--- a/car-lib/src/android/car/user/CarUserManagerHelper.java
+++ b/car-lib/src/android/car/user/CarUserManagerHelper.java
@@ -38,6 +38,7 @@ import com.android.internal.util.UserIcons;
import com.google.android.collect.Sets;
+import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
@@ -67,15 +68,23 @@ public class CarUserManagerHelper {
private final ActivityManager mActivityManager;
private int mLastActiveUser = UserHandle.USER_SYSTEM;
private Bitmap mDefaultGuestUserIcon;
- private OnUsersUpdateListener mUpdateListener;
+ private ArrayList<OnUsersUpdateListener> mUpdateListeners;
private final BroadcastReceiver mUserChangeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- mUpdateListener.onUsersUpdate();
+ ArrayList<OnUsersUpdateListener> copyOfUpdateListeners;
+ synchronized (mUpdateListeners) {
+ copyOfUpdateListeners = new ArrayList(mUpdateListeners);
+ }
+
+ for (OnUsersUpdateListener listener : copyOfUpdateListeners) {
+ listener.onUsersUpdate();
+ }
}
};
public CarUserManagerHelper(Context context) {
+ mUpdateListeners = new ArrayList<>();
mContext = context.getApplicationContext();
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
@@ -84,24 +93,42 @@ public class CarUserManagerHelper {
/**
* Registers a listener for updates to all users - removing, adding users or changing user info.
*
- * <p> Best practise is to keep one listener per helper.
- *
* @param listener Instance of {@link OnUsersUpdateListener}.
*/
public void registerOnUsersUpdateListener(OnUsersUpdateListener listener) {
- if (mUpdateListener != null) {
- unregisterOnUsersUpdateListener();
+ if (listener == null) {
+ return;
}
- mUpdateListener = listener;
- registerReceiver();
+ synchronized (mUpdateListeners) {
+ if (mUpdateListeners.isEmpty()) {
+ // First listener being added, register receiver.
+ registerReceiver();
+ }
+
+ if (!mUpdateListeners.contains(listener)) {
+ mUpdateListeners.add(listener);
+ }
+ }
}
/**
- * Unregisters on user update listener by unregistering {@code BroadcastReceiver}.
+ * Unregisters on user update listener.
+ * Unregisters {@code BroadcastReceiver} if no listeners remain.
+ *
+ * @param listener Instance of {@link OnUsersUpdateListener} to unregister.
*/
- public void unregisterOnUsersUpdateListener() {
- unregisterReceiver();
+ public void unregisterOnUsersUpdateListener(OnUsersUpdateListener listener) {
+ synchronized (mUpdateListeners) {
+ if (mUpdateListeners.contains(listener)) {
+ mUpdateListeners.remove(listener);
+
+ if (mUpdateListeners.isEmpty()) {
+ // No more listeners, unregister broadcast receiver.
+ unregisterReceiver();
+ }
+ }
+ }
}
/**
diff --git a/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java b/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java
index 240ba87cc0..8fc1eead69 100644
--- a/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java
@@ -19,8 +19,10 @@ package com.android.car;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.app.ActivityManager;
@@ -40,17 +42,18 @@ import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
/**
* This class contains unit tests for the {@link CarUserManagerHelper}.
* It tests that {@link CarUserManagerHelper} does the right thing for user management flows.
@@ -519,11 +522,107 @@ public class CarUserManagerHelperTest {
assertThat(handlerCaptor.getValue()).isNull();
// Unregister the receiver.
- mCarUserManagerHelper.unregisterOnUsersUpdateListener();
+ mCarUserManagerHelper.unregisterOnUsersUpdateListener(mTestListener);
verify(mContext).unregisterReceiver(receiverCaptor.getValue());
}
@Test
+ public void testMultipleRegistrationsOfSameListener() {
+ CarUserManagerHelper.OnUsersUpdateListener listener =
+ Mockito.mock(CarUserManagerHelper.OnUsersUpdateListener.class);
+
+ ArgumentCaptor<BroadcastReceiver> receiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+
+ mCarUserManagerHelper.registerOnUsersUpdateListener(listener);
+ mCarUserManagerHelper.registerOnUsersUpdateListener(listener);
+ // Even for multiple registrations of the same listener, broadcast receiver registered once.
+ verify(mContext, times(1))
+ .registerReceiverAsUser(receiverCaptor.capture(), any(), any(), any(), any());
+
+ // Verify that calling the receiver calls the listener.
+ receiverCaptor.getValue().onReceive(mContext, new Intent());
+ verify(listener).onUsersUpdate();
+
+ // Verify that a single removal unregisters the listener.
+ mCarUserManagerHelper.unregisterOnUsersUpdateListener(listener);
+ verify(mContext).unregisterReceiver(any());
+ }
+
+ @Test
+ public void testMultipleUnregistrationsOfTheSameListener() {
+ CarUserManagerHelper.OnUsersUpdateListener listener =
+ Mockito.mock(CarUserManagerHelper.OnUsersUpdateListener.class);
+ mCarUserManagerHelper.registerOnUsersUpdateListener(listener);
+
+ // Verify that a multiple unregistrations cause only one unregister for broadcast receiver.
+ mCarUserManagerHelper.unregisterOnUsersUpdateListener(listener);
+ mCarUserManagerHelper.unregisterOnUsersUpdateListener(listener);
+ mCarUserManagerHelper.unregisterOnUsersUpdateListener(listener);
+ verify(mContext, times(1)).unregisterReceiver(any());
+ }
+
+ @Test
+ public void testUnregisterReceiverCalledAfterAllListenersUnregister() {
+ CarUserManagerHelper.OnUsersUpdateListener listener1 =
+ Mockito.mock(CarUserManagerHelper.OnUsersUpdateListener.class);
+ CarUserManagerHelper.OnUsersUpdateListener listener2 =
+ Mockito.mock(CarUserManagerHelper.OnUsersUpdateListener.class);
+
+ mCarUserManagerHelper.registerOnUsersUpdateListener(listener1);
+ mCarUserManagerHelper.registerOnUsersUpdateListener(listener2);
+
+ mCarUserManagerHelper.unregisterOnUsersUpdateListener(listener1);
+ verify(mContext, never()).unregisterReceiver(any());
+
+ mCarUserManagerHelper.unregisterOnUsersUpdateListener(listener2);
+ verify(mContext, times(1)).unregisterReceiver(any());
+ }
+
+ @Test
+ public void testRegisteringMultipleListeners() {
+ CarUserManagerHelper.OnUsersUpdateListener listener1 =
+ Mockito.mock(CarUserManagerHelper.OnUsersUpdateListener.class);
+ CarUserManagerHelper.OnUsersUpdateListener listener2 =
+ Mockito.mock(CarUserManagerHelper.OnUsersUpdateListener.class);
+ ArgumentCaptor<BroadcastReceiver> receiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+
+ mCarUserManagerHelper.registerOnUsersUpdateListener(listener1);
+ mCarUserManagerHelper.registerOnUsersUpdateListener(listener2);
+ verify(mContext, times(1))
+ .registerReceiverAsUser(receiverCaptor.capture(), any(), any(), any(), any());
+
+ // Verify that calling the receiver calls both listeners.
+ receiverCaptor.getValue().onReceive(mContext, new Intent());
+ verify(listener1).onUsersUpdate();
+ verify(listener2).onUsersUpdate();
+ }
+
+ @Test
+ public void testUnregisteringListenerStopsUpdatesForListener() {
+ CarUserManagerHelper.OnUsersUpdateListener listener1 =
+ Mockito.mock(CarUserManagerHelper.OnUsersUpdateListener.class);
+ CarUserManagerHelper.OnUsersUpdateListener listener2 =
+ Mockito.mock(CarUserManagerHelper.OnUsersUpdateListener.class);
+ ArgumentCaptor<BroadcastReceiver> receiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+
+ mCarUserManagerHelper.registerOnUsersUpdateListener(listener1);
+ mCarUserManagerHelper.registerOnUsersUpdateListener(listener2);
+ verify(mContext, times(1))
+ .registerReceiverAsUser(receiverCaptor.capture(), any(), any(), any(), any());
+
+ // Unregister listener2
+ mCarUserManagerHelper.unregisterOnUsersUpdateListener(listener2);
+
+ // Verify that calling the receiver calls only one listener.
+ receiverCaptor.getValue().onReceive(mContext, new Intent());
+ verify(listener1).onUsersUpdate();
+ verify(listener2, never()).onUsersUpdate();
+ }
+
+ @Test
public void testGetInitialUserWithValidLastActiveUser() {
SystemProperties.set("android.car.systemuser.headless", "true");
int lastActiveUserId = 12;