[Settings] Enabling first stage of threading
Settings app would move PreferenceController to run in background thread in the near future. To support this, change some of the design within these essential components to allow: 1. Handler to run on non-main thread 2. Minimum multi-thread reentrance support Bug: 146045802 Test: make RunSettingsRoboTests -j ROBOTEST_FILTER=GlobalSettingsChangeListenerTest Test: make RunSettingsRoboTests -j ROBOTEST_FILTER=ActiveSubsciptionsListenerTest Change-Id: Ica5c942b919007d7d260feee632752d3353a6f18
This commit is contained in:
@@ -16,111 +16,157 @@
|
||||
|
||||
package com.android.settings.network;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Looper;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.internal.telephony.TelephonyIntents;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
import org.robolectric.shadows.ShadowBroadcastReceiver;
|
||||
import org.robolectric.shadows.ShadowContextImpl;
|
||||
import org.robolectric.shadows.ShadowSubscriptionManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ActiveSubsciptionsListenerTest {
|
||||
private static final int SUB_ID1 = 3;
|
||||
private static final int SUB_ID2 = 7;
|
||||
|
||||
@Mock
|
||||
private SubscriptionManager mSubscriptionManager;
|
||||
@Mock
|
||||
private SubscriptionInfo mSubscriptionInfo1;
|
||||
@Mock
|
||||
private SubscriptionInfo mSubscriptionInfo2;
|
||||
private static final Intent INTENT_RADIO_TECHNOLOGY_CHANGED =
|
||||
new Intent(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
|
||||
|
||||
private static final Intent INTENT_MULTI_SIM_CONFIG_CHANGED =
|
||||
new Intent(TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED);
|
||||
|
||||
private static final Intent INTENT_CARRIER_CONFIG_CHANGED =
|
||||
new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
|
||||
|
||||
private Context mContext;
|
||||
private ActiveSubsciptionsListener mListener;
|
||||
private ShadowContextImpl mShadowContextImpl;
|
||||
private SubscriptionManager mSubscriptionManager;
|
||||
private ShadowSubscriptionManager mShadowSubscriptionManager;
|
||||
private List<SubscriptionInfo> mActiveSubscriptions;
|
||||
private BroadcastReceiver mSubscriptionChangeReceiver;
|
||||
|
||||
private ActiveSubsciptionsListenerImpl mListener;
|
||||
private BroadcastReceiver mReceiver;
|
||||
private ShadowBroadcastReceiver mShadowReceiver;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
|
||||
|
||||
mContext = RuntimeEnvironment.application.getBaseContext();
|
||||
mShadowContextImpl = Shadow.extract(mContext);
|
||||
|
||||
mSubscriptionManager = spy(mContext.getSystemService(SubscriptionManager.class));
|
||||
mShadowSubscriptionManager = shadowOf(mSubscriptionManager);
|
||||
|
||||
mActiveSubscriptions = new ArrayList<SubscriptionInfo>();
|
||||
mActiveSubscriptions.add(ShadowSubscriptionManager.SubscriptionInfoBuilder
|
||||
.newBuilder().setId(SUB_ID1).buildSubscriptionInfo());
|
||||
mActiveSubscriptions.add(ShadowSubscriptionManager.SubscriptionInfoBuilder
|
||||
.newBuilder().setId(SUB_ID2).buildSubscriptionInfo());
|
||||
mShadowSubscriptionManager.setActiveSubscriptionInfoList(mActiveSubscriptions);
|
||||
|
||||
mListener = spy(new ActiveSubsciptionsListenerImpl(Looper.getMainLooper(), mContext));
|
||||
doReturn(mSubscriptionManager).when(mListener).getSubscriptionManager();
|
||||
mReceiver = mListener.getSubscriptionChangeReceiver();
|
||||
mShadowReceiver = shadowOf(mReceiver);
|
||||
doReturn(mReceiver).when(mListener).getSubscriptionChangeReceiver();
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUp() {
|
||||
mListener.stop();
|
||||
}
|
||||
|
||||
private class ActiveSubsciptionsListenerImpl extends ActiveSubsciptionsListener {
|
||||
private ActiveSubsciptionsListenerImpl(Looper looper, Context context) {
|
||||
super(looper, context);
|
||||
}
|
||||
public void onChanged() {}
|
||||
}
|
||||
|
||||
private void sendIntentToReceiver(Intent intent) {
|
||||
mShadowReceiver.onReceive(mContext, intent, new AtomicBoolean(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructor_noListeningWasSetup() {
|
||||
mListener = spy(new ActiveSubsciptionsListener(mContext) {
|
||||
public void onChanged() {}
|
||||
});
|
||||
verify(mSubscriptionManager, never()).addOnSubscriptionsChangedListener(any());
|
||||
verify(mContext, never()).registerReceiver(any(), any());
|
||||
verify(mListener, never()).onChanged();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void start_onChangedShouldAlwaysBeCalled() {
|
||||
mListener = spy(new ActiveSubsciptionsListener(mContext) {
|
||||
public void onChanged() {}
|
||||
});
|
||||
mSubscriptionChangeReceiver = spy(mListener.mSubscriptionChangeReceiver);
|
||||
when(mSubscriptionChangeReceiver.isInitialStickyBroadcast()).thenReturn(false);
|
||||
|
||||
mActiveSubscriptions.add(mSubscriptionInfo1);
|
||||
mActiveSubscriptions.add(mSubscriptionInfo2);
|
||||
when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(mActiveSubscriptions);
|
||||
|
||||
final Intent intentSubscription =
|
||||
new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
|
||||
final Intent intentRadioTech =
|
||||
new Intent(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
|
||||
|
||||
mSubscriptionChangeReceiver.onReceive(mContext, intentSubscription);
|
||||
mSubscriptionChangeReceiver.onReceive(mContext, intentRadioTech);
|
||||
public void start_configChangedIntent_onChangedShouldBeCalled() {
|
||||
sendIntentToReceiver(INTENT_RADIO_TECHNOLOGY_CHANGED);
|
||||
sendIntentToReceiver(INTENT_MULTI_SIM_CONFIG_CHANGED);
|
||||
verify(mListener, never()).onChanged();
|
||||
|
||||
mListener.start();
|
||||
|
||||
mSubscriptionChangeReceiver.onReceive(mContext, intentSubscription);
|
||||
verify(mListener, atLeastOnce()).onChanged();
|
||||
sendIntentToReceiver(INTENT_RADIO_TECHNOLOGY_CHANGED);
|
||||
verify(mListener, times(1)).onChanged();
|
||||
|
||||
mSubscriptionChangeReceiver.onReceive(mContext, intentRadioTech);
|
||||
sendIntentToReceiver(INTENT_MULTI_SIM_CONFIG_CHANGED);
|
||||
verify(mListener, times(2)).onChanged();
|
||||
|
||||
mListener.stop();
|
||||
|
||||
sendIntentToReceiver(INTENT_RADIO_TECHNOLOGY_CHANGED);
|
||||
sendIntentToReceiver(INTENT_MULTI_SIM_CONFIG_CHANGED);
|
||||
verify(mListener, times(2)).onChanged();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void start_carrierConfigChangedIntent_onChangedWhenSubIdBeenCached() {
|
||||
sendIntentToReceiver(INTENT_CARRIER_CONFIG_CHANGED);
|
||||
verify(mListener, never()).onChanged();
|
||||
|
||||
mListener.start();
|
||||
|
||||
mListener.getActiveSubscriptionsInfo();
|
||||
|
||||
sendIntentToReceiver(INTENT_CARRIER_CONFIG_CHANGED);
|
||||
verify(mListener, never()).onChanged();
|
||||
|
||||
INTENT_CARRIER_CONFIG_CHANGED.putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX,
|
||||
SUB_ID2);
|
||||
sendIntentToReceiver(INTENT_CARRIER_CONFIG_CHANGED);
|
||||
verify(mListener, times(1)).onChanged();
|
||||
|
||||
mListener.stop();
|
||||
|
||||
mContext.sendStickyBroadcast(intentSubscription);
|
||||
mContext.sendStickyBroadcast(intentRadioTech);
|
||||
sendIntentToReceiver(INTENT_CARRIER_CONFIG_CHANGED);
|
||||
verify(mListener, times(1)).onChanged();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void start_alwaysFetchAndCacheResult() {
|
||||
mListener = spy(new ActiveSubsciptionsListener(mContext) {
|
||||
public void onChanged() {}
|
||||
});
|
||||
mActiveSubscriptions.add(mSubscriptionInfo1);
|
||||
mActiveSubscriptions.add(mSubscriptionInfo2);
|
||||
|
||||
mListener.start();
|
||||
|
||||
List<SubscriptionInfo> subInfoList = null;
|
||||
@@ -130,8 +176,7 @@ public class ActiveSubsciptionsListenerTest {
|
||||
if (mActiveSubscriptions.size() > numberOfSubInfo) {
|
||||
mActiveSubscriptions.remove(numberOfSubInfo);
|
||||
}
|
||||
when(mSubscriptionManager.getActiveSubscriptionInfoList())
|
||||
.thenReturn(mActiveSubscriptions);
|
||||
mShadowSubscriptionManager.setActiveSubscriptionInfoList(mActiveSubscriptions);
|
||||
|
||||
// fetch twice and test if they generated access to SubscriptionManager only once
|
||||
subInfoList = mListener.getActiveSubscriptionsInfo();
|
||||
@@ -143,7 +188,7 @@ public class ActiveSubsciptionsListenerTest {
|
||||
mListener.clearCache();
|
||||
}
|
||||
|
||||
when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null);
|
||||
mShadowSubscriptionManager.setActiveSubscriptionInfoList(null);
|
||||
|
||||
// fetch twice and test if they generated access to SubscriptionManager only once
|
||||
subInfoList = mListener.getActiveSubscriptionsInfo();
|
||||
|
@@ -22,6 +22,7 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
@@ -49,7 +50,8 @@ public class GlobalSettingsChangeListenerTest {
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
mListener = spy(new GlobalSettingsChangeListener(mContext, SETTINGS_FIELD) {
|
||||
mListener = spy(new GlobalSettingsChangeListener(Looper.getMainLooper(),
|
||||
mContext, SETTINGS_FIELD) {
|
||||
public void onChanged(String field) {}
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user