Merge "Handle 5G meteredness in telephony framework" into qt-qpr1-dev-plus-aosp
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0c5faff..1e4d010 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -39,6 +39,7 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />
+ <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
@@ -71,7 +72,7 @@
<uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" />
<uses-permission android:name="android.permission.CONFIGURE_DISPLAY_COLOR_MODE" />
<uses-permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" />
- <uses-permission android:name="android.permission.SET_TIME" />
+ <uses-permission android:name="android.permission.SUGGEST_MANUAL_TIME_AND_ZONE" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATIONS" />
<uses-permission android:name="android.permission.REBOOT" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index ef75d03..b9a1939 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -465,6 +465,7 @@
<item>1xRTT</item>
<item>IS95B</item>
<item>IS95A</item>
+ <item>NR</item>
</string-array>
<string-array translatable="false" name="bearer_values">
@@ -500,6 +501,8 @@
<item>5</item>
<!-- Do not translate. -->
<item>4</item>
+ <!-- Do not translate. -->
+ <item>20</item>
</string-array>
<!-- MVNO Info used in APN editor -->
diff --git a/res/values/config.xml b/res/values/config.xml
index 5eb55ae..e4b4812 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -417,4 +417,7 @@
<!-- "Show work policy info" intent action. TODO(b/134391103): Replace with final SystemAPI intent when it's available. -->
<string name="config_work_policy_info_intent_action" translatable="false"/>
+
+ <!-- RTT setting intent action -->
+ <string name="config_rtt_setting_intent_action" translatable="false"></string>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 31a1592..5ee7171 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -218,8 +218,8 @@
<dimen name="fingerprint_finish_max_size">288dp</dimen>
<!-- Face -->
- <dimen name="face_preview_translate_y">0dp</dimen>
- <dimen name="face_preview_translate_x">0dp</dimen>
+ <item name="face_preview_translate_y" format="float" type="dimen">0</item>
+ <item name="face_preview_translate_x" format="float" type="dimen">0</item>
<item name="face_preview_scale" format="float" type="dimen">1.0</item>
<!-- Confirm device credentials -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 70e998b..123482a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -11280,5 +11280,13 @@
<string name="work_policy_privacy_settings">Your work policy info</string>
<!-- Summary for Enterprise Privacy settings, explaining what the user can expect to find under it [CHAR LIMIT=NONE]-->
<string name="work_policy_privacy_settings_summary">Settings managed by your IT admin</string>
+ <!-- Title for RTT setting. [CHAR LIMIT=NONE] -->
+ <string name="rtt_settings_title"></string>
+ <!-- Subtext for showing the option of RTT setting. [CHAR LIMIT=NONE] -->
+ <string name="rtt_settings_no_visible"></string>
+ <!-- Subtext for showing the option of RTT setting. [CHAR LIMIT=NONE] -->
+ <string name="rtt_settings_visible_during_call"></string>
+ <!-- Subtext for showing the option of RTT setting. [CHAR LIMIT=NONE] -->
+ <string name="rtt_settings_always_visible"></string>
</resources>
diff --git a/res/xml/privacy_dashboard_settings.xml b/res/xml/privacy_dashboard_settings.xml
index 3ac6f42..1dd609e 100644
--- a/res/xml/privacy_dashboard_settings.xml
+++ b/res/xml/privacy_dashboard_settings.xml
@@ -22,13 +22,6 @@
android:title="@string/privacy_dashboard_title"
settings:initialExpandedChildrenCount="4">
- <!-- This preference isn't searchable, and user won't see title in this preference.
- So, we just set empty text for title. -->
- <com.android.settingslib.widget.BarChartPreference
- android:key="permission_bar_chart"
- android:title="@string/summary_placeholder"
- settings:controller="com.android.settings.privacy.PermissionBarChartPreferenceController"/>
-
<!-- Work Policy info -->
<Preference
android:key="work_policy_info"
diff --git a/res/xml/security_settings_face.xml b/res/xml/security_settings_face.xml
index 7d59f30..e613470 100644
--- a/res/xml/security_settings_face.xml
+++ b/res/xml/security_settings_face.xml
@@ -64,7 +64,11 @@
android:summary="@string/security_settings_face_settings_require_confirmation_details"
app:keywords="@string/keywords_face_unlock"
app:controller="com.android.settings.biometrics.face.FaceSettingsConfirmPreferenceController"/>
+ </PreferenceCategory>
+ <PreferenceCategory
+ android:key="security_settings_face_button_category"
+ android:title="@string/security_settings_face_preference_title">
<com.android.settingslib.widget.LayoutPreference
android:key="security_settings_face_delete_faces_container"
android:selectable="false"
@@ -73,7 +77,7 @@
<com.android.settingslib.widget.LayoutPreference
android:key="security_settings_face_enroll_faces_container"
android:selectable="false"
- android:layout="@layout/face_enroll_button " />
+ android:layout="@layout/face_enroll_button" />
</PreferenceCategory>
<PreferenceCategory
diff --git a/src/com/android/settings/AirplaneModeEnabler.java b/src/com/android/settings/AirplaneModeEnabler.java
index dde7ce0..a843a04 100644
--- a/src/com/android/settings/AirplaneModeEnabler.java
+++ b/src/com/android/settings/AirplaneModeEnabler.java
@@ -19,28 +19,34 @@
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
+import android.telephony.PhoneStateListener;
+import android.telephony.SubscriptionInfo;
+import android.telephony.TelephonyManager;
+import android.util.Log;
-import com.android.internal.telephony.PhoneStateIntentReceiver;
-import com.android.internal.telephony.TelephonyProperties;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settings.network.GlobalSettingsChangeListener;
+import com.android.settings.network.ProxySubscriptionManager;
+import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.WirelessUtils;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-public class AirplaneModeEnabler {
+import java.util.List;
- private static final int EVENT_SERVICE_STATE_CHANGED = 3;
+/**
+ * Monitor and update configuration of airplane mode settings
+ */
+public class AirplaneModeEnabler extends GlobalSettingsChangeListener {
+
+ private static final String LOG_TAG = "AirplaneModeEnabler";
+ private static final boolean DEBUG = false;
private final Context mContext;
private final MetricsFeatureProvider mMetricsFeatureProvider;
- private PhoneStateIntentReceiver mPhoneStateReceiver;
-
private OnAirplaneModeChangedListener mOnAirplaneModeChangedListener;
public interface OnAirplaneModeChangedListener {
@@ -52,46 +58,50 @@
void onAirplaneModeChanged(boolean isAirplaneModeOn);
}
- private Handler mHandler = new Handler(Looper.getMainLooper()) {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case EVENT_SERVICE_STATE_CHANGED:
- onAirplaneModeChanged();
- break;
- }
- }
- };
+ private TelephonyManager mTelephonyManager;
+ @VisibleForTesting
+ PhoneStateListener mPhoneStateListener;
- private ContentObserver mAirplaneModeObserver = new ContentObserver(
- new Handler(Looper.getMainLooper())) {
- @Override
- public void onChange(boolean selfChange) {
- onAirplaneModeChanged();
- }
- };
+ private GlobalSettingsChangeListener mAirplaneModeObserver;
- public AirplaneModeEnabler(Context context, MetricsFeatureProvider metricsFeatureProvider,
- OnAirplaneModeChangedListener listener) {
+ public AirplaneModeEnabler(Context context, OnAirplaneModeChangedListener listener) {
+ super(context, Settings.Global.AIRPLANE_MODE_ON);
mContext = context;
- mMetricsFeatureProvider = metricsFeatureProvider;
+ mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
mOnAirplaneModeChangedListener = listener;
- mPhoneStateReceiver = new PhoneStateIntentReceiver(mContext, mHandler);
- mPhoneStateReceiver.notifyServiceState(EVENT_SERVICE_STATE_CHANGED);
+ mTelephonyManager = context.getSystemService(TelephonyManager.class);
+
+ mPhoneStateListener = new PhoneStateListener() {
+ @Override
+ public void onRadioPowerStateChanged(int state) {
+ if (DEBUG) {
+ Log.d(LOG_TAG, "RadioPower: " + state);
+ }
+ onAirplaneModeChanged();
+ }
+ };
+ }
+
+ /**
+ * Implementation of GlobalSettingsChangeListener.onChanged
+ */
+ public void onChanged(String field) {
+ if (DEBUG) {
+ Log.d(LOG_TAG, "Airplane mode configuration update");
+ }
+ onAirplaneModeChanged();
}
public void resume() {
- mPhoneStateReceiver.registerIntent();
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
- mAirplaneModeObserver);
+ mTelephonyManager.listen(mPhoneStateListener,
+ PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED);
}
public void pause() {
- mPhoneStateReceiver.unregisterIntent();
- mContext.getContentResolver().unregisterContentObserver(mAirplaneModeObserver);
+ mTelephonyManager.listen(mPhoneStateListener,
+ PhoneStateListener.LISTEN_NONE);
}
private void setAirplaneModeOn(boolean enabling) {
@@ -105,7 +115,7 @@
}
// Post the intent
- Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ final Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intent.putExtra("state", enabling);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
}
@@ -124,10 +134,36 @@
}
}
+ /**
+ * Check the status of ECM mode
+ *
+ * @return any subscription within device is under ECM mode
+ */
+ public boolean isInEcmMode() {
+ if (mTelephonyManager.getEmergencyCallbackMode()) {
+ return true;
+ }
+ final List<SubscriptionInfo> subInfoList =
+ ProxySubscriptionManager.getInstance(mContext).getActiveSubscriptionsInfo();
+ if (subInfoList == null) {
+ return false;
+ }
+ for (SubscriptionInfo subInfo : subInfoList) {
+ final TelephonyManager telephonyManager =
+ mTelephonyManager.createForSubscriptionId(subInfo.getSubscriptionId());
+ if (telephonyManager != null) {
+ if (telephonyManager.getEmergencyCallbackMode()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
public void setAirplaneMode(boolean isAirplaneModeOn) {
- if (Boolean.parseBoolean(
- SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {
+ if (isInEcmMode()) {
// In ECM mode, do not update database at this point
+ Log.d(LOG_TAG, "ECM airplane mode=" + isAirplaneModeOn);
} else {
mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_AIRPLANE_TOGGLE,
isAirplaneModeOn);
@@ -136,6 +172,7 @@
}
public void setAirplaneModeInECM(boolean isECMExit, boolean isAirplaneModeOn) {
+ Log.d(LOG_TAG, "Exist ECM=" + isECMExit + ", with airplane mode=" + isAirplaneModeOn);
if (isECMExit) {
// update database based on the current checkbox state
setAirplaneModeOn(isAirplaneModeOn);
diff --git a/src/com/android/settings/IccLockSettings.java b/src/com/android/settings/IccLockSettings.java
index 605f483..8880001 100644
--- a/src/com/android/settings/IccLockSettings.java
+++ b/src/com/android/settings/IccLockSettings.java
@@ -29,8 +29,6 @@
import android.os.Handler;
import android.os.Message;
import android.telephony.SubscriptionInfo;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
@@ -55,6 +53,9 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.TelephonyIntents;
+import com.android.settings.network.ProxySubscriptionManager;
+
+import java.util.List;
/**
* Implements the preference screen to enable/disable ICC lock and
@@ -112,6 +113,7 @@
private ListView mListView;
private Phone mPhone;
+ private ProxySubscriptionManager mProxySubscriptionMgr;
private EditPinPreference mPinDialog;
private SwitchPreference mPinToggle;
@@ -129,7 +131,7 @@
// For replies from IccCard interface
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
- AsyncResult ar = (AsyncResult) msg.obj;
+ final AsyncResult ar = (AsyncResult) msg.obj;
switch (msg.what) {
case MSG_ENABLE_ICC_PIN_COMPLETE:
iccLockChanged(ar.exception == null, msg.arg1, ar.exception);
@@ -161,8 +163,8 @@
}
static String getSummary(Context context) {
- Resources res = context.getResources();
- String summary = isIccLockEnabled()
+ final Resources res = context.getResources();
+ final String summary = isIccLockEnabled()
? res.getString(R.string.sim_lock_on)
: res.getString(R.string.sim_lock_off);
return summary;
@@ -177,6 +179,11 @@
return;
}
+ // enable ProxySubscriptionMgr with Lifecycle support for all controllers
+ // live within this fragment
+ mProxySubscriptionMgr = ProxySubscriptionManager.getInstance(getContext());
+ mProxySubscriptionMgr.setLifecycle(getLifecycle());
+
addPreferencesFromResource(R.xml.sim_lock_settings);
mPinDialog = (EditPinPreference) findPreference(PIN_DIALOG);
@@ -217,14 +224,12 @@
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- final TelephonyManager tm =
- (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
- final int numSims = tm.getSimCount();
+ final int numSims = mProxySubscriptionMgr.getActiveSubscriptionInfoCountMax();
if (numSims > 1) {
- View view = inflater.inflate(R.layout.icc_lock_tabs, container, false);
+ final View view = inflater.inflate(R.layout.icc_lock_tabs, container, false);
final ViewGroup prefs_container = (ViewGroup) view.findViewById(R.id.prefs_container);
Utils.prepareCustomPreferencesList(container, view, prefs_container, false);
- View prefs = super.onCreateView(inflater, prefs_container, savedInstanceState);
+ final View prefs = super.onCreateView(inflater, prefs_container, savedInstanceState);
prefs_container.addView(prefs);
mTabHost = (TabHost) view.findViewById(android.R.id.tabhost);
@@ -235,18 +240,19 @@
mTabHost.setOnTabChangedListener(mTabListener);
mTabHost.clearAllTabs();
- SubscriptionManager sm = SubscriptionManager.from(getContext());
+ final List<SubscriptionInfo> subInfoList =
+ mProxySubscriptionMgr.getActiveSubscriptionsInfo();
for (int i = 0; i < numSims; ++i) {
- final SubscriptionInfo subInfo = sm.getActiveSubscriptionInfoForSimSlotIndex(i);
+ final SubscriptionInfo subInfo =
+ getActiveSubscriptionInfoForSimSlotIndex(subInfoList, i);
mTabHost.addTab(buildTabSpec(String.valueOf(i),
String.valueOf(subInfo == null
? getContext().getString(R.string.sim_editor_title, i + 1)
: subInfo.getDisplayName())));
}
- final SubscriptionInfo sir = sm.getActiveSubscriptionInfoForSimSlotIndex(0);
+ final SubscriptionInfo sir = getActiveSubscriptionInfoForSimSlotIndex(subInfoList, 0);
- mPhone = (sir == null) ? null
- : PhoneFactory.getPhone(SubscriptionManager.getPhoneId(sir.getSubscriptionId()));
+ mPhone = (sir == null) ? null : PhoneFactory.getPhone(sir.getSimSlotIndex());
if (savedInstanceState != null && savedInstanceState.containsKey(CURRENT_TAB)) {
mTabHost.setCurrentTabByTag(savedInstanceState.getString(CURRENT_TAB));
@@ -456,7 +462,7 @@
private void tryChangeIccLockState() {
// Try to change icc lock. If it succeeds, toggle the lock state and
// reset dialog state. Else inject error message and show dialog again.
- Message callback = Message.obtain(mHandler, MSG_ENABLE_ICC_PIN_COMPLETE);
+ final Message callback = Message.obtain(mHandler, MSG_ENABLE_ICC_PIN_COMPLETE);
mPhone.getIccCard().setIccLockEnabled(mToState, mPin, callback);
// Disable the setting till the response is received.
mPinToggle.setEnabled(false);
@@ -467,7 +473,8 @@
mPinToggle.setChecked(mToState);
} else {
if (exception instanceof CommandException) {
- CommandException.Error err = ((CommandException)(exception)).getCommandError();
+ final CommandException.Error err =
+ ((CommandException) exception).getCommandError();
if (err == CommandException.Error.PASSWORD_INCORRECT) {
createCustomTextToast(getPinPasswordErrorMessage(attemptsRemaining));
} else {
@@ -490,9 +497,9 @@
// The window type of Toast is set by NotificationManagerService.
// It can't be overwritten by LayoutParams.type.
// Ovarlay a custom window with LayoutParams (TYPE_STATUS_BAR_PANEL) on PUK unlock screen.
- View v = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE))
+ final View v = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE))
.inflate(com.android.internal.R.layout.transient_notification, null);
- TextView tv = (TextView) v.findViewById(com.android.internal.R.id.message);
+ final TextView tv = (TextView) v.findViewById(com.android.internal.R.id.message);
tv.setText(errorMessage);
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
@@ -521,7 +528,7 @@
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
- WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
+ final WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
wm.addView(v, params);
mHandler.postDelayed(new Runnable() {
@@ -545,7 +552,7 @@
}
private void tryChangePin() {
- Message callback = Message.obtain(mHandler, MSG_CHANGE_ICC_PIN_COMPLETE);
+ final Message callback = Message.obtain(mHandler, MSG_CHANGE_ICC_PIN_COMPLETE);
mPhone.getIccCard().changeIccLockPassword(mOldPin,
mNewPin, callback);
}
@@ -583,15 +590,27 @@
mDialogState = OFF_MODE;
}
+ private static SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(
+ List<SubscriptionInfo> subInfoList, int slotId) {
+ if (subInfoList == null) {
+ return null;
+ }
+ for (SubscriptionInfo subInfo : subInfoList) {
+ if (subInfo.getSimSlotIndex() == slotId) {
+ return subInfo;
+ }
+ }
+ return null;
+ }
+
private OnTabChangeListener mTabListener = new OnTabChangeListener() {
@Override
public void onTabChanged(String tabId) {
final int slotId = Integer.parseInt(tabId);
- final SubscriptionInfo sir = SubscriptionManager.from(getActivity().getBaseContext())
- .getActiveSubscriptionInfoForSimSlotIndex(slotId);
+ final SubscriptionInfo sir = getActiveSubscriptionInfoForSimSlotIndex(
+ mProxySubscriptionMgr.getActiveSubscriptionsInfo(), slotId);
- mPhone = (sir == null) ? null
- : PhoneFactory.getPhone(SubscriptionManager.getPhoneId(sir.getSubscriptionId()));
+ mPhone = (sir == null) ? null : PhoneFactory.getPhone(sir.getSimSlotIndex());
// The User has changed tab; update the body.
updatePreferences();
diff --git a/src/com/android/settings/ResetNetworkConfirm.java b/src/com/android/settings/ResetNetworkConfirm.java
index beb0528..c4e4baf 100644
--- a/src/com/android/settings/ResetNetworkConfirm.java
+++ b/src/com/android/settings/ResetNetworkConfirm.java
@@ -47,7 +47,6 @@
import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog;
-import com.android.ims.ImsManager;
import com.android.internal.telephony.PhoneConstants;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
@@ -104,15 +103,16 @@
p2pFactoryReset(mContext);
TelephonyManager telephonyManager = (TelephonyManager)
- mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ mContext.getSystemService(TelephonyManager.class)
+ .createForSubscriptionId(mSubId);
if (telephonyManager != null) {
- telephonyManager.factoryReset(mSubId);
+ telephonyManager.resetSettings();
}
NetworkPolicyManager policyManager = (NetworkPolicyManager)
mContext.getSystemService(Context.NETWORK_POLICY_SERVICE);
if (policyManager != null) {
- String subscriberId = telephonyManager.getSubscriberId(mSubId);
+ String subscriberId = telephonyManager.getSubscriberId();
policyManager.factoryReset(subscriberId);
}
@@ -125,8 +125,6 @@
}
}
- ImsManager.getInstance(mContext,
- SubscriptionManager.getPhoneId(mSubId)).factoryReset();
restoreDefaultApn(mContext);
if (mEraseEsim) {
return RecoverySystem.wipeEuiccData(mContext, mPackageName);
diff --git a/src/com/android/settings/SettingsDumpService.java b/src/com/android/settings/SettingsDumpService.java
index a57e983..487ccf5 100644
--- a/src/com/android/settings/SettingsDumpService.java
+++ b/src/com/android/settings/SettingsDumpService.java
@@ -103,12 +103,14 @@
DataUsageController controller = new DataUsageController(this);
ConnectivityManager connectivityManager = getSystemService(ConnectivityManager.class);
SubscriptionManager manager = SubscriptionManager.from(this);
- TelephonyManager telephonyManager = TelephonyManager.from(this);
+ TelephonyManager telephonyManager = this.getSystemService(TelephonyManager.class);
if (connectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)) {
JSONArray array = new JSONArray();
for (SubscriptionInfo info : manager.getAllSubscriptionInfoList()) {
+ telephonyManager = telephonyManager
+ .createForSubscriptionId(info.getSubscriptionId());
NetworkTemplate mobileAll = NetworkTemplate.buildTemplateMobileAll(
- telephonyManager.getSubscriberId(info.getSubscriptionId()));
+ telephonyManager.getSubscriberId());
final JSONObject usage = dumpDataUsage(mobileAll, controller);
usage.put("subId", info.getSubscriptionId());
array.put(usage);
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java b/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java
index 8806712..853ca7c 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java
@@ -18,6 +18,7 @@
import android.app.settings.SettingsEnums;
import android.content.Context;
+import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
@@ -316,14 +317,19 @@
scaleX = scaleX / smaller;
scaleY = scaleY / smaller;
- // Apply the transformation/scale
- mTextureView.setTranslationX(getResources().getDimension(R.dimen.face_preview_translate_x));
- mTextureView.setTranslationY(getResources().getDimension(R.dimen.face_preview_translate_y));
-
+ final TypedValue tx = new TypedValue();
+ final TypedValue ty = new TypedValue();
final TypedValue scale = new TypedValue();
+ getResources().getValue(R.dimen.face_preview_translate_x, tx, true /* resolveRefs */);
+ getResources().getValue(R.dimen.face_preview_translate_y, ty, true /* resolveRefs */);
getResources().getValue(R.dimen.face_preview_scale, scale, true /* resolveRefs */);
- mTextureView.setScaleX(scaleX * scale.getFloat());
- mTextureView.setScaleY(scaleY * scale.getFloat());
+
+ // Apply the transformation/scale
+ final Matrix transform = new Matrix();
+ mTextureView.getTransform(transform);
+ transform.setScale(scaleX * scale.getFloat(), scaleY * scale.getFloat());
+ transform.postTranslate(tx.getFloat(), ty.getFloat());
+ mTextureView.setTransform(transform);
}
private void closeCamera() {
diff --git a/src/com/android/settings/datausage/DataUsageBaseFragment.java b/src/com/android/settings/datausage/DataUsageBaseFragment.java
index f6e88cc..299ce43 100644
--- a/src/com/android/settings/datausage/DataUsageBaseFragment.java
+++ b/src/com/android/settings/datausage/DataUsageBaseFragment.java
@@ -51,7 +51,7 @@
services.mPolicyEditor = new NetworkPolicyEditor(services.mPolicyManager);
- services.mTelephonyManager = TelephonyManager.from(context);
+ services.mTelephonyManager = context.getSystemService(TelephonyManager.class);
services.mSubscriptionManager = SubscriptionManager.from(context);
services.mUserManager = UserManager.get(context);
}
diff --git a/src/com/android/settings/datausage/DataUsageUtils.java b/src/com/android/settings/datausage/DataUsageUtils.java
index 0e400a2..ef3e7b6 100644
--- a/src/com/android/settings/datausage/DataUsageUtils.java
+++ b/src/com/android/settings/datausage/DataUsageUtils.java
@@ -33,7 +33,6 @@
import android.text.format.Formatter.BytesResult;
import android.util.Log;
-import java.util.ArrayList;
import java.util.List;
/**
@@ -72,7 +71,7 @@
return false;
}
- final TelephonyManager telephonyManager = TelephonyManager.from(context);
+ final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
final NetworkStatsManager networkStatsManager =
context.getSystemService(NetworkStatsManager.class);
boolean hasEthernetUsage = false;
@@ -115,7 +114,7 @@
}
return false;
}
- final TelephonyManager tele = TelephonyManager.from(context);
+ final TelephonyManager tele = context.getSystemService(TelephonyManager.class);
// require both supported network and ready SIM
boolean isReady = true;
for (SubscriptionInfo subInfo : subInfoList) {
diff --git a/src/com/android/settings/development/compat/PlatformCompatDashboard.java b/src/com/android/settings/development/compat/PlatformCompatDashboard.java
index dab45f2..53c6e9f 100644
--- a/src/com/android/settings/development/compat/PlatformCompatDashboard.java
+++ b/src/com/android/settings/development/compat/PlatformCompatDashboard.java
@@ -16,7 +16,9 @@
package com.android.settings.development.compat;
+import static com.android.settings.development.AppPicker.EXTRA_DEBUGGABLE;
import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes.REQUEST_COMPAT_CHANGE_APP;
+import static com.android.internal.compat.OverrideAllowedState.ALLOWED;
import android.app.Activity;
import android.app.settings.SettingsEnums;
@@ -25,7 +27,9 @@
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -37,9 +41,12 @@
import androidx.preference.PreferenceCategory;
import androidx.preference.SwitchPreference;
+import com.android.internal.compat.AndroidBuildClassifier;
import com.android.internal.compat.CompatibilityChangeConfig;
import com.android.internal.compat.CompatibilityChangeInfo;
import com.android.internal.compat.IPlatformCompat;
+import com.android.internal.compat.IOverrideValidator;
+import com.android.internal.compat.OverrideAllowedState;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.development.AppPicker;
@@ -61,6 +68,8 @@
private CompatibilityChangeInfo[] mChanges;
+ private AndroidBuildClassifier mAndroidBuildClassifier = new AndroidBuildClassifier();
+
@VisibleForTesting
String mSelectedApp;
@@ -114,17 +123,21 @@
if (requestCode == REQUEST_COMPAT_CHANGE_APP) {
if (resultCode == Activity.RESULT_OK) {
mSelectedApp = data.getAction();
- addPreferences();
+ try {
+ final ApplicationInfo applicationInfo = getApplicationInfo();
+ addPreferences(applicationInfo);
+ } catch (PackageManager.NameNotFoundException e) {
+ startAppPicker();
+ }
}
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
- private void addPreferences() {
+ private void addPreferences(ApplicationInfo applicationInfo) {
getPreferenceScreen().removeAll();
- getPreferenceScreen().addPreference(
- createAppPreference(getApplicationInfo().loadIcon(getPackageManager())));
+ getPreferenceScreen().addPreference(createAppPreference(applicationInfo));
// Differentiate compatibility changes into default enabled, default disabled and enabled
// after target sdk.
final CompatibilityChangeConfig configMappings = getAppChangeMappings();
@@ -161,7 +174,7 @@
try {
final ApplicationInfo applicationInfo = getApplicationInfo();
return getPlatformCompat().getAppConfig(applicationInfo);
- } catch (RemoteException e) {
+ } catch (RemoteException | PackageManager.NameNotFoundException e) {
throw new RuntimeException("Could not get app config!", e);
}
}
@@ -180,7 +193,15 @@
change.getName() != null ? change.getName() : "Change_" + change.getId();
item.setSummary(changeName);
item.setKey(changeName);
- item.setEnabled(true);
+ boolean shouldEnable = true;
+ try {
+ shouldEnable = getPlatformCompat().getOverrideValidator()
+ .getOverrideAllowedState(change.getId(), mSelectedApp)
+ .state == ALLOWED;
+ } catch (RemoteException e) {
+ throw new RuntimeException("Could not check if change can be overridden for app.", e);
+ }
+ item.setEnabled(shouldEnable);
item.setChecked(currentValue);
item.setOnPreferenceChangeListener(
new CompatChangePreferenceChangeListener(change.getId()));
@@ -192,12 +213,8 @@
*
* @return an {@link ApplicationInfo} instance.
*/
- ApplicationInfo getApplicationInfo() {
- try {
- return getPackageManager().getApplicationInfo(mSelectedApp, 0);
- } catch (PackageManager.NameNotFoundException e) {
- throw new RuntimeException("Could not get ApplicationInfo for selected app!", e);
- }
+ ApplicationInfo getApplicationInfo() throws PackageManager.NameNotFoundException {
+ return getPackageManager().getApplicationInfo(mSelectedApp, 0);
}
/**
@@ -206,9 +223,10 @@
* <p>The {@link Preference} contains the icon, package name and target SDK for the selected
* app. Selecting this preference will also re-trigger the app selection dialog.</p>
*/
- Preference createAppPreference(Drawable icon) {
- final ApplicationInfo applicationInfo = getApplicationInfo();
- final Preference appPreference = new Preference(getPreferenceScreen().getContext());
+ Preference createAppPreference(ApplicationInfo applicationInfo) {
+ final Context context = getPreferenceScreen().getContext();
+ final Drawable icon = applicationInfo.loadIcon(context.getPackageManager());
+ final Preference appPreference = new Preference(context);
appPreference.setIcon(icon);
appPreference.setSummary(mSelectedApp
+ " SDK "
@@ -243,6 +261,11 @@
private void startAppPicker() {
final Intent intent = new Intent(getContext(), AppPicker.class);
+ // If build is neither userdebug nor eng, only include debuggable apps
+ final boolean debuggableBuild = mAndroidBuildClassifier.isDebuggableBuild();
+ if (!debuggableBuild) {
+ intent.putExtra(AppPicker.EXTRA_DEBUGGABLE, true /* value */);
+ }
startActivityForResult(intent, REQUEST_COMPAT_CHANGE_APP);
}
diff --git a/src/com/android/settings/deviceinfo/MigrateEstimateTask.java b/src/com/android/settings/deviceinfo/MigrateEstimateTask.java
index c41ebe0..a5790b3 100644
--- a/src/com/android/settings/deviceinfo/MigrateEstimateTask.java
+++ b/src/com/android/settings/deviceinfo/MigrateEstimateTask.java
@@ -29,7 +29,7 @@
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
-import android.telecom.Log;
+import android.util.Log;
import android.text.format.DateUtils;
import android.text.format.Formatter;
diff --git a/src/com/android/settings/deviceinfo/OWNERS b/src/com/android/settings/deviceinfo/OWNERS
new file mode 100644
index 0000000..bedbe16
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/OWNERS
@@ -0,0 +1,6 @@
+# Default reviewers for this and subdirectories.
+andychou@google.com
+bonianchen@google.com
+allenwtsu@google.com
+
+# Emergency approvers in case the above are not available
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
index 0751141..26d8e2b 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
+++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
@@ -25,6 +25,7 @@
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.UserHandle;
+import android.telephony.Annotation;
import android.telephony.CarrierConfigManager;
import android.telephony.CellSignalStrength;
import android.telephony.PhoneStateListener;
@@ -35,12 +36,14 @@
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
+import android.telephony.UiccCardInfo;
import android.telephony.euicc.EuiccManager;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
+import com.android.internal.telephony.PhoneConstants;
import com.android.settings.R;
import com.android.settingslib.DeviceInfoUtils;
import com.android.settingslib.Utils;
@@ -50,6 +53,7 @@
import com.android.settingslib.core.lifecycle.events.OnResume;
import java.util.List;
+import java.util.Map;
public class SimStatusDialogController implements LifecycleObserver, OnResume, OnPause {
@@ -82,6 +86,8 @@
@VisibleForTesting
final static int ICCID_INFO_VALUE_ID = R.id.icc_id_value;
@VisibleForTesting
+ final static int EID_INFO_LABEL_ID = R.id.esim_id_label;
+ @VisibleForTesting
final static int EID_INFO_VALUE_ID = R.id.esim_id_value;
@VisibleForTesting
final static int IMS_REGISTRATION_STATE_LABEL_ID = R.id.ims_reg_state_label;
@@ -100,15 +106,18 @@
public void onSubscriptionsChanged() {
mSubscriptionInfo = mSubscriptionManager.getActiveSubscriptionInfo(
mSubscriptionInfo.getSubscriptionId());
+ mTelephonyManager = mTelephonyManager.createForSubscriptionId(
+ mSubscriptionInfo.getSubscriptionId());
updateNetworkProvider();
}
};
private SubscriptionInfo mSubscriptionInfo;
- private int mSlotIndex;
+
+ private final int mSlotIndex;
+ private TelephonyManager mTelephonyManager;
private final SimStatusDialogFragment mDialog;
- private final TelephonyManager mTelephonyManager;
private final SubscriptionManager mSubscriptionManager;
private final CarrierConfigManager mCarrierConfigManager;
private final EuiccManager mEuiccManager;
@@ -166,11 +175,13 @@
mPhoneStateListener = getPhoneStateListener();
updateNetworkProvider();
- final ServiceState serviceState = getCurrentServiceState();
+ final ServiceState serviceState = mTelephonyManager.getServiceState();
+ final SignalStrength signalStrength = mTelephonyManager.getSignalStrength();
+
updatePhoneNumber();
updateLatestAreaInfo();
updateServiceState(serviceState);
- updateSignalStrength(getSignalStrength());
+ updateSignalStrength(signalStrength);
updateNetworkType();
updateRoamingStatus(serviceState);
updateIccidNumber();
@@ -182,12 +193,12 @@
if (mSubscriptionInfo == null) {
return;
}
-
- mTelephonyManager.createForSubscriptionId(mSubscriptionInfo.getSubscriptionId())
- .listen(mPhoneStateListener,
- PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
- | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
- | PhoneStateListener.LISTEN_SERVICE_STATE);
+ mTelephonyManager = mTelephonyManager.createForSubscriptionId(
+ mSubscriptionInfo.getSubscriptionId());
+ mTelephonyManager.listen(mPhoneStateListener,
+ PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
+ | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
+ | PhoneStateListener.LISTEN_SERVICE_STATE);
mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
if (mShowLatestAreaInfo) {
@@ -209,8 +220,7 @@
}
mSubscriptionManager.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
- mTelephonyManager.createForSubscriptionId(mSubscriptionInfo.getSubscriptionId())
- .listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+ mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
if (mShowLatestAreaInfo) {
mContext.unregisterReceiver(mAreaInfoReceiver);
@@ -313,7 +323,7 @@
return;
}
- ServiceState serviceState = getCurrentServiceState();
+ ServiceState serviceState = mTelephonyManager.getServiceState();
if (serviceState == null || !Utils.isInService(serviceState)) {
return;
}
@@ -342,13 +352,13 @@
String dataNetworkTypeName = null;
String voiceNetworkTypeName = null;
final int subId = mSubscriptionInfo.getSubscriptionId();
- final int actualDataNetworkType = mTelephonyManager.getDataNetworkType(subId);
- final int actualVoiceNetworkType = mTelephonyManager.getVoiceNetworkType(subId);
+ final int actualDataNetworkType = mTelephonyManager.getDataNetworkType();
+ final int actualVoiceNetworkType = mTelephonyManager.getVoiceNetworkType();
if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualDataNetworkType) {
- dataNetworkTypeName = mTelephonyManager.getNetworkTypeName(actualDataNetworkType);
+ dataNetworkTypeName = getNetworkTypeName(actualDataNetworkType);
}
if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualVoiceNetworkType) {
- voiceNetworkTypeName = mTelephonyManager.getNetworkTypeName(actualVoiceNetworkType);
+ voiceNetworkTypeName = getNetworkTypeName(actualVoiceNetworkType);
}
boolean show4GForLTE = false;
@@ -393,15 +403,48 @@
mDialog.removeSettingFromScreen(ICCID_INFO_LABEL_ID);
mDialog.removeSettingFromScreen(ICCID_INFO_VALUE_ID);
} else {
- mDialog.setText(ICCID_INFO_VALUE_ID, getSimSerialNumber(subscriptionId));
+ mDialog.setText(ICCID_INFO_VALUE_ID, mTelephonyManager.getSimSerialNumber());
}
}
private void updateEid() {
- if (mEuiccManager.isEnabled()) {
- mDialog.setText(EID_INFO_VALUE_ID, mEuiccManager.getEid());
- } else {
+ boolean shouldHaveEid = false;
+ String eid = null;
+
+ if (mTelephonyManager.getPhoneCount() > PhoneConstants.MAX_PHONE_COUNT_SINGLE_SIM) {
+ // Get EID per-SIM in multi-SIM mode
+ Map<Integer, Integer> mapping = mTelephonyManager.getLogicalToPhysicalSlotMapping();
+ int pSlotId = mapping.getOrDefault(mSlotIndex,
+ SubscriptionManager.INVALID_SIM_SLOT_INDEX);
+
+ if (pSlotId != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ List<UiccCardInfo> infos = mTelephonyManager.getUiccCardsInfo();
+
+ for (UiccCardInfo info : infos) {
+ if (info.getSlotIndex() == pSlotId) {
+ if (info.isEuicc()) {
+ shouldHaveEid = true;
+ eid = info.getEid();
+
+ if (TextUtils.isEmpty(eid)) {
+ eid = mEuiccManager.createForCardId(info.getCardId()).getEid();
+ }
+ }
+ break;
+ }
+ }
+ }
+ } else if (mEuiccManager.isEnabled()) {
+ // Get EID of default eSIM in single-SIM mode
+ shouldHaveEid = true;
+ eid = mEuiccManager.getEid();
+ }
+
+ if (!shouldHaveEid) {
+ mDialog.removeSettingFromScreen(EID_INFO_LABEL_ID);
mDialog.removeSettingFromScreen(EID_INFO_VALUE_ID);
+ } else if (!TextUtils.isEmpty(eid)) {
+ mDialog.setText(EID_INFO_VALUE_ID, eid);
}
}
@@ -426,12 +469,6 @@
return SubscriptionManager.from(mContext).getActiveSubscriptionInfoForSimSlotIndex(slotId);
}
- @VisibleForTesting
- ServiceState getCurrentServiceState() {
- return mTelephonyManager.getServiceStateForSubscriber(
- mSubscriptionInfo.getSubscriptionId());
- }
-
private int getDbm(SignalStrength signalStrength) {
List<CellSignalStrength> cellSignalStrengthList = signalStrength.getCellSignalStrengths();
int dbm = -1;
@@ -490,12 +527,50 @@
}
@VisibleForTesting
- SignalStrength getSignalStrength() {
- return mTelephonyManager.getSignalStrength();
- }
-
- @VisibleForTesting
- String getSimSerialNumber(int subscriptionId) {
- return mTelephonyManager.getSimSerialNumber(subscriptionId);
+ static String getNetworkTypeName(@Annotation.NetworkType int type) {
+ switch (type) {
+ case TelephonyManager.NETWORK_TYPE_GPRS:
+ return "GPRS";
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ return "EDGE";
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ return "UMTS";
+ case TelephonyManager.NETWORK_TYPE_HSDPA:
+ return "HSDPA";
+ case TelephonyManager.NETWORK_TYPE_HSUPA:
+ return "HSUPA";
+ case TelephonyManager.NETWORK_TYPE_HSPA:
+ return "HSPA";
+ case TelephonyManager.NETWORK_TYPE_CDMA:
+ return "CDMA";
+ case TelephonyManager.NETWORK_TYPE_EVDO_0:
+ return "CDMA - EvDo rev. 0";
+ case TelephonyManager.NETWORK_TYPE_EVDO_A:
+ return "CDMA - EvDo rev. A";
+ case TelephonyManager.NETWORK_TYPE_EVDO_B:
+ return "CDMA - EvDo rev. B";
+ case TelephonyManager.NETWORK_TYPE_1xRTT:
+ return "CDMA - 1xRTT";
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ return "LTE";
+ case TelephonyManager.NETWORK_TYPE_EHRPD:
+ return "CDMA - eHRPD";
+ case TelephonyManager.NETWORK_TYPE_IDEN:
+ return "iDEN";
+ case TelephonyManager.NETWORK_TYPE_HSPAP:
+ return "HSPA+";
+ case TelephonyManager.NETWORK_TYPE_GSM:
+ return "GSM";
+ case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
+ return "TD_SCDMA";
+ case TelephonyManager.NETWORK_TYPE_IWLAN:
+ return "IWLAN";
+ case TelephonyManager.NETWORK_TYPE_LTE_CA:
+ return "LTE_CA";
+ case TelephonyManager.NETWORK_TYPE_NR:
+ return "NR";
+ default:
+ return "UNKNOWN";
+ }
}
}
diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java
index fa23101..5e6c54b 100644
--- a/src/com/android/settings/homepage/SettingsHomepageActivity.java
+++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java
@@ -33,6 +33,7 @@
import com.android.settings.R;
import com.android.settings.accounts.AvatarViewMixin;
+import com.android.settings.core.HideNonSystemOverlayMixin;
import com.android.settings.homepage.contextualcards.ContextualCardsFragment;
import com.android.settings.overlay.FeatureFactory;
@@ -54,8 +55,8 @@
.initSearchToolbar(this /* activity */, toolbar, SettingsEnums.SETTINGS_HOMEPAGE);
final ImageView avatarView = findViewById(R.id.account_avatar);
- final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(this, avatarView);
- getLifecycle().addObserver(avatarViewMixin);
+ getLifecycle().addObserver(new AvatarViewMixin(this, avatarView));
+ getLifecycle().addObserver(new HideNonSystemOverlayMixin(this));
if (!getSystemService(ActivityManager.class).isLowRamDevice()) {
// Only allow contextual feature on high ram devices.
diff --git a/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSlice.java b/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSlice.java
index 36a3980..1b7f003 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSlice.java
@@ -17,15 +17,21 @@
import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
+import static android.provider.Settings.Global.LOW_POWER_MODE;
+
import android.annotation.ColorInt;
import android.app.PendingIntent;
import android.app.UiModeManager;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Configuration;
+import android.database.ContentObserver;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Handler;
import android.os.Looper;
+import android.os.PowerManager;
+import android.provider.Settings;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
@@ -39,6 +45,9 @@
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
+import com.android.settings.slices.SliceBackgroundWorker;
+
+import java.io.IOException;
public class DarkThemeSlice implements CustomSliceable {
private static final String TAG = "DarkThemeSlice";
@@ -53,10 +62,12 @@
private final Context mContext;
private final UiModeManager mUiModeManager;
+ private final PowerManager mPowerManager;
public DarkThemeSlice(Context context) {
mContext = context;
mUiModeManager = context.getSystemService(UiModeManager.class);
+ mPowerManager = context.getSystemService(PowerManager.class);
}
@Override
@@ -67,15 +78,18 @@
sActiveUiSession = currentUiSession;
sKeepSliceShow = false;
}
- if (!sKeepSliceShow && !isAvailable(mContext)) {
- return null;
+ // Dark theme slice will disappear when battery saver is ON.
+ if (mPowerManager.isPowerSaveMode() || (!sKeepSliceShow && !isAvailable(mContext))) {
+ return new ListBuilder(mContext, CustomSliceRegistry.DARK_THEME_SLICE_URI,
+ ListBuilder.INFINITY)
+ .setIsError(true)
+ .build();
}
sKeepSliceShow = true;
final PendingIntent toggleAction = getBroadcastIntent(mContext);
@ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
final IconCompat icon =
IconCompat.createWithResource(mContext, R.drawable.dark_theme);
- final boolean isChecked = mUiModeManager.getNightMode() == UiModeManager.MODE_NIGHT_YES;
return new ListBuilder(mContext, CustomSliceRegistry.DARK_THEME_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(color)
@@ -85,7 +99,7 @@
.setSubtitle(mContext.getText(R.string.dark_theme_slice_subtitle))
.setPrimaryAction(
SliceAction.createToggle(toggleAction, null /* actionTitle */,
- isChecked)))
+ isDarkThemeMode(mContext))))
.build();
}
@@ -100,8 +114,7 @@
false);
// make toggle transition more smooth before dark theme takes effect
new Handler(Looper.getMainLooper()).postDelayed(() -> {
- mUiModeManager.setNightMode(
- isChecked ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO);
+ mUiModeManager.setNightModeActivated(isChecked);
}, DELAY_TIME_EXECUTING_DARK_THEME);
}
@@ -110,10 +123,15 @@
return null;
}
+ @Override
+ public Class getBackgroundWorkerClass() {
+ return DarkThemeWorker.class;
+ }
+
@VisibleForTesting
boolean isAvailable(Context context) {
// checking dark theme mode.
- if (mUiModeManager.getNightMode() == UiModeManager.MODE_NIGHT_YES) {
+ if (isDarkThemeMode(context)) {
return false;
}
@@ -121,7 +139,47 @@
final BatteryManager batteryManager = context.getSystemService(BatteryManager.class);
final int level = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
Log.d(TAG, "battery level=" + level);
-
return level <= BATTERY_LEVEL_THRESHOLD;
}
+
+ @VisibleForTesting
+ boolean isDarkThemeMode(Context context) {
+ final int currentNightMode =
+ context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
+ return currentNightMode == Configuration.UI_MODE_NIGHT_YES;
+ }
+
+ public static class DarkThemeWorker extends SliceBackgroundWorker<Void> {
+ private final Context mContext;
+ private final ContentObserver mContentObserver =
+ new ContentObserver(new Handler(Looper.getMainLooper())) {
+ @Override
+ public void onChange(boolean bChanged) {
+ if (mContext.getSystemService(PowerManager.class).isPowerSaveMode()) {
+ notifySliceChange();
+ }
+ }
+ };
+
+ public DarkThemeWorker(Context context, Uri uri) {
+ super(context, uri);
+ mContext = context;
+ }
+
+ @Override
+ protected void onSlicePinned() {
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(LOW_POWER_MODE), false /* notifyForDescendants */,
+ mContentObserver);
+ }
+
+ @Override
+ protected void onSliceUnpinned() {
+ mContext.getContentResolver().unregisterContentObserver(mContentObserver);
+ }
+
+ @Override
+ public void close() throws IOException {
+ }
+ }
}
diff --git a/src/com/android/settings/network/ActiveSubsciptionsListener.java b/src/com/android/settings/network/ActiveSubsciptionsListener.java
new file mode 100644
index 0000000..3e4272d
--- /dev/null
+++ b/src/com/android/settings/network/ActiveSubsciptionsListener.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2019 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.settings.network;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.Looper;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.internal.telephony.TelephonyIntents;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * A listener for active subscription change
+ */
+public abstract class ActiveSubsciptionsListener
+ extends SubscriptionManager.OnSubscriptionsChangedListener
+ implements AutoCloseable {
+
+ private static final String TAG = "ActiveSubsciptions";
+ private static final boolean DEBUG = false;
+
+ /**
+ * Constructor
+ *
+ * @param looper {@code Looper} of this listener
+ * @param context {@code Context} of this listener
+ */
+ public ActiveSubsciptionsListener(Looper looper, Context context) {
+ mLooper = looper;
+ mContext = context;
+
+ mCacheState = new AtomicInteger(STATE_NOT_LISTENING);
+ mMaxActiveSubscriptionInfos = new AtomicInteger(MAX_SUBSCRIPTION_UNKNOWN);
+
+ mSubscriptionChangeIntentFilter = new IntentFilter();
+ mSubscriptionChangeIntentFilter.addAction(
+ CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+ mSubscriptionChangeIntentFilter.addAction(
+ TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
+ mSubscriptionChangeIntentFilter.addAction(
+ TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED);
+ }
+
+ @VisibleForTesting
+ BroadcastReceiver getSubscriptionChangeReceiver() {
+ return new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (isInitialStickyBroadcast()) {
+ return;
+ }
+ final String action = intent.getAction();
+ if (TextUtils.isEmpty(action)) {
+ return;
+ }
+ if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(action)) {
+ final int subId = intent.getIntExtra(
+ CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX,
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ if (!clearCachedSubId(subId)) {
+ return;
+ }
+ }
+ onSubscriptionsChanged();
+ }
+ };
+ }
+
+ private Looper mLooper;
+ private Context mContext;
+
+ private static final int STATE_NOT_LISTENING = 0;
+ private static final int STATE_STOPPING = 1;
+ private static final int STATE_PREPARING = 2;
+ private static final int STATE_LISTENING = 3;
+ private static final int STATE_DATA_CACHED = 4;
+
+ private AtomicInteger mCacheState;
+ private SubscriptionManager mSubscriptionManager;
+
+ private IntentFilter mSubscriptionChangeIntentFilter;
+ private BroadcastReceiver mSubscriptionChangeReceiver;
+
+ private static final int MAX_SUBSCRIPTION_UNKNOWN = -1;
+
+ private AtomicInteger mMaxActiveSubscriptionInfos;
+ private List<SubscriptionInfo> mCachedActiveSubscriptionInfo;
+
+ /**
+ * Active subscriptions got changed
+ */
+ public abstract void onChanged();
+
+ @Override
+ public void onSubscriptionsChanged() {
+ // clear value in cache
+ clearCache();
+ listenerNotify();
+ }
+
+ /**
+ * Start listening subscriptions change
+ */
+ public void start() {
+ monitorSubscriptionsChange(true);
+ }
+
+ /**
+ * Stop listening subscriptions change
+ */
+ public void stop() {
+ monitorSubscriptionsChange(false);
+ }
+
+ /**
+ * Implementation of {@code AutoCloseable}
+ */
+ public void close() {
+ stop();
+ }
+
+ /**
+ * Get SubscriptionManager
+ *
+ * @return a SubscriptionManager
+ */
+ public SubscriptionManager getSubscriptionManager() {
+ if (mSubscriptionManager == null) {
+ mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
+ }
+ return mSubscriptionManager;
+ }
+
+ /**
+ * Get current max. number active subscription info(s) been setup within device
+ *
+ * @return max. number of active subscription info(s)
+ */
+ public int getActiveSubscriptionInfoCountMax() {
+ int cacheState = mCacheState.get();
+ if (cacheState < STATE_LISTENING) {
+ return getSubscriptionManager().getActiveSubscriptionInfoCountMax();
+ }
+
+ mMaxActiveSubscriptionInfos.compareAndSet(MAX_SUBSCRIPTION_UNKNOWN,
+ getSubscriptionManager().getActiveSubscriptionInfoCountMax());
+ return mMaxActiveSubscriptionInfos.get();
+ }
+
+ /**
+ * Get a list of active subscription info
+ *
+ * @return A list of active subscription info
+ */
+ public List<SubscriptionInfo> getActiveSubscriptionsInfo() {
+ if (mCacheState.get() >= STATE_DATA_CACHED) {
+ return mCachedActiveSubscriptionInfo;
+ }
+ mCachedActiveSubscriptionInfo = getSubscriptionManager().getActiveSubscriptionInfoList();
+ mCacheState.compareAndSet(STATE_LISTENING, STATE_DATA_CACHED);
+
+ if (DEBUG) {
+ if ((mCachedActiveSubscriptionInfo == null)
+ || (mCachedActiveSubscriptionInfo.size() <= 0)) {
+ Log.d(TAG, "active subscriptions: " + mCachedActiveSubscriptionInfo);
+ } else {
+ final StringBuilder logString = new StringBuilder("active subscriptions:");
+ for (SubscriptionInfo subInfo : mCachedActiveSubscriptionInfo) {
+ logString.append(" " + subInfo.getSubscriptionId());
+ }
+ Log.d(TAG, logString.toString());
+ }
+ }
+
+ return mCachedActiveSubscriptionInfo;
+ }
+
+ /**
+ * Get an active subscription info with given subscription ID
+ *
+ * @param subId target subscription ID
+ * @return A subscription info which is active list
+ */
+ public SubscriptionInfo getActiveSubscriptionInfo(int subId) {
+ final List<SubscriptionInfo> subInfoList = getActiveSubscriptionsInfo();
+ if (subInfoList == null) {
+ return null;
+ }
+ for (SubscriptionInfo subInfo : subInfoList) {
+ if (subInfo.getSubscriptionId() == subId) {
+ return subInfo;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get a list of all subscription info which accessible by Settings app
+ *
+ * @return A list of accessible subscription info
+ */
+ public List<SubscriptionInfo> getAccessibleSubscriptionsInfo() {
+ return getSubscriptionManager().getAvailableSubscriptionInfoList();
+ }
+
+ /**
+ * Get an accessible subscription info with given subscription ID
+ *
+ * @param subId target subscription ID
+ * @return A subscription info which is accessible list
+ */
+ public SubscriptionInfo getAccessibleSubscriptionInfo(int subId) {
+ // Always check if subId is part of activeSubscriptions
+ // since there's cache design within SubscriptionManager.
+ // That give us a chance to avoid from querying ContentProvider.
+ final SubscriptionInfo activeSubInfo = getActiveSubscriptionInfo(subId);
+ if (activeSubInfo != null) {
+ return activeSubInfo;
+ }
+
+ final List<SubscriptionInfo> subInfoList = getAccessibleSubscriptionsInfo();
+ if (subInfoList == null) {
+ return null;
+ }
+ for (SubscriptionInfo subInfo : subInfoList) {
+ if (subInfo.getSubscriptionId() == subId) {
+ return subInfo;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Clear data cached within listener
+ */
+ public void clearCache() {
+ mMaxActiveSubscriptionInfos.set(MAX_SUBSCRIPTION_UNKNOWN);
+ mCacheState.compareAndSet(STATE_DATA_CACHED, STATE_LISTENING);
+ mCachedActiveSubscriptionInfo = null;
+ }
+
+ private void monitorSubscriptionsChange(boolean on) {
+ if (on) {
+ if (!mCacheState.compareAndSet(STATE_NOT_LISTENING, STATE_PREPARING)) {
+ return;
+ }
+
+ if (mSubscriptionChangeReceiver == null) {
+ mSubscriptionChangeReceiver = getSubscriptionChangeReceiver();
+ }
+ mContext.registerReceiver(mSubscriptionChangeReceiver,
+ mSubscriptionChangeIntentFilter, null, new Handler(mLooper));
+ getSubscriptionManager().addOnSubscriptionsChangedListener(this);
+ mCacheState.compareAndSet(STATE_PREPARING, STATE_LISTENING);
+ return;
+ }
+
+ final int currentState = mCacheState.getAndSet(STATE_STOPPING);
+ if (currentState <= STATE_STOPPING) {
+ mCacheState.compareAndSet(STATE_STOPPING, currentState);
+ return;
+ }
+ if (mSubscriptionChangeReceiver != null) {
+ mContext.unregisterReceiver(mSubscriptionChangeReceiver);
+ }
+ getSubscriptionManager().removeOnSubscriptionsChangedListener(this);
+ clearCache();
+ mCacheState.compareAndSet(STATE_STOPPING, STATE_NOT_LISTENING);
+ }
+
+ private void listenerNotify() {
+ if (mCacheState.get() < STATE_LISTENING) {
+ return;
+ }
+ onChanged();
+ }
+
+ private boolean clearCachedSubId(int subId) {
+ if (mCacheState.get() < STATE_DATA_CACHED) {
+ return false;
+ }
+ if (mCachedActiveSubscriptionInfo == null) {
+ return false;
+ }
+ for (SubscriptionInfo subInfo : mCachedActiveSubscriptionInfo) {
+ if (subInfo.getSubscriptionId() == subId) {
+ clearCache();
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/com/android/settings/network/AirplaneModePreferenceController.java b/src/com/android/settings/network/AirplaneModePreferenceController.java
index 5c1913b..d7da909 100644
--- a/src/com/android/settings/network/AirplaneModePreferenceController.java
+++ b/src/com/android/settings/network/AirplaneModePreferenceController.java
@@ -20,7 +20,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.os.SystemProperties;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
@@ -28,12 +27,9 @@
import androidx.preference.SwitchPreference;
import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.TelephonyProperties;
import com.android.settings.AirplaneModeEnabler;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
-import com.android.settings.overlay.FeatureFactory;
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
@@ -47,14 +43,15 @@
private static final String EXIT_ECM_RESULT = "exit_ecm_result";
private Fragment mFragment;
- private final MetricsFeatureProvider mMetricsFeatureProvider;
private AirplaneModeEnabler mAirplaneModeEnabler;
private SwitchPreference mAirplaneModePreference;
public AirplaneModePreferenceController(Context context, String key) {
super(context, key);
- mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
- mAirplaneModeEnabler = new AirplaneModeEnabler(mContext, mMetricsFeatureProvider, this);
+
+ if (isAvailable(mContext)) {
+ mAirplaneModeEnabler = new AirplaneModeEnabler(mContext, this);
+ }
}
public void setFragment(Fragment hostFragment) {
@@ -63,8 +60,8 @@
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
- if (KEY_AIRPLANE_MODE.equals(preference.getKey()) && Boolean.parseBoolean(
- SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {
+ if (KEY_AIRPLANE_MODE.equals(preference.getKey())
+ && mAirplaneModeEnabler.isInEcmMode()) {
// In ECM mode launch ECM app dialog
if (mFragment != null) {
mFragment.startActivityForResult(
@@ -80,9 +77,7 @@
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
- if (isAvailable()) {
- mAirplaneModePreference = screen.findPreference(getPreferenceKey());
- }
+ mAirplaneModePreference = screen.findPreference(getPreferenceKey());
}
public static boolean isAvailable(Context context) {
@@ -117,7 +112,7 @@
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_EXIT_ECM) {
- Boolean isChoiceYes = data.getBooleanExtra(EXIT_ECM_RESULT, false);
+ final boolean isChoiceYes = data.getBooleanExtra(EXIT_ECM_RESULT, false);
// Set Airplane mode based on the return value and checkbox state
mAirplaneModeEnabler.setAirplaneModeInECM(isChoiceYes,
mAirplaneModePreference.isChecked());
diff --git a/src/com/android/settings/network/ApnEditor.java b/src/com/android/settings/network/ApnEditor.java
index 1451a40..84e6b1d 100644
--- a/src/com/android/settings/network/ApnEditor.java
+++ b/src/com/android/settings/network/ApnEditor.java
@@ -16,8 +16,6 @@
package com.android.settings.network;
-import static android.content.Context.TELEPHONY_SERVICE;
-
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.ContentValues;
@@ -29,7 +27,7 @@
import android.os.PersistableBundle;
import android.provider.Telephony;
import android.telephony.CarrierConfigManager;
-import android.telephony.ServiceState;
+import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -60,6 +58,7 @@
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
public class ApnEditor extends SettingsPreferenceFragment
@@ -131,7 +130,7 @@
private boolean mNewApn;
private int mSubId;
- private TelephonyManager mTelephonyManager;
+ private ProxySubscriptionManager mProxySubscriptionMgr;
private int mBearerInitialVal = 0;
private String mMvnoTypeStr;
private String mMvnoMatchDataStr;
@@ -209,6 +208,11 @@
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ // enable ProxySubscriptionMgr with Lifecycle support for all controllers
+ // live within this fragment
+ mProxySubscriptionMgr = ProxySubscriptionManager.getInstance(getContext());
+ mProxySubscriptionMgr.setLifecycle(getLifecycle());
+
addPreferencesFromResource(R.xml.apn_editor);
sNotSet = getResources().getString(R.string.apn_not_set);
@@ -246,10 +250,10 @@
mReadOnlyApnTypes = null;
mReadOnlyApnFields = null;
- CarrierConfigManager configManager = (CarrierConfigManager)
+ final CarrierConfigManager configManager = (CarrierConfigManager)
getSystemService(Context.CARRIER_CONFIG_SERVICE);
if (configManager != null) {
- PersistableBundle b = configManager.getConfigForSubId(mSubId);
+ final PersistableBundle b = configManager.getConfigForSubId(mSubId);
if (b != null) {
mReadOnlyApnTypes = b.getStringArray(
CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY);
@@ -300,10 +304,8 @@
mApnData = new ApnData(sProjection.length);
}
- mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
-
- boolean isUserEdited = mApnData.getInteger(EDITED_INDEX, Telephony.Carriers.USER_EDITED)
- == Telephony.Carriers.USER_EDITED;
+ final boolean isUserEdited = mApnData.getInteger(EDITED_INDEX,
+ Telephony.Carriers.USER_EDITED) == Telephony.Carriers.USER_EDITED;
Log.d(TAG, "onCreate: EDITED " + isUserEdited);
// if it's not a USER_EDITED apn, check if it's read-only
@@ -353,7 +355,7 @@
return false;
}
- List apnList = Arrays.asList(apnTypes);
+ final List apnList = Arrays.asList(apnTypes);
if (apnList.contains(PhoneConstants.APN_TYPE_ALL)) {
Log.d(TAG, "hasAllApns: true because apnList.contains(PhoneConstants.APN_TYPE_ALL)");
return true;
@@ -384,8 +386,8 @@
return true;
}
- List apnTypesList1 = Arrays.asList(apnTypesArray1);
- String[] apnTypesArray2 = apnTypes2.split(",");
+ final List apnTypesList1 = Arrays.asList(apnTypesArray1);
+ final String[] apnTypesArray2 = apnTypes2.split(",");
for (String apn : apnTypesArray2) {
if (apnTypesList1.contains(apn.trim())) {
@@ -457,7 +459,7 @@
*/
private void disableFields(String[] apnFields) {
for (String apnField : apnFields) {
- Preference preference = getPreferenceFromFieldName(apnField);
+ final Preference preference = getPreferenceFromFieldName(apnField);
if (preference != null) {
preference.setEnabled(false);
}
@@ -513,13 +515,15 @@
mMnc.setText(mApnData.getString(MNC_INDEX));
mApnType.setText(mApnData.getString(TYPE_INDEX));
if (mNewApn) {
- String numeric = mTelephonyManager.getSimOperator(mSubId);
- // MCC is first 3 chars and then in 2 - 3 chars of MNC
- if (numeric != null && numeric.length() > 4) {
- // Country code
- String mcc = numeric.substring(0, 3);
- // Network code
- String mnc = numeric.substring(3);
+ final SubscriptionInfo subInfo =
+ mProxySubscriptionMgr.getActiveSubscriptionInfo(mSubId);
+
+ // Country code
+ final String mcc = (subInfo == null) ? null : subInfo.getMccString();
+ // Network code
+ final String mnc = (subInfo == null) ? null : subInfo.getMncString();
+
+ if ((!TextUtils.isEmpty(mcc)) && (!TextUtils.isEmpty(mcc))) {
// Auto populate MNC and MCC for new entries, based on what SIM reports
mMcc.setText(mcc);
mMnc.setText(mnc);
@@ -527,7 +531,7 @@
mCurMcc = mcc;
}
}
- int authVal = mApnData.getInteger(AUTH_TYPE_INDEX, -1);
+ final int authVal = mApnData.getInteger(AUTH_TYPE_INDEX, -1);
if (authVal != -1) {
mAuthType.setValueIndex(authVal);
} else {
@@ -539,7 +543,7 @@
mCarrierEnabled.setChecked(mApnData.getInteger(CARRIER_ENABLED_INDEX, 1) == 1);
mBearerInitialVal = mApnData.getInteger(BEARER_INDEX, 0);
- HashSet<String> bearers = new HashSet<String>();
+ final HashSet<String> bearers = new HashSet<String>();
int bearerBitmask = mApnData.getInteger(BEARER_BITMASK_INDEX, 0);
if (bearerBitmask == 0) {
if (mBearerInitialVal == 0) {
@@ -585,12 +589,12 @@
mMnc.setSummary(formatInteger(checkNull(mMnc.getText())));
mApnType.setSummary(checkNull(mApnType.getText()));
- String authVal = mAuthType.getValue();
+ final String authVal = mAuthType.getValue();
if (authVal != null) {
- int authValIndex = Integer.parseInt(authVal);
+ final int authValIndex = Integer.parseInt(authVal);
mAuthType.setValueIndex(authValIndex);
- String[] values = getResources().getStringArray(R.array.apn_auth_entries);
+ final String[] values = getResources().getStringArray(R.array.apn_auth_entries);
mAuthType.setSummary(values[authValIndex]);
} else {
mAuthType.setSummary(sNotSet);
@@ -605,7 +609,8 @@
checkNull(mvnoDescription(mMvnoType.getValue())));
mMvnoMatchData.setSummary(checkNull(mMvnoMatchData.getText()));
// allow user to edit carrier_enabled for some APN
- boolean ceEditable = getResources().getBoolean(R.bool.config_allow_edit_carrier_enabled);
+ final boolean ceEditable = getResources().getBoolean(
+ R.bool.config_allow_edit_carrier_enabled);
if (ceEditable) {
mCarrierEnabled.setEnabled(true);
} else {
@@ -619,11 +624,11 @@
* return null.
*/
private String protocolDescription(String raw, ListPreference protocol) {
- int protocolIndex = protocol.findIndexOfValue(raw);
+ final int protocolIndex = protocol.findIndexOfValue(raw);
if (protocolIndex == -1) {
return null;
} else {
- String[] values = getResources().getStringArray(R.array.apn_protocol_entries);
+ final String[] values = getResources().getStringArray(R.array.apn_protocol_entries);
try {
return values[protocolIndex];
} catch (ArrayIndexOutOfBoundsException e) {
@@ -633,8 +638,8 @@
}
private String bearerMultiDescription(Set<String> raw) {
- String[] values = getResources().getStringArray(R.array.bearer_entries);
- StringBuilder retVal = new StringBuilder();
+ final String[] values = getResources().getStringArray(R.array.bearer_entries);
+ final StringBuilder retVal = new StringBuilder();
boolean first = true;
for (String bearer : raw) {
int bearerIndex = mBearerMulti.findIndexOfValue(bearer);
@@ -649,7 +654,7 @@
// ignore
}
}
- String val = retVal.toString();
+ final String val = retVal.toString();
if (!TextUtils.isEmpty(val)) {
return val;
}
@@ -657,26 +662,45 @@
}
private String mvnoDescription(String newValue) {
- int mvnoIndex = mMvnoType.findIndexOfValue(newValue);
- String oldValue = mMvnoType.getValue();
+ final int mvnoIndex = mMvnoType.findIndexOfValue(newValue);
+ final String oldValue = mMvnoType.getValue();
if (mvnoIndex == -1) {
return null;
} else {
- String[] values = getResources().getStringArray(R.array.mvno_type_entries);
- boolean mvnoMatchDataUneditable =
+ final String[] values = getResources().getStringArray(R.array.mvno_type_entries);
+ final boolean mvnoMatchDataUneditable =
mReadOnlyApn || (mReadOnlyApnFields != null
&& Arrays.asList(mReadOnlyApnFields)
.contains(Telephony.Carriers.MVNO_MATCH_DATA));
mMvnoMatchData.setEnabled(!mvnoMatchDataUneditable && mvnoIndex != 0);
if (newValue != null && newValue.equals(oldValue) == false) {
if (values[mvnoIndex].equals("SPN")) {
- mMvnoMatchData.setText(mTelephonyManager.getSimOperatorName());
+ TelephonyManager telephonyManager = (TelephonyManager)
+ getContext().getSystemService(TelephonyManager.class);
+ final TelephonyManager telephonyManagerForSubId =
+ telephonyManager.createForSubscriptionId(mSubId);
+ if (telephonyManagerForSubId != null) {
+ telephonyManager = telephonyManagerForSubId;
+ }
+ mMvnoMatchData.setText(telephonyManager.getSimOperatorName());
} else if (values[mvnoIndex].equals("IMSI")) {
- String numeric = mTelephonyManager.getSimOperator(mSubId);
- mMvnoMatchData.setText(numeric + "x");
+ final SubscriptionInfo subInfo =
+ mProxySubscriptionMgr.getAccessibleSubscriptionInfo(mSubId);
+ final String mcc = (subInfo == null) ? "" :
+ Objects.toString(subInfo.getMccString(), "");
+ final String mnc = (subInfo == null) ? "" :
+ Objects.toString(subInfo.getMncString(), "");
+ mMvnoMatchData.setText(mcc + mnc + "x");
} else if (values[mvnoIndex].equals("GID")) {
- mMvnoMatchData.setText(mTelephonyManager.getGroupIdLevel1());
+ TelephonyManager telephonyManager = (TelephonyManager)
+ getContext().getSystemService(TelephonyManager.class);
+ final TelephonyManager telephonyManagerForSubId =
+ telephonyManager.createForSubscriptionId(mSubId);
+ if (telephonyManagerForSubId != null) {
+ telephonyManager = telephonyManagerForSubId;
+ }
+ mMvnoMatchData.setText(telephonyManager.getGroupIdLevel1());
}
}
@@ -692,37 +716,37 @@
String key = preference.getKey();
if (KEY_AUTH_TYPE.equals(key)) {
try {
- int index = Integer.parseInt((String) newValue);
+ final int index = Integer.parseInt((String) newValue);
mAuthType.setValueIndex(index);
- String[] values = getResources().getStringArray(R.array.apn_auth_entries);
+ final String[] values = getResources().getStringArray(R.array.apn_auth_entries);
mAuthType.setSummary(values[index]);
} catch (NumberFormatException e) {
return false;
}
} else if (KEY_PROTOCOL.equals(key)) {
- String protocol = protocolDescription((String) newValue, mProtocol);
+ final String protocol = protocolDescription((String) newValue, mProtocol);
if (protocol == null) {
return false;
}
mProtocol.setSummary(protocol);
mProtocol.setValue((String) newValue);
} else if (KEY_ROAMING_PROTOCOL.equals(key)) {
- String protocol = protocolDescription((String) newValue, mRoamingProtocol);
+ final String protocol = protocolDescription((String) newValue, mRoamingProtocol);
if (protocol == null) {
return false;
}
mRoamingProtocol.setSummary(protocol);
mRoamingProtocol.setValue((String) newValue);
} else if (KEY_BEARER_MULTI.equals(key)) {
- String bearer = bearerMultiDescription((Set<String>) newValue);
+ final String bearer = bearerMultiDescription((Set<String>) newValue);
if (bearer == null) {
return false;
}
mBearerMulti.setValues((Set<String>) newValue);
mBearerMulti.setSummary(bearer);
} else if (KEY_MVNO_TYPE.equals(key)) {
- String mvno = mvnoDescription((String) newValue);
+ final String mvno = mvnoDescription((String) newValue);
if (mvno == null) {
return false;
}
@@ -815,14 +839,14 @@
*/
boolean setStringValueAndCheckIfDiff(
ContentValues cv, String key, String value, boolean assumeDiff, int index) {
- String valueFromLocalCache = mApnData.getString(index);
+ final String valueFromLocalCache = mApnData.getString(index);
if (VDBG) {
Log.d(TAG, "setStringValueAndCheckIfDiff: assumeDiff: " + assumeDiff
+ " key: " + key
+ " value: '" + value
+ "' valueFromDb: '" + valueFromLocalCache + "'");
}
- boolean isDiff = assumeDiff
+ final boolean isDiff = assumeDiff
|| !((TextUtils.isEmpty(value) && TextUtils.isEmpty(valueFromLocalCache))
|| (value != null && value.equals(valueFromLocalCache)));
@@ -841,7 +865,7 @@
*/
boolean setIntValueAndCheckIfDiff(
ContentValues cv, String key, int value, boolean assumeDiff, int index) {
- Integer valueFromLocalCache = mApnData.getInteger(index);
+ final Integer valueFromLocalCache = mApnData.getInteger(index);
if (VDBG) {
Log.d(TAG, "setIntValueAndCheckIfDiff: assumeDiff: " + assumeDiff
+ " key: " + key
@@ -849,7 +873,7 @@
+ "' valueFromDb: '" + valueFromLocalCache + "'");
}
- boolean isDiff = assumeDiff || value != valueFromLocalCache;
+ final boolean isDiff = assumeDiff || value != valueFromLocalCache;
if (isDiff) {
cv.put(key, value);
}
@@ -871,18 +895,18 @@
return true;
}
- String name = checkNotSet(mName.getText());
- String apn = checkNotSet(mApn.getText());
- String mcc = checkNotSet(mMcc.getText());
- String mnc = checkNotSet(mMnc.getText());
+ final String name = checkNotSet(mName.getText());
+ final String apn = checkNotSet(mApn.getText());
+ final String mcc = checkNotSet(mMcc.getText());
+ final String mnc = checkNotSet(mMnc.getText());
- String errorMsg = validateApnData();
+ final String errorMsg = validateApnData();
if (errorMsg != null) {
showError();
return false;
}
- ContentValues values = new ContentValues();
+ final ContentValues values = new ContentValues();
// call update() if it's a new APN. If not, check if any field differs from the db value;
// if any diff is found update() should be called
boolean callUpdate = mNewApn;
@@ -946,7 +970,7 @@
callUpdate,
MMSC_INDEX);
- String authVal = mAuthType.getValue();
+ final String authVal = mAuthType.getValue();
if (authVal != null) {
callUpdate = setIntValueAndCheckIfDiff(values,
Telephony.Carriers.AUTH_TYPE,
@@ -993,14 +1017,14 @@
}
}
- Set<String> bearerSet = mBearerMulti.getValues();
+ final Set<String> bearerSet = mBearerMulti.getValues();
int bearerBitmask = 0;
for (String bearer : bearerSet) {
if (Integer.parseInt(bearer) == 0) {
bearerBitmask = 0;
break;
} else {
- bearerBitmask |= ServiceState.getBitmaskForTech(Integer.parseInt(bearer));
+ bearerBitmask |= getBitmaskForTech(Integer.parseInt(bearer));
}
}
callUpdate = setIntValueAndCheckIfDiff(values,
@@ -1012,7 +1036,7 @@
int bearerVal;
if (bearerBitmask == 0 || mBearerInitialVal == 0) {
bearerVal = 0;
- } else if (ServiceState.bitmaskHasTech(bearerBitmask, mBearerInitialVal)) {
+ } else if (bitmaskHasTech(bearerBitmask, mBearerInitialVal)) {
bearerVal = mBearerInitialVal;
} else {
// bearer field was being used but bitmask has changed now and does not include the
@@ -1081,10 +1105,10 @@
String validateApnData() {
String errorMsg = null;
- String name = checkNotSet(mName.getText());
- String apn = checkNotSet(mApn.getText());
- String mcc = checkNotSet(mMcc.getText());
- String mnc = checkNotSet(mMnc.getText());
+ final String name = checkNotSet(mName.getText());
+ final String apn = checkNotSet(mApn.getText());
+ final String mcc = checkNotSet(mMcc.getText());
+ final String mnc = checkNotSet(mMnc.getText());
if (TextUtils.isEmpty(name)) {
errorMsg = getResources().getString(R.string.error_name_empty);
@@ -1101,7 +1125,7 @@
// those
if (!ArrayUtils.isEmpty(mReadOnlyApnTypes)
&& apnTypesMatch(mReadOnlyApnTypes, getUserEnteredApnType())) {
- StringBuilder stringBuilder = new StringBuilder();
+ final StringBuilder stringBuilder = new StringBuilder();
for (String type : mReadOnlyApnTypes) {
stringBuilder.append(type).append(", ");
Log.d(TAG, "validateApnData: appending type: " + type);
@@ -1134,7 +1158,7 @@
if (value == null || value.length() == 0) {
return sNotSet;
} else {
- char[] password = new char[value.length()];
+ final char[] password = new char[value.length()];
for (int i = 0; i < password.length; i++) {
password[i] = '*';
}
@@ -1173,8 +1197,8 @@
apnTypeList = mDefaultApnTypes;
}
- StringBuilder editableApnTypes = new StringBuilder();
- List<String> readOnlyApnTypes = Arrays.asList(mReadOnlyApnTypes);
+ final StringBuilder editableApnTypes = new StringBuilder();
+ final List<String> readOnlyApnTypes = Arrays.asList(mReadOnlyApnTypes);
boolean first = true;
for (String apnType : apnTypeList) {
// add APN type if it is not read-only and is not wild-cardable
@@ -1201,14 +1225,14 @@
public static class ErrorDialog extends InstrumentedDialogFragment {
public static void showError(ApnEditor editor) {
- ErrorDialog dialog = new ErrorDialog();
+ final ErrorDialog dialog = new ErrorDialog();
dialog.setTargetFragment(editor, 0);
dialog.show(editor.getFragmentManager(), "error");
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- String msg = ((ApnEditor) getTargetFragment()).validateApnData();
+ final String msg = ((ApnEditor) getTargetFragment()).validateApnData();
return new AlertDialog.Builder(getContext())
.setTitle(R.string.error_title)
@@ -1296,7 +1320,7 @@
}
Integer getInteger(int index, Integer defaultValue) {
- Integer val = getInteger(index);
+ final Integer val = getInteger(index);
return val == null ? defaultValue : val;
}
@@ -1304,4 +1328,20 @@
return (String) mData[index];
}
}
+
+ private static int getBitmaskForTech(int radioTech) {
+ if (radioTech >= 1) {
+ return (1 << (radioTech - 1));
+ }
+ return 0;
+ }
+
+ private static boolean bitmaskHasTech(int bearerBitmask, int radioTech) {
+ if (bearerBitmask == 0) {
+ return true;
+ } else if (radioTech >= 1) {
+ return ((bearerBitmask & (1 << (radioTech - 1))) != 0);
+ }
+ return false;
+ }
}
diff --git a/src/com/android/settings/network/ApnSettings.java b/src/com/android/settings/network/ApnSettings.java
index 137abadf..94d7bca 100755
--- a/src/com/android/settings/network/ApnSettings.java
+++ b/src/com/android/settings/network/ApnSettings.java
@@ -54,7 +54,6 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.uicc.UiccController;
import com.android.settings.R;
import com.android.settings.RestrictedSettingsFragment;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -114,7 +113,6 @@
private SubscriptionInfo mSubscriptionInfo;
private int mSubId;
private int mPhoneId;
- private UiccController mUiccController;
private String mMvnoType;
private String mMvnoMatchData;
@@ -193,7 +191,6 @@
setIfOnlyAvailableForAdmins(true);
mSubscriptionInfo = getSubscriptionInfo(mSubId);
- mUiccController = UiccController.getInstance();
CarrierConfigManager configManager = (CarrierConfigManager)
getSystemService(Context.CARRIER_CONFIG_SERVICE);
diff --git a/src/com/android/settings/network/GlobalSettingsChangeListener.java b/src/com/android/settings/network/GlobalSettingsChangeListener.java
new file mode 100644
index 0000000..4c58c60
--- /dev/null
+++ b/src/com/android/settings/network/GlobalSettingsChangeListener.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2019 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.settings.network;
+
+import static androidx.lifecycle.Lifecycle.Event.ON_DESTROY;
+import static androidx.lifecycle.Lifecycle.Event.ON_START;
+import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * A listener for Settings.Global configuration change, with support of Lifecycle
+ */
+public abstract class GlobalSettingsChangeListener extends ContentObserver
+ implements LifecycleObserver, AutoCloseable {
+
+ /**
+ * Constructor
+ *
+ * @param context {@code Context} of this listener
+ * @param field field of Global Settings
+ */
+ public GlobalSettingsChangeListener(Context context, String field) {
+ this(Looper.getMainLooper(), context, field);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param looper {@code Looper} for processing callback
+ * @param context {@code Context} of this listener
+ * @param field field of Global Settings
+ */
+ public GlobalSettingsChangeListener(Looper looper, Context context, String field) {
+ super(new Handler(looper));
+ mContext = context;
+ mField = field;
+ mUri = Settings.Global.getUriFor(field);
+ mListening = new AtomicBoolean(false);
+ monitorUri(true);
+ }
+
+ private Context mContext;
+ private String mField;
+ private Uri mUri;
+ private AtomicBoolean mListening;
+ private Lifecycle mLifecycle;
+
+ /**
+ * Observed Settings got changed
+ */
+ public abstract void onChanged(String field);
+
+ /**
+ * Notify change of Globals.Setting based on given Lifecycle
+ *
+ * @param lifecycle life cycle to reference
+ */
+ public void notifyChangeBasedOn(Lifecycle lifecycle) {
+ if (mLifecycle != null) {
+ mLifecycle.removeObserver(this);
+ }
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
+ mLifecycle = lifecycle;
+ }
+
+ public void onChange(boolean selfChange) {
+ if (!mListening.get()) {
+ return;
+ }
+ onChanged(mField);
+ }
+
+ @OnLifecycleEvent(ON_START)
+ void onStart() {
+ monitorUri(true);
+ }
+
+ @OnLifecycleEvent(ON_STOP)
+ void onStop() {
+ monitorUri(false);
+ }
+
+ @OnLifecycleEvent(ON_DESTROY)
+ void onDestroy() {
+ close();
+ }
+
+ /**
+ * Implementation of AutoCloseable
+ */
+ public void close() {
+ monitorUri(false);
+ notifyChangeBasedOn(null);
+ }
+
+ private void monitorUri(boolean on) {
+ if (!mListening.compareAndSet(!on, on)) {
+ return;
+ }
+
+ if (on) {
+ mContext.getContentResolver().registerContentObserver(mUri, false, this);
+ return;
+ }
+
+ mContext.getContentResolver().unregisterContentObserver(this);
+ }
+}
diff --git a/src/com/android/settings/network/MobileDataContentObserver.java b/src/com/android/settings/network/MobileDataContentObserver.java
index b8a1c8c..0aab75f 100644
--- a/src/com/android/settings/network/MobileDataContentObserver.java
+++ b/src/com/android/settings/network/MobileDataContentObserver.java
@@ -33,9 +33,13 @@
super(handler);
}
- public static Uri getObservableUri(int subId) {
+ /**
+ * Return a URI of mobile data(ON vs OFF)
+ */
+ public static Uri getObservableUri(Context context, int subId) {
Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA);
- if (TelephonyManager.getDefault().getSimCount() != 1) {
+ TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
+ if (telephonyManager.getActiveModemCount() != 1) {
uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + subId);
}
return uri;
@@ -54,7 +58,7 @@
}
public void register(Context context, int subId) {
- final Uri uri = getObservableUri(subId);
+ final Uri uri = getObservableUri(context, subId);
context.getContentResolver().registerContentObserver(uri, false, this);
}
diff --git a/src/com/android/settings/network/OWNERS b/src/com/android/settings/network/OWNERS
new file mode 100644
index 0000000..bedbe16
--- /dev/null
+++ b/src/com/android/settings/network/OWNERS
@@ -0,0 +1,6 @@
+# Default reviewers for this and subdirectories.
+andychou@google.com
+bonianchen@google.com
+allenwtsu@google.com
+
+# Emergency approvers in case the above are not available
diff --git a/src/com/android/settings/network/ProxySubscriptionManager.java b/src/com/android/settings/network/ProxySubscriptionManager.java
new file mode 100644
index 0000000..0306b55
--- /dev/null
+++ b/src/com/android/settings/network/ProxySubscriptionManager.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2019 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.settings.network;
+
+import static androidx.lifecycle.Lifecycle.Event.ON_DESTROY;
+import static androidx.lifecycle.Lifecycle.Event.ON_START;
+import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+
+import android.content.Context;
+import android.os.Looper;
+import android.provider.Settings;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A proxy to the subscription manager
+ */
+public class ProxySubscriptionManager implements LifecycleObserver {
+
+ /**
+ * Interface for monitor active subscriptions list changing
+ */
+ public interface OnActiveSubscriptionChangedListener {
+ /**
+ * When active subscriptions list get changed
+ */
+ void onChanged();
+ /**
+ * get Lifecycle of listener
+ *
+ * @return Returns Lifecycle.
+ */
+ default Lifecycle getLifecycle() {
+ return null;
+ }
+ }
+
+ /**
+ * Get proxy instance to subscription manager
+ *
+ * @return proxy to subscription manager
+ */
+ public static ProxySubscriptionManager getInstance(Context context) {
+ if (sSingleton != null) {
+ return sSingleton;
+ }
+ sSingleton = new ProxySubscriptionManager(context.getApplicationContext());
+ return sSingleton;
+ }
+
+ private static ProxySubscriptionManager sSingleton;
+
+ private ProxySubscriptionManager(Context context) {
+ final Looper looper = Looper.getMainLooper();
+
+ mActiveSubscriptionsListeners =
+ new ArrayList<OnActiveSubscriptionChangedListener>();
+
+ mSubscriptionMonitor = new ActiveSubsciptionsListener(looper, context) {
+ public void onChanged() {
+ notifyAllListeners();
+ }
+ };
+ mAirplaneModeMonitor = new GlobalSettingsChangeListener(looper,
+ context, Settings.Global.AIRPLANE_MODE_ON) {
+ public void onChanged(String field) {
+ mSubscriptionMonitor.clearCache();
+ notifyAllListeners();
+ }
+ };
+
+ mSubscriptionMonitor.start();
+ }
+
+ private Lifecycle mLifecycle;
+ private ActiveSubsciptionsListener mSubscriptionMonitor;
+ private GlobalSettingsChangeListener mAirplaneModeMonitor;
+
+ private List<OnActiveSubscriptionChangedListener> mActiveSubscriptionsListeners;
+
+ private void notifyAllListeners() {
+ for (OnActiveSubscriptionChangedListener listener : mActiveSubscriptionsListeners) {
+ final Lifecycle lifecycle = listener.getLifecycle();
+ if ((lifecycle == null)
+ || (lifecycle.getCurrentState().isAtLeast(Lifecycle.State.STARTED))) {
+ listener.onChanged();
+ }
+ }
+ }
+
+ /**
+ * Lifecycle for data within proxy
+ *
+ * @param lifecycle life cycle to reference
+ */
+ public void setLifecycle(Lifecycle lifecycle) {
+ if (mLifecycle == lifecycle) {
+ return;
+ }
+ if (mLifecycle != null) {
+ mLifecycle.removeObserver(this);
+ }
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
+ mLifecycle = lifecycle;
+ mAirplaneModeMonitor.notifyChangeBasedOn(lifecycle);
+ }
+
+ @OnLifecycleEvent(ON_START)
+ void onStart() {
+ mSubscriptionMonitor.start();
+ }
+
+ @OnLifecycleEvent(ON_STOP)
+ void onStop() {
+ mSubscriptionMonitor.stop();
+ }
+
+ @OnLifecycleEvent(ON_DESTROY)
+ void onDestroy() {
+ mSubscriptionMonitor.close();
+ mAirplaneModeMonitor.close();
+
+ if (mLifecycle != null) {
+ mLifecycle.removeObserver(this);
+ mLifecycle = null;
+
+ sSingleton = null;
+ }
+ }
+
+ /**
+ * Get SubscriptionManager
+ *
+ * @return a SubscriptionManager
+ */
+ public SubscriptionManager get() {
+ return mSubscriptionMonitor.getSubscriptionManager();
+ }
+
+ /**
+ * Get current max. number active subscription info(s) been setup within device
+ *
+ * @return max. number of active subscription info(s)
+ */
+ public int getActiveSubscriptionInfoCountMax() {
+ return mSubscriptionMonitor.getActiveSubscriptionInfoCountMax();
+ }
+
+ /**
+ * Get a list of active subscription info
+ *
+ * @return A list of active subscription info
+ */
+ public List<SubscriptionInfo> getActiveSubscriptionsInfo() {
+ return mSubscriptionMonitor.getActiveSubscriptionsInfo();
+ }
+
+ /**
+ * Get an active subscription info with given subscription ID
+ *
+ * @param subId target subscription ID
+ * @return A subscription info which is active list
+ */
+ public SubscriptionInfo getActiveSubscriptionInfo(int subId) {
+ return mSubscriptionMonitor.getActiveSubscriptionInfo(subId);
+ }
+
+ /**
+ * Get a list of accessible subscription info
+ *
+ * @return A list of accessible subscription info
+ */
+ public List<SubscriptionInfo> getAccessibleSubscriptionsInfo() {
+ return mSubscriptionMonitor.getAccessibleSubscriptionsInfo();
+ }
+
+ /**
+ * Get an accessible subscription info with given subscription ID
+ *
+ * @param subId target subscription ID
+ * @return A subscription info which is accessible list
+ */
+ public SubscriptionInfo getAccessibleSubscriptionInfo(int subId) {
+ return mSubscriptionMonitor.getAccessibleSubscriptionInfo(subId);
+ }
+
+ /**
+ * Clear data cached within proxy
+ */
+ public void clearCache() {
+ mSubscriptionMonitor.clearCache();
+ }
+
+ /**
+ * Add listener to active subscriptions monitor list
+ *
+ * @param listener listener to active subscriptions change
+ */
+ public void addActiveSubscriptionsListener(OnActiveSubscriptionChangedListener listener) {
+ if (mActiveSubscriptionsListeners.contains(listener)) {
+ return;
+ }
+ mActiveSubscriptionsListeners.add(listener);
+ }
+
+ /**
+ * Remove listener from active subscriptions monitor list
+ *
+ * @param listener listener to active subscriptions change
+ */
+ public void removeActiveSubscriptionsListener(OnActiveSubscriptionChangedListener listener) {
+ mActiveSubscriptionsListeners.remove(listener);
+ }
+}
diff --git a/src/com/android/settings/network/telephony/DataServiceSetupPreferenceController.java b/src/com/android/settings/network/telephony/DataServiceSetupPreferenceController.java
index d1fbd73..46f398c 100644
--- a/src/com/android/settings/network/telephony/DataServiceSetupPreferenceController.java
+++ b/src/com/android/settings/network/telephony/DataServiceSetupPreferenceController.java
@@ -63,7 +63,8 @@
public void init(int subId) {
mSubId = subId;
- mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
+ .createForSubscriptionId(mSubId);
}
@Override
diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
index 3abb36a..675a1ba 100644
--- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
+++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
@@ -27,7 +27,6 @@
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.RadioAccessFamily;
-import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -148,7 +147,8 @@
public void init(Lifecycle lifecycle, int subId) {
mSubId = subId;
final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
- mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
+ .createForSubscriptionId(mSubId);
final boolean isLteOnCdma =
mTelephonyManager.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE;
diff --git a/src/com/android/settings/network/telephony/EuiccPreferenceController.java b/src/com/android/settings/network/telephony/EuiccPreferenceController.java
index ecd20ed..68f4370 100644
--- a/src/com/android/settings/network/telephony/EuiccPreferenceController.java
+++ b/src/com/android/settings/network/telephony/EuiccPreferenceController.java
@@ -50,7 +50,8 @@
public void init(int subId) {
mSubId = subId;
- mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
+ .createForSubscriptionId(mSubId);
}
@Override
diff --git a/src/com/android/settings/network/telephony/MmsMessagePreferenceController.java b/src/com/android/settings/network/telephony/MmsMessagePreferenceController.java
index 4d3986b..00f5ebc 100644
--- a/src/com/android/settings/network/telephony/MmsMessagePreferenceController.java
+++ b/src/com/android/settings/network/telephony/MmsMessagePreferenceController.java
@@ -82,7 +82,8 @@
public void init(int subId) {
mSubId = subId;
- mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
+ .createForSubscriptionId(mSubId);
}
@Override
diff --git a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
index c06b78b..daee6ab 100644
--- a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
+++ b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
@@ -138,13 +138,14 @@
public void init(FragmentManager fragmentManager, int subId) {
mFragmentManager = fragmentManager;
mSubId = subId;
- mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
+ .createForSubscriptionId(mSubId);
}
@VisibleForTesting
boolean isDialogNeeded() {
final boolean enableData = !isChecked();
- final boolean isMultiSim = (mTelephonyManager.getSimCount() > 1);
+ final boolean isMultiSim = (mTelephonyManager.getActiveModemCount() > 1);
final int defaultSubId = mSubscriptionManager.getDefaultDataSubscriptionId();
final boolean needToDisableOthers = mSubscriptionManager
.isActiveSubscriptionId(defaultSubId) && defaultSubId != mSubId;
diff --git a/src/com/android/settings/network/telephony/MobileDataSlice.java b/src/com/android/settings/network/telephony/MobileDataSlice.java
index 152028c..c70ae1a 100644
--- a/src/com/android/settings/network/telephony/MobileDataSlice.java
+++ b/src/com/android/settings/network/telephony/MobileDataSlice.java
@@ -252,7 +252,7 @@
}
public void register(Context context, int subId) {
- final Uri uri = MobileDataContentObserver.getObservableUri(subId);
+ final Uri uri = MobileDataContentObserver.getObservableUri(context, subId);
context.getContentResolver().registerContentObserver(uri, false, this);
}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index f1e0819..004291a 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -187,7 +187,8 @@
final Context context = getContext();
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- mTelephonyManager = TelephonyManager.from(context).createForSubscriptionId(mSubId);
+ mTelephonyManager = context.getSystemService(TelephonyManager.class)
+ .createForSubscriptionId(mSubId);
onRestoreInstance(icicle);
}
diff --git a/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java
index 7b24a93..89e2d5b8 100644
--- a/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java
+++ b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java
@@ -20,7 +20,6 @@
import android.os.PersistableBundle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
-import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -97,7 +96,8 @@
public void init(int subId) {
mSubId = subId;
final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
- mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
+ .createForSubscriptionId(mSubId);
final boolean isLteOnCdma =
mTelephonyManager.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE;
diff --git a/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java b/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java
index 2085cdf..a0c9859 100644
--- a/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java
+++ b/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java
@@ -149,7 +149,8 @@
}
final TextView operatorName = view.findViewById(R.id.operator_name_value);
- final ServiceState serviceState = mTelephonyManager.getServiceStateForSubscriber(mSubId);
+ mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId);
+ final ServiceState serviceState = mTelephonyManager.getServiceState();
operatorName.setText(serviceState.getOperatorAlphaLong());
final TextView phoneTitle = view.findViewById(R.id.number_label);
diff --git a/src/com/android/settings/network/telephony/RoamingDialogFragment.java b/src/com/android/settings/network/telephony/RoamingDialogFragment.java
index 1298445..bf22fba 100644
--- a/src/com/android/settings/network/telephony/RoamingDialogFragment.java
+++ b/src/com/android/settings/network/telephony/RoamingDialogFragment.java
@@ -42,7 +42,7 @@
public static RoamingDialogFragment newInstance(int subId) {
final RoamingDialogFragment dialogFragment = new RoamingDialogFragment();
- Bundle args = new Bundle();
+ final Bundle args = new Bundle();
args.putInt(SUB_ID_KEY, subId);
dialogFragment.setArguments(args);
@@ -52,17 +52,17 @@
@Override
public void onAttach(Context context) {
super.onAttach(context);
- Bundle args = getArguments();
+ final Bundle args = getArguments();
mSubId = args.getInt(SUB_ID_KEY);
mCarrierConfigManager = new CarrierConfigManager(context);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
- int title = R.string.roaming_alert_title;
+ final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+ final int title = R.string.roaming_alert_title;
int message = R.string.roaming_warning;
- PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
+ final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
if (carrierConfig != null && carrierConfig.getBoolean(
CarrierConfigManager.KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL)) {
message = R.string.roaming_check_price_warning;
@@ -84,8 +84,13 @@
public void onClick(DialogInterface dialog, int which) {
// let the host know that the positive button has been clicked
if (which == dialog.BUTTON_POSITIVE) {
- TelephonyManager.from(getContext()).createForSubscriptionId(
- mSubId).setDataRoamingEnabled(true);
+ final TelephonyManager telephonyManager =
+ getContext().getSystemService(TelephonyManager.class)
+ .createForSubscriptionId(mSubId);
+ if (telephonyManager == null) {
+ return;
+ }
+ telephonyManager.setDataRoamingEnabled(true);
}
}
}
diff --git a/src/com/android/settings/network/telephony/RoamingPreferenceController.java b/src/com/android/settings/network/telephony/RoamingPreferenceController.java
index dd5fd0e..08fe323 100644
--- a/src/com/android/settings/network/telephony/RoamingPreferenceController.java
+++ b/src/com/android/settings/network/telephony/RoamingPreferenceController.java
@@ -17,22 +17,20 @@
package com.android.settings.network.telephony;
import android.content.Context;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Looper;
import android.os.PersistableBundle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
+import com.android.settings.network.GlobalSettingsChangeListener;
import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
@@ -44,31 +42,59 @@
public class RoamingPreferenceController extends TelephonyTogglePreferenceController implements
LifecycleObserver, OnStart, OnStop {
+ private static final String TAG = "RoamingController";
private static final String DIALOG_TAG = "MobileDataDialog";
private RestrictedSwitchPreference mSwitchPreference;
private TelephonyManager mTelephonyManager;
private CarrierConfigManager mCarrierConfigManager;
- private DataContentObserver mDataContentObserver;
- @VisibleForTesting
- boolean mNeedDialog;
+
+ /**
+ * There're 2 listeners both activated at the same time.
+ * For project that access DATA_ROAMING, only first listener is functional.
+ * For project that access "DATA_ROAMING + subId", first listener will be stopped when receiving
+ * any onChange from second listener.
+ */
+ private GlobalSettingsChangeListener mListener;
+ private GlobalSettingsChangeListener mListenerForSubId;
+
@VisibleForTesting
FragmentManager mFragmentManager;
public RoamingPreferenceController(Context context, String key) {
super(context, key);
mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
- mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper()));
}
@Override
public void onStart() {
- mDataContentObserver.register(mContext, mSubId);
+ if (mListener == null) {
+ mListener = new GlobalSettingsChangeListener(mContext,
+ Settings.Global.DATA_ROAMING) {
+ public void onChanged(String field) {
+ updateState(mSwitchPreference);
+ }
+ };
+ }
+ stopMonitorSubIdSpecific();
+
+ if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ return;
+ }
+
+ mListenerForSubId = new GlobalSettingsChangeListener(mContext,
+ Settings.Global.DATA_ROAMING + mSubId) {
+ public void onChanged(String field) {
+ stopMonitor();
+ updateState(mSwitchPreference);
+ }
+ };
}
@Override
public void onStop() {
- mDataContentObserver.unRegister(mContext);
+ stopMonitor();
+ stopMonitorSubIdSpecific();
}
@Override
@@ -87,7 +113,7 @@
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (TextUtils.equals(preference.getKey(), getPreferenceKey())) {
- if (mNeedDialog) {
+ if (isDialogNeeded()) {
showDialog();
}
return true;
@@ -98,9 +124,7 @@
@Override
public boolean setChecked(boolean isChecked) {
- mNeedDialog = isDialogNeeded();
-
- if (!mNeedDialog) {
+ if (!isDialogNeeded()) {
// Update data directly if we don't need dialog
mTelephonyManager.setDataRoamingEnabled(isChecked);
return true;
@@ -141,7 +165,18 @@
public void init(FragmentManager fragmentManager, int subId) {
mFragmentManager = fragmentManager;
mSubId = subId;
- mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+ if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ return;
+ }
+ final TelephonyManager telephonyManager = mTelephonyManager
+ .createForSubscriptionId(mSubId);
+ if (telephonyManager == null) {
+ Log.w(TAG, "fail to init in sub" + mSubId);
+ mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ return;
+ }
+ mTelephonyManager = telephonyManager;
}
private void showDialog() {
@@ -150,32 +185,17 @@
dialogFragment.show(mFragmentManager, DIALOG_TAG);
}
- /**
- * Listener that listens data roaming change
- */
- public class DataContentObserver extends ContentObserver {
-
- public DataContentObserver(Handler handler) {
- super(handler);
+ private void stopMonitor() {
+ if (mListener != null) {
+ mListener.close();
+ mListener = null;
}
+ }
- @Override
- public void onChange(boolean selfChange) {
- super.onChange(selfChange);
- updateState(mSwitchPreference);
- }
-
- public void register(Context context, int subId) {
- Uri uri = Settings.Global.getUriFor(Settings.Global.DATA_ROAMING);
- if (TelephonyManager.getDefault().getSimCount() != 1) {
- uri = Settings.Global.getUriFor(Settings.Global.DATA_ROAMING + subId);
- }
- context.getContentResolver().registerContentObserver(uri, false, this);
-
- }
-
- public void unRegister(Context context) {
- context.getContentResolver().unregisterContentObserver(this);
+ private void stopMonitorSubIdSpecific() {
+ if (mListenerForSubId != null) {
+ mListenerForSubId.close();
+ mListenerForSubId = null;
}
}
}
diff --git a/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java b/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java
index ea7d82f..07805b0 100644
--- a/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java
+++ b/src/com/android/settings/network/telephony/cdma/CdmaBasePreferenceController.java
@@ -73,7 +73,8 @@
public void init(PreferenceManager preferenceManager, int subId) {
mPreferenceManager = preferenceManager;
mSubId = subId;
- mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
+ .createForSubscriptionId(mSubId);
}
public void init(int subId) {
diff --git a/src/com/android/settings/network/telephony/cdma/CdmaListPreference.java b/src/com/android/settings/network/telephony/cdma/CdmaListPreference.java
index 14c7169..2cb1840 100644
--- a/src/com/android/settings/network/telephony/cdma/CdmaListPreference.java
+++ b/src/com/android/settings/network/telephony/cdma/CdmaListPreference.java
@@ -41,6 +41,7 @@
}
public void setSubId(int subId) {
- mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(subId);
+ mTelephonyManager = getContext().getSystemService(TelephonyManager.class)
+ .createForSubscriptionId(subId);
}
}
diff --git a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java
index 56d0b2d..626390a 100644
--- a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java
+++ b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java
@@ -144,7 +144,8 @@
public AutoSelectPreferenceController init(int subId) {
mSubId = subId;
- mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
+ .createForSubscriptionId(mSubId);
final PersistableBundle carrierConfig = mContext.getSystemService(
CarrierConfigManager.class).getConfigForSubId(mSubId);
mOnlyAutoSelectInHome = carrierConfig != null
@@ -187,4 +188,4 @@
public interface OnNetworkSelectModeListener {
void onNetworkSelectModeChanged();
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceController.java b/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceController.java
index d679373..8c3928d 100644
--- a/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceController.java
+++ b/src/com/android/settings/network/telephony/gsm/OpenNetworkSelectPagePreferenceController.java
@@ -29,7 +29,6 @@
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
-import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.network.telephony.MobileNetworkUtils;
import com.android.settings.network.telephony.NetworkSelectSettings;
@@ -100,7 +99,8 @@
public OpenNetworkSelectPagePreferenceController init(int subId) {
mSubId = subId;
- mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
+ .createForSubscriptionId(mSubId);
return this;
}
diff --git a/src/com/android/settings/panel/SettingsPanelActivity.java b/src/com/android/settings/panel/SettingsPanelActivity.java
index 749a46e..8693186 100644
--- a/src/com/android/settings/panel/SettingsPanelActivity.java
+++ b/src/com/android/settings/panel/SettingsPanelActivity.java
@@ -32,6 +32,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
+import com.android.settings.core.HideNonSystemOverlayMixin;
/**
* Dialog Activity to host Settings Slices.
@@ -62,6 +63,7 @@
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
createOrUpdatePanel(true /* shouldForceCreation */);
+ getLifecycle().addObserver(new HideNonSystemOverlayMixin(this));
}
@Override
diff --git a/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java b/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java
deleted file mode 100644
index 28533df..0000000
--- a/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (C) 2019 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.settings.privacy;
-
-import static android.Manifest.permission_group.CAMERA;
-import static android.Manifest.permission_group.LOCATION;
-import static android.Manifest.permission_group.MICROPHONE;
-
-import static java.util.concurrent.TimeUnit.DAYS;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.permission.PermissionControllerManager;
-import android.permission.RuntimePermissionUsageInfo;
-import android.provider.DeviceConfig;
-import android.util.Log;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.core.BasePreferenceController;
-import com.android.settingslib.Utils;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnCreate;
-import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
-import com.android.settingslib.core.lifecycle.events.OnStart;
-import com.android.settingslib.widget.BarChartInfo;
-import com.android.settingslib.widget.BarChartPreference;
-import com.android.settingslib.widget.BarViewInfo;
-
-import java.util.ArrayList;
-import java.util.List;
-
-
-public class PermissionBarChartPreferenceController extends BasePreferenceController implements
- PermissionControllerManager.OnPermissionUsageResultCallback, LifecycleObserver, OnCreate,
- OnStart, OnSaveInstanceState {
-
- private static final String TAG = "BarChartPreferenceCtl";
- private static final String KEY_PERMISSION_USAGE = "usage_infos";
-
- @VisibleForTesting
- List<RuntimePermissionUsageInfo> mOldUsageInfos;
- private PackageManager mPackageManager;
- private PrivacyDashboardFragment mParent;
- private BarChartPreference mBarChartPreference;
-
- public PermissionBarChartPreferenceController(Context context, String preferenceKey) {
- super(context, preferenceKey);
- mOldUsageInfos = new ArrayList<>();
- mPackageManager = context.getPackageManager();
- }
-
- public void setFragment(PrivacyDashboardFragment fragment) {
- mParent = fragment;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- if (savedInstanceState != null) {
- mOldUsageInfos = savedInstanceState.getParcelableArrayList(KEY_PERMISSION_USAGE);
- }
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- outState.putParcelableList(KEY_PERMISSION_USAGE, mOldUsageInfos);
- }
-
- @Override
- public int getAvailabilityStatus() {
- return UNSUPPORTED_ON_DEVICE;
- }
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- mBarChartPreference = screen.findPreference(getPreferenceKey());
-
- final BarChartInfo info = new BarChartInfo.Builder()
- .setTitle(R.string.permission_bar_chart_title)
- .setDetails(R.string.permission_bar_chart_details)
- .setEmptyText(R.string.permission_bar_chart_empty_text)
- .setDetailsOnClickListener((View v) -> {
- final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE);
- intent.putExtra(Intent.EXTRA_DURATION_MILLIS, DAYS.toMillis(1));
- mContext.startActivity(intent);
- })
- .build();
-
- mBarChartPreference.initializeBarChart(info);
- if (!mOldUsageInfos.isEmpty()) {
- mBarChartPreference.setBarViewInfos(createBarViews(mOldUsageInfos));
- }
- }
-
- @Override
- public void onStart() {
- if (!isAvailable()) {
- return;
- }
-
- // We don't hide chart when we have existing data.
- mBarChartPreference.updateLoadingState(mOldUsageInfos.isEmpty() /* isLoading */);
- // But we still need to hint user with progress bar that we are updating new usage data.
- mParent.setLoadingEnabled(true /* enabled */);
- retrievePermissionUsageData();
- }
-
- @Override
- public void onPermissionUsageResult(@NonNull List<RuntimePermissionUsageInfo> usageInfos) {
- usageInfos.sort((x, y) -> {
- int usageDiff = y.getAppAccessCount() - x.getAppAccessCount();
- if (usageDiff != 0) {
- return usageDiff;
- }
- String xName = x.getName();
- String yName = y.getName();
- if (xName.equals(LOCATION)) {
- return -1;
- } else if (yName.equals(LOCATION)) {
- return 1;
- } else if (xName.equals(MICROPHONE)) {
- return -1;
- } else if (yName.equals(MICROPHONE)) {
- return 1;
- } else if (xName.equals(CAMERA)) {
- return -1;
- } else if (yName.equals(CAMERA)) {
- return 1;
- }
- return x.getName().compareTo(y.getName());
- });
-
- // If the result is different, we need to update bar views.
- if (!areSamePermissionGroups(usageInfos)) {
- mBarChartPreference.setBarViewInfos(createBarViews(usageInfos));
- mOldUsageInfos = usageInfos;
- }
-
- mBarChartPreference.updateLoadingState(false /* isLoading */);
- mParent.setLoadingEnabled(false /* enabled */);
- }
-
- private void retrievePermissionUsageData() {
- mContext.getSystemService(PermissionControllerManager.class).getPermissionUsages(
- false /* countSystem */, (int) DAYS.toMillis(1),
- mContext.getMainExecutor() /* executor */, this /* callback */);
- }
-
- private BarViewInfo[] createBarViews(List<RuntimePermissionUsageInfo> usageInfos) {
- if (usageInfos.isEmpty()) {
- return null;
- }
-
- final BarViewInfo[] barViewInfos = new BarViewInfo[
- Math.min(BarChartPreference.MAXIMUM_BAR_VIEWS, usageInfos.size())];
-
- for (int index = 0; index < barViewInfos.length; index++) {
- final RuntimePermissionUsageInfo permissionGroupInfo = usageInfos.get(index);
- final int count = permissionGroupInfo.getAppAccessCount();
- final CharSequence permLabel = getPermissionGroupLabel(permissionGroupInfo.getName());
-
- barViewInfos[index] = new BarViewInfo(
- getPermissionGroupIcon(permissionGroupInfo.getName()), count, permLabel,
- mContext.getResources().getQuantityString(R.plurals.permission_bar_chart_label,
- count, count), permLabel);
-
- // Set the click listener for each bar view.
- // The listener will navigate user to permission usage app.
- barViewInfos[index].setClickListener((View v) -> {
- final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE);
- intent.putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, permissionGroupInfo.getName());
- intent.putExtra(Intent.EXTRA_DURATION_MILLIS, DAYS.toMillis(1));
- mContext.startActivity(intent);
- });
- }
-
- return barViewInfos;
- }
-
- private Drawable getPermissionGroupIcon(String permissionGroup) {
- Drawable icon = null;
- try {
- icon = mPackageManager.getPermissionGroupInfo(permissionGroup, 0)
- .loadIcon(mPackageManager);
- icon.setTintList(Utils.getColorAttr(mContext, android.R.attr.textColorSecondary));
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "Cannot find group icon for " + permissionGroup, e);
- }
-
- return icon;
- }
-
- private CharSequence getPermissionGroupLabel(String permissionGroup) {
- CharSequence label = null;
- try {
- label = mPackageManager.getPermissionGroupInfo(permissionGroup, 0)
- .loadLabel(mPackageManager);
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "Cannot find group label for " + permissionGroup, e);
- }
-
- return label;
- }
-
- private boolean areSamePermissionGroups(List<RuntimePermissionUsageInfo> newUsageInfos) {
- if (newUsageInfos.size() != mOldUsageInfos.size()) {
- return false;
- }
-
- for (int index = 0; index < newUsageInfos.size(); index++) {
- final RuntimePermissionUsageInfo newInfo = newUsageInfos.get(index);
- final RuntimePermissionUsageInfo oldInfo = mOldUsageInfos.get(index);
-
- if (!newInfo.getName().equals(oldInfo.getName()) ||
- newInfo.getAppAccessCount() != oldInfo.getAppAccessCount()) {
- return false;
- }
- }
- return true;
- }
-}
diff --git a/src/com/android/settings/privacy/PrivacyDashboardFragment.java b/src/com/android/settings/privacy/PrivacyDashboardFragment.java
index fa21f9d..1869cff 100644
--- a/src/com/android/settings/privacy/PrivacyDashboardFragment.java
+++ b/src/com/android/settings/privacy/PrivacyDashboardFragment.java
@@ -18,14 +18,12 @@
import android.app.settings.SettingsEnums;
import android.content.Context;
-import android.os.Bundle;
import android.provider.SearchIndexableResource;
import android.view.View;
import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
-import com.android.settings.Utils;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.notification.LockScreenNotificationPreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
@@ -75,34 +73,6 @@
return buildPreferenceControllers(context, getSettingsLifecycle());
}
- @Override
- public void onAttach(Context context) {
- super.onAttach(context);
- use(PermissionBarChartPreferenceController.class).setFragment(this /* fragment */);
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- Utils.setActionBarShadowAnimation(getActivity(), getSettingsLifecycle(), getListView());
- initLoadingBar();
- }
-
- @VisibleForTesting
- void initLoadingBar() {
- mProgressHeader = setPinnedHeaderView(R.layout.progress_header);
- mProgressAnimation = mProgressHeader.findViewById(R.id.progress_bar_animation);
- setLoadingEnabled(false);
- }
-
- @VisibleForTesting
- void setLoadingEnabled(boolean enabled) {
- if (mProgressHeader != null && mProgressAnimation != null) {
- mProgressHeader.setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
- mProgressAnimation.setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
- }
- }
-
private static List<AbstractPreferenceController> buildPreferenceControllers(
Context context, Lifecycle lifecycle) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
diff --git a/src/com/android/settings/sim/CallsSimListDialogFragment.java b/src/com/android/settings/sim/CallsSimListDialogFragment.java
index 7d3de44..6dd262b 100644
--- a/src/com/android/settings/sim/CallsSimListDialogFragment.java
+++ b/src/com/android/settings/sim/CallsSimListDialogFragment.java
@@ -47,8 +47,7 @@
return result;
}
for (PhoneAccountHandle handle : phoneAccounts) {
- final PhoneAccount phoneAccount = telecomManager.getPhoneAccount(handle);
- final int subId = telephonyManager.getSubIdForPhoneAccount(phoneAccount);
+ final int subId = telephonyManager.getSubscriptionId(handle);
if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
continue;
diff --git a/src/com/android/settings/sim/OWNERS b/src/com/android/settings/sim/OWNERS
new file mode 100644
index 0000000..bedbe16
--- /dev/null
+++ b/src/com/android/settings/sim/OWNERS
@@ -0,0 +1,6 @@
+# Default reviewers for this and subdirectories.
+andychou@google.com
+bonianchen@google.com
+allenwtsu@google.com
+
+# Emergency approvers in case the above are not available
diff --git a/src/com/android/settings/sim/SimDialogActivity.java b/src/com/android/settings/sim/SimDialogActivity.java
index d24dbf5..0ae294e 100644
--- a/src/com/android/settings/sim/SimDialogActivity.java
+++ b/src/com/android/settings/sim/SimDialogActivity.java
@@ -176,8 +176,7 @@
final TelephonyManager telephonyManager = getSystemService(TelephonyManager.class);
for (PhoneAccountHandle handle : telecomManager.getCallCapablePhoneAccounts()) {
- final PhoneAccount phoneAccount = telecomManager.getPhoneAccount(handle);
- if (subId == telephonyManager.getSubIdForPhoneAccount(phoneAccount)) {
+ if (subId == telephonyManager.getSubscriptionId(handle)) {
return handle;
}
}
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index 7c2992c..45da776 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -240,6 +240,8 @@
searchDestination.putExtra(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, key)
.setAction("com.android.settings.SEARCH_RESULT_TRAMPOLINE")
.setComponent(null);
+ searchDestination.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
+
return searchDestination;
}
diff --git a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
index 4762403..ceda8a7 100644
--- a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
+++ b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
@@ -310,7 +310,7 @@
mHandler.sendEmptyMessageDelayed(MESSAGE_STOP_SCAN_WIFI_LIST, DELAY_TIME_STOP_SCAN_MS);
if (mFilterWifiTracker == null) {
- mFilterWifiTracker = new FilterWifiTracker(getActivity(), getSettingsLifecycle());
+ mFilterWifiTracker = new FilterWifiTracker(getContext(), getSettingsLifecycle());
}
mFilterWifiTracker.onResume();
}
@@ -476,11 +476,13 @@
private final class FilterWifiTracker {
private final List<String> mAccessPointKeys;
private final WifiTracker mWifiTracker;
+ private final Context mContext;
public FilterWifiTracker(Context context, Lifecycle lifecycle) {
mWifiTracker = WifiTrackerFactory.create(context, mWifiListener,
lifecycle, /* includeSaved */ true, /* includeScans */ true);
mAccessPointKeys = new ArrayList<>();
+ mContext = context;
}
/**
@@ -489,7 +491,7 @@
*/
public void updateKeys(List<ScanResult> scanResults) {
for (ScanResult scanResult : scanResults) {
- final String key = AccessPoint.getKey(scanResult);
+ final String key = AccessPoint.getKey(mContext, scanResult);
if (!mAccessPointKeys.contains(key)) {
mAccessPointKeys.add(key);
}
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index 0aae89a..c924aaf 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -583,35 +583,6 @@
}
}
- /**
- * Special handling for WPA2/WPA3 and OWE in Transition mode: The key
- * SECURITY_PSK_SAE_TRANSITION and SECURITY_OWE_TRANSITION are pseudo keys which result by the
- * scan results, but never appears in the saved networks.
- * A saved network is either WPA3 for supporting devices or WPA2 for non-supporting devices,
- * or, OWE for supporting devices or Open for non-supporting devices.
- *
- * @param accessPointSecurity Access point current security type
- * @return Converted security type (if required)
- */
- private int convertSecurityTypeForMatching(int accessPointSecurity) {
- if (accessPointSecurity == AccessPoint.SECURITY_PSK_SAE_TRANSITION) {
- if (mWifiManager.isWpa3SaeSupported()) {
- return AccessPoint.SECURITY_SAE;
- } else {
- return AccessPoint.SECURITY_PSK;
- }
- }
- if (accessPointSecurity == AccessPoint.SECURITY_OWE_TRANSITION) {
- if (mWifiManager.isEnhancedOpenSupported()) {
- return AccessPoint.SECURITY_OWE;
- } else {
- return AccessPoint.SECURITY_NONE;
- }
- }
-
- return accessPointSecurity;
- }
-
public WifiConfiguration getConfig() {
if (mMode == WifiConfigUiBase.MODE_VIEW) {
return null;
@@ -634,8 +605,6 @@
config.shared = mSharedCheckBox.isChecked();
- mAccessPointSecurity = convertSecurityTypeForMatching(mAccessPointSecurity);
-
switch (mAccessPointSecurity) {
case AccessPoint.SECURITY_NONE:
config.allowedKeyManagement.set(KeyMgmt.NONE);
@@ -960,8 +929,7 @@
private void showSecurityFields(boolean refreshEapMethods, boolean refreshCertificates) {
if (mAccessPointSecurity == AccessPoint.SECURITY_NONE ||
- mAccessPointSecurity == AccessPoint.SECURITY_OWE ||
- mAccessPointSecurity == AccessPoint.SECURITY_OWE_TRANSITION) {
+ mAccessPointSecurity == AccessPoint.SECURITY_OWE) {
mView.findViewById(R.id.security_fields).setVisibility(View.GONE);
return;
}
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 8c4bfa2..4d3f230 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -494,9 +494,7 @@
if (isSavedNetwork) {
connect(mSelectedAccessPoint.getConfig(), isSavedNetwork);
} else if ((mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_NONE) ||
- (mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_OWE) ||
- (mSelectedAccessPoint.getSecurity()
- == AccessPoint.SECURITY_OWE_TRANSITION)) {
+ (mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_OWE)) {
/** Bypass dialog for unsecured networks */
mSelectedAccessPoint.generateOpenNetworkConfig();
connect(mSelectedAccessPoint.getConfig(), isSavedNetwork);
@@ -750,8 +748,7 @@
preference.setOrder(index);
if (mOpenSsid != null && mOpenSsid.equals(accessPoint.getSsidStr())
&& (accessPoint.getSecurity() != AccessPoint.SECURITY_NONE &&
- accessPoint.getSecurity() != AccessPoint.SECURITY_OWE &&
- accessPoint.getSecurity() != AccessPoint.SECURITY_OWE_TRANSITION)) {
+ accessPoint.getSecurity() != AccessPoint.SECURITY_OWE)) {
if (!accessPoint.isSaved() || isDisabledByWrongPassword(accessPoint)) {
onPreferenceTreeClick(preference);
mOpenSsid = null;
diff --git a/src/com/android/settings/wifi/WifiUtils.java b/src/com/android/settings/wifi/WifiUtils.java
index c4df567..9b3c1b3 100644
--- a/src/com/android/settings/wifi/WifiUtils.java
+++ b/src/com/android/settings/wifi/WifiUtils.java
@@ -268,8 +268,7 @@
if (accessPoint.isOsuProvider()) {
return CONNECT_TYPE_OSU_PROVISION;
} else if ((accessPoint.getSecurity() == AccessPoint.SECURITY_NONE) ||
- (accessPoint.getSecurity() == AccessPoint.SECURITY_OWE) ||
- (accessPoint.getSecurity() == AccessPoint.SECURITY_OWE_TRANSITION)) {
+ (accessPoint.getSecurity() == AccessPoint.SECURITY_OWE)) {
return CONNECT_TYPE_OPEN_NETWORK;
} else if (accessPoint.isSaved() && config != null
&& config.getNetworkSelectionStatus() != null
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
index 2a958e8..fc1bc25 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -206,7 +206,7 @@
setConfiguratorIntentExtra(intent, wifiManager, wifiConfiguration);
// For a transition mode Wi-Fi AP, creates a QR code that's compatible with more devices
- if (accessPoint.getSecurity() == AccessPoint.SECURITY_PSK_SAE_TRANSITION) {
+ if (accessPoint.isPskSaeTransitionMode()) {
intent.putExtra(EXTRA_WIFI_SECURITY, WifiQrCode.SECURITY_WPA_PSK);
}
@@ -406,7 +406,6 @@
}
break;
case AccessPoint.SECURITY_PSK:
- case AccessPoint.SECURITY_PSK_SAE_TRANSITION:
return true;
default:
}
@@ -419,8 +418,6 @@
case AccessPoint.SECURITY_PSK:
case AccessPoint.SECURITY_WEP:
case AccessPoint.SECURITY_NONE:
- case AccessPoint.SECURITY_PSK_SAE_TRANSITION:
- case AccessPoint.SECURITY_OWE_TRANSITION:
return true;
case AccessPoint.SECURITY_SAE:
if (wifiManager.isWpa3SaeSupported()) {
diff --git a/tests/robotests/src/com/android/settings/AirplaneModeEnablerTest.java b/tests/robotests/src/com/android/settings/AirplaneModeEnablerTest.java
new file mode 100644
index 0000000..24abac9
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/AirplaneModeEnablerTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 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.settings;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.telephony.TelephonyManager;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowSettings;
+
+
+@RunWith(AndroidJUnit4.class)
+public final class AirplaneModeEnablerTest {
+
+ private Context mContext;
+
+ @Mock
+ private AirplaneModeChangedListener mAirplaneModeChangedListener;
+ private AirplaneModeEnabler mAirplaneModeEnabler;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = RuntimeEnvironment.application.getBaseContext();
+ mAirplaneModeEnabler = new AirplaneModeEnabler(mContext,
+ mAirplaneModeChangedListener);
+ }
+
+ @Test
+ public void onRadioPowerStateChanged_beenInvoke_invokeOnAirplaneModeChanged() {
+ mAirplaneModeEnabler.resume();
+
+ ShadowSettings.setAirplaneMode(true);
+
+ mAirplaneModeEnabler.mPhoneStateListener.onRadioPowerStateChanged(
+ TelephonyManager.RADIO_POWER_OFF);
+
+ verify(mAirplaneModeChangedListener, times(1)).onAirplaneModeChanged(true);
+ }
+
+ private class AirplaneModeChangedListener
+ implements AirplaneModeEnabler.OnAirplaneModeChangedListener {
+ public void onAirplaneModeChanged(boolean isAirplaneModeOn) {}
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/development/compat/PlatformCompatDashboardTest.java b/tests/robotests/src/com/android/settings/development/compat/PlatformCompatDashboardTest.java
index 693ed45..d0cb97a 100644
--- a/tests/robotests/src/com/android/settings/development/compat/PlatformCompatDashboardTest.java
+++ b/tests/robotests/src/com/android/settings/development/compat/PlatformCompatDashboardTest.java
@@ -16,16 +16,23 @@
package com.android.settings.development.compat;
+import static com.android.internal.compat.OverrideAllowedState.ALLOWED;
+import static com.android.internal.compat.OverrideAllowedState.DISABLED_NOT_DEBUGGABLE;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.compat.Compatibility.ChangeConfig;
import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.os.RemoteException;
@@ -38,7 +45,9 @@
import com.android.internal.compat.CompatibilityChangeConfig;
import com.android.internal.compat.CompatibilityChangeInfo;
+import com.android.internal.compat.IOverrideValidator;
import com.android.internal.compat.IPlatformCompat;
+import com.android.internal.compat.OverrideAllowedState;
import com.android.settings.R;
import org.junit.Before;
@@ -66,6 +75,10 @@
private ApplicationInfo mApplicationInfo;
@Mock
private PreferenceManager mPreferenceManager;
+ @Mock
+ private IOverrideValidator mOverrideValidator;
+ @Mock
+ private PackageManager mPackageManager;
private Context mContext;
private CompatibilityChangeInfo[] mChanges;
@@ -81,7 +94,11 @@
mChanges[3] = new CompatibilityChangeInfo(4L, "Enabled_After_SDK_1_2", 1, false, "");
mChanges[4] = new CompatibilityChangeInfo(5L, "Enabled_After_SDK_2", 2, false, "");
when(mPlatformCompat.listAllChanges()).thenReturn(mChanges);
- mContext = RuntimeEnvironment.application;
+ when(mPlatformCompat.getOverrideValidator()).thenReturn(mOverrideValidator);
+ // By default, allow any change
+ when(mOverrideValidator.getOverrideAllowedState(anyLong(),anyString()))
+ .thenReturn(new OverrideAllowedState(ALLOWED, -1, -1));
+ mContext = spy(RuntimeEnvironment.application);
mPreferenceManager = new PreferenceManager(mContext);
mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
mApplicationInfo.packageName = APP_NAME;
@@ -91,6 +108,7 @@
doReturn(mPlatformCompat).when(mDashboard).getPlatformCompat();
doReturn(mPreferenceScreen).when(mDashboard).getPreferenceScreen();
doReturn(mPreferenceManager).when(mDashboard).getPreferenceManager();
+ doReturn(mPackageManager).when(mContext).getPackageManager();
}
@Test
@@ -107,8 +125,10 @@
@Test
public void createAppPreference_targetSdkEquals1_summaryReturnsAppNameAndTargetSdk() {
mApplicationInfo.targetSdkVersion = 1;
+ Drawable icon = mock(Drawable.class);
+ when(mApplicationInfo.loadIcon(any(PackageManager.class))).thenReturn(icon);
- Preference appPreference = mDashboard.createAppPreference(any(Drawable.class));
+ Preference appPreference = mDashboard.createAppPreference(mApplicationInfo);
assertThat(appPreference.getSummary()).isEqualTo(APP_NAME + " SDK 1");
}
@@ -128,6 +148,7 @@
assertThat(enabledPreference.getSummary()).isEqualTo(mChanges[0].getName());
assertThat(enabledPreference instanceof SwitchPreference).isTrue();
assertThat(enabledSwitchPreference.isChecked()).isTrue();
+ assertThat(enabledSwitchPreference.isEnabled()).isTrue();
}
@Test
@@ -139,10 +160,32 @@
Preference disabledPreference = mDashboard.createPreferenceForChange(mContext,
disabledChange, config);
-
+
assertThat(disabledPreference.getSummary()).isEqualTo(mChanges[1].getName());
SwitchPreference disabledSwitchPreference = (SwitchPreference) disabledPreference;
assertThat(disabledSwitchPreference.isChecked()).isFalse();
+ assertThat(disabledSwitchPreference.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void createPreferenceForChange_cannotOverride_createDisabledEntry()
+ throws RemoteException {
+ CompatibilityChangeInfo enabledChange = mChanges[0];
+ CompatibilityChangeConfig config = new CompatibilityChangeConfig(
+ new ChangeConfig(new HashSet<Long>(Arrays.asList(enabledChange.getId())),
+ new HashSet<Long>()));
+ when(mOverrideValidator.getOverrideAllowedState(anyLong(),anyString()))
+ .thenReturn(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+
+ Preference preference = mDashboard.createPreferenceForChange(mContext, enabledChange,
+ config);
+
+ SwitchPreference switchPreference = (SwitchPreference) preference;
+
+ assertThat(preference.getSummary()).isEqualTo(mChanges[0].getName());
+ assertThat(preference instanceof SwitchPreference).isTrue();
+ assertThat(switchPreference.isChecked()).isTrue();
+ assertThat(switchPreference.isEnabled()).isFalse();
}
@Test
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java
index 2c0b4fc..782fb25 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java
@@ -18,6 +18,7 @@
import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController.CELL_DATA_NETWORK_TYPE_VALUE_ID;
import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController.CELL_VOICE_NETWORK_TYPE_VALUE_ID;
+import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController.EID_INFO_LABEL_ID;
import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController.EID_INFO_VALUE_ID;
import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController.ICCID_INFO_LABEL_ID;
import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController.ICCID_INFO_VALUE_ID;
@@ -55,10 +56,12 @@
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.UiccCardInfo;
import android.telephony.euicc.EuiccManager;
import androidx.lifecycle.LifecycleOwner;
+import com.android.internal.telephony.PhoneConstants;
import com.android.settings.R;
import com.android.settings.testutils.shadow.ShadowDeviceInfoUtils;
import com.android.settingslib.DeviceInfoUtils;
@@ -79,7 +82,9 @@
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowDeviceInfoUtils.class})
@@ -117,6 +122,9 @@
private LifecycleOwner mLifecycleOwner;
private Lifecycle mLifecycle;
+ private static final String TEST_EID_FROM_CARD = "11111111111111111111111111111111";
+ private static final String TEST_EID_FROM_MANAGER = "22222222222222222222222222222222";
+
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
@@ -126,7 +134,6 @@
mLifecycle = new Lifecycle(mLifecycleOwner);
mController = spy(new SimStatusDialogController(mDialog, mLifecycle, 0 /* phone id */));
ShadowDeviceInfoUtils.setPhoneNumber("");
- doReturn(mServiceState).when(mController).getCurrentServiceState();
//CellSignalStrength setup
doReturn(0).when(mCellSignalStrengthCdma).getDbm();
doReturn(0).when(mCellSignalStrengthCdma).getAsuLevel();
@@ -137,20 +144,31 @@
doReturn(null).when(mSignalStrength).getCellSignalStrengths();
doReturn(mPhoneStateListener).when(mController).getPhoneStateListener();
- doReturn(mSignalStrength).when(mController).getSignalStrength();
doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
- when(mEuiccManager.isEnabled()).thenReturn(true);
- when(mEuiccManager.getEid()).thenReturn("");
ReflectionHelpers.setField(mController, "mTelephonyManager", mTelephonyManager);
ReflectionHelpers.setField(mController, "mCarrierConfigManager", mCarrierConfigManager);
ReflectionHelpers.setField(mController, "mSubscriptionInfo", mSubscriptionInfo);
ReflectionHelpers.setField(mController, "mEuiccManager", mEuiccManager);
ReflectionHelpers.setField(mController, "mSubscriptionManager", mSubscriptionManager);
+
+ when(mTelephonyManager.getPhoneCount()).thenReturn(
+ PhoneConstants.MAX_PHONE_COUNT_SINGLE_SIM);
+ when(mTelephonyManager.getUiccCardsInfo()).thenReturn(new ArrayList<UiccCardInfo>());
+ when(mTelephonyManager.getLogicalToPhysicalSlotMapping()).thenReturn(
+ new HashMap<Integer, Integer>());
+
+ when(mEuiccManager.isEnabled()).thenReturn(false);
+ when(mEuiccManager.getEid()).thenReturn("");
+ when(mEuiccManager.createForCardId(anyInt())).thenReturn(mEuiccManager);
+
when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mPersistableBundle);
when(mPersistableBundle.getBoolean(
CarrierConfigManager.KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL))
.thenReturn(true);
+ when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
+ doReturn(mServiceState).when(mTelephonyManager).getServiceState();
+ doReturn(mSignalStrength).when(mTelephonyManager).getSignalStrength();
final ShadowPackageManager shadowPackageManager =
Shadows.shadowOf(RuntimeEnvironment.application.getPackageManager());
@@ -313,25 +331,25 @@
@Test
@Ignore
public void initialize_updateVoiceNetworkTypeWithEdge_shouldUpdateSettingToEdge() {
- when(mTelephonyManager.getVoiceNetworkType(anyInt())).thenReturn(
+ when(mTelephonyManager.getVoiceNetworkType()).thenReturn(
TelephonyManager.NETWORK_TYPE_EDGE);
mController.initialize();
verify(mDialog).setText(CELL_VOICE_NETWORK_TYPE_VALUE_ID,
- TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_EDGE));
+ SimStatusDialogController.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_EDGE));
}
@Test
@Ignore
public void initialize_updateDataNetworkTypeWithEdge_shouldUpdateSettingToEdge() {
- when(mTelephonyManager.getDataNetworkType(anyInt())).thenReturn(
+ when(mTelephonyManager.getDataNetworkType()).thenReturn(
TelephonyManager.NETWORK_TYPE_EDGE);
mController.initialize();
verify(mDialog).setText(CELL_DATA_NETWORK_TYPE_VALUE_ID,
- TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_EDGE));
+ SimStatusDialogController.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_EDGE));
}
@Test
@@ -400,7 +418,7 @@
final String iccid = "12351351231241";
when(mPersistableBundle.getBoolean(
CarrierConfigManager.KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL)).thenReturn(true);
- doReturn(iccid).when(mController).getSimSerialNumber(anyInt());
+ doReturn(iccid).when(mTelephonyManager).getSimSerialNumber();
mController.initialize();
@@ -408,25 +426,283 @@
}
@Test
- @Ignore
- public void initialize_showEid_shouldSetEidToSetting() {
- final String eid = "12351351231241";
- when(mEuiccManager.getEid()).thenReturn(eid);
+ public void initialize_updateEid_shouldNotSetEid() {
+ when(mTelephonyManager.getPhoneCount()).thenReturn(PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM);
+
+ ArrayList<UiccCardInfo> uiccCardInfos = new ArrayList<>();
+ UiccCardInfo uiccCardInfo1 = new UiccCardInfo(
+ false, // isEuicc
+ 0, // cardId
+ null, // eid
+ "123451234567890", // iccid
+ 0, // slotIndex
+ true); // isRemovable
+ uiccCardInfos.add(uiccCardInfo1);
+ UiccCardInfo uiccCardInfo2 = new UiccCardInfo(
+ true, // isEuicc
+ 1, // cardId
+ null, // eid (unavailable)
+ null, // iccid
+ 1, // slotIndex
+ false); // isRemovable
+ uiccCardInfos.add(uiccCardInfo2);
+ when(mTelephonyManager.getUiccCardsInfo()).thenReturn(uiccCardInfos);
+
+ Map<Integer, Integer> slotMapping = new HashMap<>();
+ slotMapping.put(0, 1);
+ slotMapping.put(1, 0);
+ when(mTelephonyManager.getLogicalToPhysicalSlotMapping()).thenReturn(slotMapping);
+
+ when(mEuiccManager.isEnabled()).thenReturn(true);
+ when(mEuiccManager.getEid()).thenReturn(null);
mController.initialize();
- verify(mDialog).setText(EID_INFO_VALUE_ID, eid);
+ // Keep 'Not available' if neither the card nor the associated manager can provide EID.
+ verify(mDialog, never()).setText(eq(EID_INFO_VALUE_ID), any());
verify(mDialog, never()).removeSettingFromScreen(eq(EID_INFO_VALUE_ID));
}
@Test
- @Ignore
- public void initialize_showEid_euiccManagerIsNotEnabled() {
- when(mEuiccManager.isEnabled()).thenReturn(false);
+ public void initialize_updateEid_shouldSetEidFromCard() {
+ when(mTelephonyManager.getPhoneCount()).thenReturn(PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM);
+
+ ArrayList<UiccCardInfo> uiccCardInfos = new ArrayList<>();
+ UiccCardInfo uiccCardInfo1 = new UiccCardInfo(
+ true, // isEuicc
+ 0, // cardId
+ TEST_EID_FROM_CARD, // eid
+ null, // iccid
+ 0, // slotIndex
+ false); // isRemovable
+ uiccCardInfos.add(uiccCardInfo1);
+ UiccCardInfo uiccCardInfo2 = new UiccCardInfo(
+ false, // isEuicc
+ 1, // cardId
+ null, // eid
+ "123451234567890", // iccid
+ 1, // slotIndex
+ true); // isRemovable
+ uiccCardInfos.add(uiccCardInfo2);
+ when(mTelephonyManager.getUiccCardsInfo()).thenReturn(uiccCardInfos);
+
+ Map<Integer, Integer> slotMapping = new HashMap<>();
+ slotMapping.put(0, 0);
+ slotMapping.put(1, 1);
+ when(mTelephonyManager.getLogicalToPhysicalSlotMapping()).thenReturn(slotMapping);
+
+ when(mEuiccManager.isEnabled()).thenReturn(true);
+ when(mEuiccManager.getEid()).thenReturn(TEST_EID_FROM_MANAGER);
mController.initialize();
+ // Set EID retrieved from the card.
+ verify(mDialog).setText(EID_INFO_VALUE_ID, TEST_EID_FROM_CARD);
+ verify(mDialog, never()).removeSettingFromScreen(eq(EID_INFO_VALUE_ID));
+ }
+
+ @Test
+ public void initialize_updateEid_shouldSetEidFromManager() {
+ when(mTelephonyManager.getPhoneCount()).thenReturn(PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM);
+
+ ArrayList<UiccCardInfo> uiccCardInfos = new ArrayList<>();
+ UiccCardInfo uiccCardInfo1 = new UiccCardInfo(
+ false, // isEuicc
+ 0, // cardId
+ null, // eid
+ "123451234567890", // iccid
+ 0, // slotIndex
+ true); // isRemovable
+ uiccCardInfos.add(uiccCardInfo1);
+ UiccCardInfo uiccCardInfo2 = new UiccCardInfo(
+ true, // isEuicc
+ 1, // cardId
+ null, // eid (unavailable)
+ null, // iccid
+ 1, // slotIndex
+ false); // isRemovable
+ uiccCardInfos.add(uiccCardInfo2);
+ when(mTelephonyManager.getUiccCardsInfo()).thenReturn(uiccCardInfos);
+
+ Map<Integer, Integer> slotMapping = new HashMap<>();
+ slotMapping.put(0, 1);
+ slotMapping.put(1, 0);
+ when(mTelephonyManager.getLogicalToPhysicalSlotMapping()).thenReturn(slotMapping);
+
+ when(mEuiccManager.isEnabled()).thenReturn(true);
+ when(mEuiccManager.getEid()).thenReturn(TEST_EID_FROM_MANAGER);
+ when(mEuiccManager.createForCardId(0)).thenThrow(
+ new RuntimeException("Unexpected card ID was specified"));
+ when(mEuiccManager.createForCardId(1)).thenReturn(mEuiccManager);
+
+ mController.initialize();
+
+ // Set EID retrieved from the manager associated with the card which cannot provide EID.
+ verify(mDialog).setText(EID_INFO_VALUE_ID, TEST_EID_FROM_MANAGER);
+ verify(mDialog, never()).removeSettingFromScreen(eq(EID_INFO_VALUE_ID));
+ }
+
+ @Test
+ public void initialize_updateEid_shouldRemoveEid() {
+ when(mTelephonyManager.getPhoneCount()).thenReturn(PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM);
+
+ ArrayList<UiccCardInfo> uiccCardInfos = new ArrayList<>();
+ UiccCardInfo uiccCardInfo1 = new UiccCardInfo(
+ false, // isEuicc
+ 0, // cardId
+ null, // eid
+ "123451234567890", // iccid
+ 0, // slotIndex
+ true); // isRemovable
+ uiccCardInfos.add(uiccCardInfo1);
+ UiccCardInfo uiccCardInfo2 = new UiccCardInfo(
+ true, // isEuicc
+ 1, // cardId
+ TEST_EID_FROM_CARD, // eid
+ null, // iccid
+ 1, // slotIndex
+ false); // isRemovable
+ uiccCardInfos.add(uiccCardInfo2);
+ when(mTelephonyManager.getUiccCardsInfo()).thenReturn(uiccCardInfos);
+
+ Map<Integer, Integer> slotMapping = new HashMap<>();
+ slotMapping.put(0, 0);
+ slotMapping.put(1, 1);
+ when(mTelephonyManager.getLogicalToPhysicalSlotMapping()).thenReturn(slotMapping);
+
+ when(mEuiccManager.isEnabled()).thenReturn(true);
+ when(mEuiccManager.getEid()).thenReturn(TEST_EID_FROM_MANAGER);
+
+ mController.initialize();
+
+ // Remove EID if the card is not eUICC.
verify(mDialog, never()).setText(eq(EID_INFO_VALUE_ID), any());
+ verify(mDialog).removeSettingFromScreen(eq(EID_INFO_LABEL_ID));
+ verify(mDialog).removeSettingFromScreen(eq(EID_INFO_VALUE_ID));
+ }
+
+ @Test
+ public void initialize_updateEid_shouldNotSetEidInSingleSimMode() {
+ when(mTelephonyManager.getPhoneCount()).thenReturn(
+ PhoneConstants.MAX_PHONE_COUNT_SINGLE_SIM);
+
+ ArrayList<UiccCardInfo> uiccCardInfos = new ArrayList<>();
+ UiccCardInfo uiccCardInfo = new UiccCardInfo(
+ true, // isEuicc
+ 0, // cardId
+ TEST_EID_FROM_CARD, // eid (not used)
+ null, // iccid
+ 0, // slotIndex
+ false); // isRemovable
+ uiccCardInfos.add(uiccCardInfo);
+ when(mTelephonyManager.getUiccCardsInfo()).thenReturn(uiccCardInfos);
+
+ Map<Integer, Integer> slotMapping = new HashMap<>();
+ slotMapping.put(0, 0);
+ when(mTelephonyManager.getLogicalToPhysicalSlotMapping()).thenReturn(slotMapping);
+
+ when(mEuiccManager.isEnabled()).thenReturn(true);
+ when(mEuiccManager.getEid()).thenReturn(null);
+
+ mController.initialize();
+
+ // Keep 'Not available' if the default eUICC manager cannot provide EID in Single SIM mode.
+ verify(mDialog, never()).setText(eq(EID_INFO_VALUE_ID), any());
+ verify(mDialog, never()).removeSettingFromScreen(eq(EID_INFO_VALUE_ID));
+ }
+
+ @Test
+ public void initialize_updateEid_shouldSetEidInSingleSimModeWithEnabledEuicc() {
+ when(mTelephonyManager.getPhoneCount()).thenReturn(
+ PhoneConstants.MAX_PHONE_COUNT_SINGLE_SIM);
+
+ ArrayList<UiccCardInfo> uiccCardInfos = new ArrayList<>();
+ UiccCardInfo uiccCardInfo = new UiccCardInfo(
+ true, // isEuicc (eUICC slot is selected)
+ 0, // cardId
+ TEST_EID_FROM_CARD, // eid (not used)
+ null, // iccid
+ 0, // slotIndex
+ false); // isRemovable
+ uiccCardInfos.add(uiccCardInfo);
+ when(mTelephonyManager.getUiccCardsInfo()).thenReturn(uiccCardInfos);
+
+ Map<Integer, Integer> slotMapping = new HashMap<>();
+ slotMapping.put(0, 0);
+ when(mTelephonyManager.getLogicalToPhysicalSlotMapping()).thenReturn(slotMapping);
+
+ when(mEuiccManager.isEnabled()).thenReturn(true);
+ when(mEuiccManager.getEid()).thenReturn(TEST_EID_FROM_MANAGER);
+ when(mEuiccManager.createForCardId(anyInt())).thenThrow(
+ new RuntimeException("EID shall be retrieved from the default eUICC manager"));
+
+ mController.initialize();
+
+ // Set EID retrieved from the default eUICC manager in Single SIM mode.
+ verify(mDialog).setText(EID_INFO_VALUE_ID, TEST_EID_FROM_MANAGER);
+ verify(mDialog, never()).removeSettingFromScreen(eq(EID_INFO_VALUE_ID));
+ }
+
+ @Test
+ public void initialize_updateEid_shouldSetEidInSingleSimModeWithDisabledEuicc() {
+ when(mTelephonyManager.getPhoneCount()).thenReturn(
+ PhoneConstants.MAX_PHONE_COUNT_SINGLE_SIM);
+
+ ArrayList<UiccCardInfo> uiccCardInfos = new ArrayList<>();
+ UiccCardInfo uiccCardInfo = new UiccCardInfo(
+ false, // isEuicc (eUICC slot is not selected)
+ 0, // cardId
+ null, // eid
+ "123451234567890", // iccid
+ 0, // slotIndex
+ true); // isRemovable
+ uiccCardInfos.add(uiccCardInfo);
+ when(mTelephonyManager.getUiccCardsInfo()).thenReturn(uiccCardInfos);
+
+ Map<Integer, Integer> slotMapping = new HashMap<>();
+ slotMapping.put(0, 0);
+ when(mTelephonyManager.getLogicalToPhysicalSlotMapping()).thenReturn(slotMapping);
+
+ when(mEuiccManager.isEnabled()).thenReturn(true);
+ when(mEuiccManager.getEid()).thenReturn(TEST_EID_FROM_MANAGER);
+ when(mEuiccManager.createForCardId(anyInt())).thenThrow(
+ new RuntimeException("EID shall be retrieved from the default eUICC manager"));
+
+ mController.initialize();
+
+ // Set EID retrieved from the default eUICC manager in Single SIM mode.
+ verify(mDialog).setText(EID_INFO_VALUE_ID, TEST_EID_FROM_MANAGER);
+ verify(mDialog, never()).removeSettingFromScreen(eq(EID_INFO_VALUE_ID));
+ }
+
+ @Test
+ public void initialize_updateEid_shouldRemoveEidInSingleSimMode() {
+ when(mTelephonyManager.getPhoneCount()).thenReturn(
+ PhoneConstants.MAX_PHONE_COUNT_SINGLE_SIM);
+
+ ArrayList<UiccCardInfo> uiccCardInfos = new ArrayList<>();
+ UiccCardInfo uiccCardInfo = new UiccCardInfo(
+ false, // isEuicc
+ 0, // cardId
+ null, // eid
+ "123451234567890", // iccid
+ 0, // slotIndex
+ true); // isRemovable
+ uiccCardInfos.add(uiccCardInfo);
+ when(mTelephonyManager.getUiccCardsInfo()).thenReturn(uiccCardInfos);
+
+ Map<Integer, Integer> slotMapping = new HashMap<>();
+ slotMapping.put(0, 0);
+ when(mTelephonyManager.getLogicalToPhysicalSlotMapping()).thenReturn(slotMapping);
+
+ when(mEuiccManager.isEnabled()).thenReturn(false);
+ when(mEuiccManager.getEid()).thenReturn(null);
+
+ mController.initialize();
+
+ // Remove EID if the default eUICC manager indicates that eSIM is not enabled.
+ verify(mDialog, never()).setText(eq(EID_INFO_VALUE_ID), any());
+ verify(mDialog).removeSettingFromScreen(eq(EID_INFO_LABEL_ID));
verify(mDialog).removeSettingFromScreen(eq(EID_INFO_VALUE_ID));
}
@@ -482,7 +758,7 @@
@Test
@Ignore
public void initialize_nullSignalStrength_noCrash() {
- doReturn(null).when(mController).getSignalStrength();
+ doReturn(null).when(mTelephonyManager).getSignalStrength();
// we should not crash when running the following line
mController.initialize();
}
diff --git a/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java b/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java
index dcb32c4..db12580 100644
--- a/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java
@@ -16,20 +16,42 @@
package com.android.settings.homepage;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.os.Build;
import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
import android.widget.FrameLayout;
import com.android.settings.R;
+import com.android.settings.core.HideNonSystemOverlayMixin;
+import com.android.settings.homepage.contextualcards.slices.BatteryFixSliceTest;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.android.controller.ActivityController;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
public class SettingsHomepageActivityTest {
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
@Test
public void setHomepageContainerPaddingTop_shouldBeSetPaddingTop() {
@@ -55,4 +77,55 @@
assertThat(frameLayout.getLayoutTransition()).isNotNull();
}
+
+ @Test
+ @Config(shadows = {
+ BatteryFixSliceTest.ShadowBatteryStatsHelperLoader.class,
+ BatteryFixSliceTest.ShadowBatteryTipLoader.class
+ })
+ public void onStart_isNotDebuggable_shouldHideSystemOverlay() {
+ ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", false);
+
+ final ActivityController<SettingsHomepageActivity> activityController =
+ Robolectric.buildActivity(SettingsHomepageActivity.class).create();
+ final SettingsHomepageActivity activity = spy(activityController.get());
+ final Window window = mock(Window.class);
+ when(activity.getWindow()).thenReturn(window);
+ activity.getLifecycle().addObserver(new HideNonSystemOverlayMixin(activity));
+
+ activityController.start();
+
+ verify(window).addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+ }
+
+ @Test
+ @Config(shadows = {
+ BatteryFixSliceTest.ShadowBatteryStatsHelperLoader.class,
+ BatteryFixSliceTest.ShadowBatteryTipLoader.class,
+ })
+ public void onStop_isNotDebuggable_shouldRemoveHideSystemOverlay() {
+ ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", false);
+
+ final ActivityController<SettingsHomepageActivity> activityController =
+ Robolectric.buildActivity(SettingsHomepageActivity.class).create();
+ final SettingsHomepageActivity activity = spy(activityController.get());
+ final Window window = mock(Window.class);
+ when(activity.getWindow()).thenReturn(window);
+ activity.getLifecycle().addObserver(new HideNonSystemOverlayMixin(activity));
+
+ activityController.start();
+
+ verify(window).addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+
+ final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
+ when(window.getAttributes()).thenReturn(layoutParams);
+
+ activityController.stop();
+ final ArgumentCaptor<WindowManager.LayoutParams> paramCaptor = ArgumentCaptor.forClass(
+ WindowManager.LayoutParams.class);
+
+ verify(window).setAttributes(paramCaptor.capture());
+ assertThat(paramCaptor.getValue().privateFlags
+ & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS).isEqualTo(0);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSliceTest.java
index bb21332..1af7b2b 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSliceTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSliceTest.java
@@ -22,10 +22,10 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
-import android.app.UiModeManager;
import android.content.Context;
import android.net.Uri;
import android.os.BatteryManager;
+import android.os.PowerManager;
import androidx.slice.Slice;
import androidx.slice.SliceMetadata;
@@ -48,9 +48,9 @@
@RunWith(RobolectricTestRunner.class)
public class DarkThemeSliceTest {
@Mock
- private UiModeManager mUiModeManager;
- @Mock
private BatteryManager mBatteryManager;
+ @Mock
+ private PowerManager mPowerManager;
private Context mContext;
private DarkThemeSlice mDarkThemeSlice;
@@ -63,11 +63,12 @@
mFeatureFactory = FakeFeatureFactory.setupForTest();
mFeatureFactory.slicesFeatureProvider = new SlicesFeatureProviderImpl();
mFeatureFactory.slicesFeatureProvider.newUiSession();
- doReturn(mUiModeManager).when(mContext).getSystemService(UiModeManager.class);
+ doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
+ when(mPowerManager.isPowerSaveMode()).thenReturn(false);
// Set-up specs for SliceMetadata.
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
- mDarkThemeSlice = new DarkThemeSlice(mContext);
+ mDarkThemeSlice = spy(new DarkThemeSlice(mContext));
mDarkThemeSlice.sKeepSliceShow = false;
}
@@ -80,7 +81,7 @@
@Test
public void isAvailable_inDarkThemeMode_returnFalse() {
- when(mUiModeManager.getNightMode()).thenReturn(UiModeManager.MODE_NIGHT_YES);
+ doReturn(true).when(mDarkThemeSlice).isDarkThemeMode(mContext);
assertThat(mDarkThemeSlice.isAvailable(mContext)).isFalse();
}
@@ -100,23 +101,36 @@
}
@Test
- public void getSlice_notAvailable_returnNull() {
- when(mUiModeManager.getNightMode()).thenReturn(UiModeManager.MODE_NIGHT_YES);
+ public void getSlice_batterySaver_returnErrorSlice() {
+ when(mPowerManager.isPowerSaveMode()).thenReturn(true);
- assertThat(mDarkThemeSlice.getSlice()).isNull();
+ final Slice mediaSlice = mDarkThemeSlice.getSlice();
+ final SliceMetadata metadata = SliceMetadata.from(mContext, mediaSlice);
+ assertThat(metadata.isErrorSlice()).isTrue();
}
@Test
- public void getSlice_newSession_notAvailable_returnNull() {
+ public void getSlice_notAvailable_returnErrorSlice() {
+ doReturn(true).when(mDarkThemeSlice).isDarkThemeMode(mContext);
+
+ final Slice mediaSlice = mDarkThemeSlice.getSlice();
+ final SliceMetadata metadata = SliceMetadata.from(mContext, mediaSlice);
+ assertThat(metadata.isErrorSlice()).isTrue();
+ }
+
+ @Test
+ public void getSlice_newSession_notAvailable_returnErrorSlice() {
// previous displayed: yes
mDarkThemeSlice.sKeepSliceShow = true;
// Session: use original value + 1 to become a new session
mDarkThemeSlice.sActiveUiSession =
mFeatureFactory.slicesFeatureProvider.getUiSessionToken() + 1;
- when(mUiModeManager.getNightMode()).thenReturn(UiModeManager.MODE_NIGHT_YES);
+ doReturn(true).when(mDarkThemeSlice).isDarkThemeMode(mContext);
- assertThat(mDarkThemeSlice.getSlice()).isNull();
+ final Slice mediaSlice = mDarkThemeSlice.getSlice();
+ final SliceMetadata metadata = SliceMetadata.from(mContext, mediaSlice);
+ assertThat(metadata.isErrorSlice()).isTrue();
}
@Test
@@ -149,7 +163,7 @@
}
private void setBatteryCapacityLevel(int power_level) {
- when(mUiModeManager.getNightMode()).thenReturn(UiModeManager.MODE_NIGHT_NO);
+ doReturn(false).when(mDarkThemeSlice).isDarkThemeMode(mContext);
doReturn(mBatteryManager).when(mContext).getSystemService(BatteryManager.class);
when(mBatteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY))
.thenReturn(power_level);
diff --git a/tests/robotests/src/com/android/settings/network/ActiveSubsciptionsListenerTest.java b/tests/robotests/src/com/android/settings/network/ActiveSubsciptionsListenerTest.java
new file mode 100644
index 0000000..4c7b55b
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/ActiveSubsciptionsListenerTest.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2019 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.settings.network;
+
+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.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.MockitoAnnotations;
+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(AndroidJUnit4.class)
+public class ActiveSubsciptionsListenerTest {
+ private static final int SUB_ID1 = 3;
+ private static final int SUB_ID2 = 7;
+
+ 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 ShadowContextImpl mShadowContextImpl;
+ private SubscriptionManager mSubscriptionManager;
+ private ShadowSubscriptionManager mShadowSubscriptionManager;
+ private List<SubscriptionInfo> mActiveSubscriptions;
+
+ private ActiveSubsciptionsListenerImpl mListener;
+ private BroadcastReceiver mReceiver;
+ private ShadowBroadcastReceiver mShadowReceiver;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ 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.close();
+ }
+
+ 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() {
+ verify(mListener, never()).onChanged();
+ }
+
+ @Test
+ public void start_configChangedIntent_onChangedShouldBeCalled() {
+ sendIntentToReceiver(INTENT_RADIO_TECHNOLOGY_CHANGED);
+ sendIntentToReceiver(INTENT_MULTI_SIM_CONFIG_CHANGED);
+ verify(mListener, never()).onChanged();
+
+ mListener.start();
+
+ sendIntentToReceiver(INTENT_RADIO_TECHNOLOGY_CHANGED);
+ verify(mListener, times(1)).onChanged();
+
+ 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();
+
+ sendIntentToReceiver(INTENT_CARRIER_CONFIG_CHANGED);
+ verify(mListener, times(1)).onChanged();
+ }
+
+
+ @Test
+ public void start_alwaysFetchAndCacheResult() {
+ mListener.start();
+
+ List<SubscriptionInfo> subInfoList = null;
+ int numberOfAccess = 0;
+ for (int numberOfSubInfo = mActiveSubscriptions.size(); numberOfSubInfo >= 0;
+ numberOfSubInfo--) {
+ if (mActiveSubscriptions.size() > numberOfSubInfo) {
+ mActiveSubscriptions.remove(numberOfSubInfo);
+ }
+ mShadowSubscriptionManager.setActiveSubscriptionInfoList(mActiveSubscriptions);
+
+ // fetch twice and test if they generated access to SubscriptionManager only once
+ subInfoList = mListener.getActiveSubscriptionsInfo();
+ subInfoList = mListener.getActiveSubscriptionsInfo();
+
+ numberOfAccess++;
+ verify(mSubscriptionManager, times(numberOfAccess)).getActiveSubscriptionInfoList();
+
+ mListener.clearCache();
+ }
+
+ mShadowSubscriptionManager.setActiveSubscriptionInfoList(null);
+
+ // fetch twice and test if they generated access to SubscriptionManager only once
+ subInfoList = mListener.getActiveSubscriptionsInfo();
+ subInfoList = mListener.getActiveSubscriptionsInfo();
+
+ numberOfAccess++;
+ verify(mSubscriptionManager, times(numberOfAccess)).getActiveSubscriptionInfoList();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/network/ApnEditorTest.java b/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
index dc14418..3aa6a6f 100644
--- a/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
+++ b/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
@@ -30,6 +30,7 @@
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
+import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
@@ -46,6 +47,7 @@
import com.android.settings.R;
import com.android.settings.network.ApnEditor.ApnData;
+import com.android.settings.testutils.shadow.ShadowFragment;
import org.junit.Before;
import org.junit.Test;
@@ -58,6 +60,7 @@
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
public class ApnEditorTest {
@@ -96,27 +99,33 @@
@Mock
private Cursor mCursor;
+ @Mock
+ private FragmentActivity mActivity;
+
@Captor
private ArgumentCaptor<Uri> mUriCaptor;
private ApnEditor mApnEditorUT;
- private FragmentActivity mActivity;
+ private Context mContext;
private Resources mResources;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mActivity = spy(Robolectric.setupActivity(FragmentActivity.class));
- mResources = mActivity.getResources();
+ mContext = spy(RuntimeEnvironment.application);
+
+ mResources = mContext.getResources();
mApnEditorUT = spy(new ApnEditor());
doReturn(mActivity).when(mApnEditorUT).getActivity();
doReturn(mResources).when(mApnEditorUT).getResources();
doNothing().when(mApnEditorUT).finish();
doNothing().when(mApnEditorUT).showError();
- when(mApnEditorUT.getContext()).thenReturn(RuntimeEnvironment.application);
+ doReturn(mContext).when(mApnEditorUT).getContext();
+ doReturn(mContext.getTheme()).when(mActivity).getTheme();
+ doReturn(mContext.getContentResolver()).when(mActivity).getContentResolver();
- setMockPreference(mActivity);
+ setMockPreference(mContext);
mApnEditorUT.mApnData = new FakeApnData(APN_DATA);
mApnEditorUT.sNotSet = "Not Set";
}
@@ -317,7 +326,7 @@
// WHEN press the back button
final KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
- mApnEditorUT.onKey(new View(mActivity), KeyEvent.KEYCODE_BACK, event);
+ mApnEditorUT.onKey(new View(mContext), KeyEvent.KEYCODE_BACK, event);
// THEN the apn data is saved and the apn editor is closed
verify(mApnEditorUT).validateAndSaveApnData();
@@ -455,7 +464,9 @@
}
@Test
+ @Config(shadows = ShadowFragment.class)
public void onCreate_noAction_shouldFinishAndNoCrash() {
+ doReturn(new Intent()).when(mActivity).getIntent();
doNothing().when(mApnEditorUT).addPreferencesFromResource(anyInt());
mApnEditorUT.onCreate(null);
diff --git a/tests/robotests/src/com/android/settings/network/GlobalSettingsChangeListenerTest.java b/tests/robotests/src/com/android/settings/network/GlobalSettingsChangeListenerTest.java
new file mode 100644
index 0000000..e419071
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/GlobalSettingsChangeListenerTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 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.settings.network;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.spy;
+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;
+
+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;
+
+@RunWith(RobolectricTestRunner.class)
+public class GlobalSettingsChangeListenerTest {
+
+ @Mock
+ private Lifecycle mLifecycle;
+
+ private Context mContext;
+ private GlobalSettingsChangeListener mListener;
+
+ private static final String SETTINGS_FIELD = Settings.Global.AIRPLANE_MODE_ON;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ mListener = spy(new GlobalSettingsChangeListener(Looper.getMainLooper(),
+ mContext, SETTINGS_FIELD) {
+ public void onChanged(String field) {}
+ });
+
+ doNothing().when(mLifecycle).addObserver(mListener);
+ doNothing().when(mLifecycle).removeObserver(mListener);
+ }
+
+ @Test
+ public void whenChanged_onChangedBeenCalled() {
+ mListener.onChange(false);
+ verify(mListener, times(1)).onChanged(SETTINGS_FIELD);
+ }
+
+ @Test
+ public void whenNotifyChangeBasedOnLifecycle_onStopEvent_onChangedNotCalled() {
+ mListener.notifyChangeBasedOn(mLifecycle);
+ mListener.onStart();
+
+ mListener.onChange(false);
+ verify(mListener, times(1)).onChanged(SETTINGS_FIELD);
+
+ mListener.onStop();
+
+ mListener.onChange(false);
+ verify(mListener, times(1)).onChanged(SETTINGS_FIELD);
+
+ mListener.onStart();
+
+ mListener.onChange(false);
+ verify(mListener, times(2)).onChanged(SETTINGS_FIELD);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
index 51f8ec0..6fd94c3 100644
--- a/tests/robotests/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
@@ -29,6 +29,7 @@
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -63,6 +64,7 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowSubscriptionManager;
@@ -107,7 +109,7 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mContext = spy(Robolectric.setupActivity(Activity.class));
+ mContext = spy(RuntimeEnvironment.application);
mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner);
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
@@ -257,14 +259,14 @@
*/
private void runPreferenceClickTest(final int subscriptionCount, final int selectedPrefIndex) {
final List<SubscriptionInfo> subs = setupMockSubscriptions(subscriptionCount);
- mController.displayPreference(mScreen);
final ArgumentCaptor<Preference> prefCaptor = ArgumentCaptor.forClass(Preference.class);
+ mController.displayPreference(mScreen);
verify(mPreferenceCategory, times(subscriptionCount)).addPreference(prefCaptor.capture());
final List<Preference> prefs = prefCaptor.getAllValues();
final Preference pref = prefs.get(selectedPrefIndex);
- pref.getOnPreferenceClickListener().onPreferenceClick(pref);
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
- verify(mContext).startActivity(intentCaptor.capture());
+ doNothing().when(mContext).startActivity(intentCaptor.capture());
+ pref.getOnPreferenceClickListener().onPreferenceClick(pref);
final Intent intent = intentCaptor.getValue();
assertThat(intent).isNotNull();
assertThat(intent.hasExtra(Settings.EXTRA_SUB_ID)).isTrue();
diff --git a/tests/robotests/src/com/android/settings/network/telephony/ApnPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/ApnPreferenceControllerTest.java
index ce4c9a2..d362837 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/ApnPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/ApnPreferenceControllerTest.java
@@ -21,6 +21,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -47,6 +48,7 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class ApnPreferenceControllerTest {
@@ -69,7 +71,7 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
- mContext = spy(Robolectric.setupActivity(Activity.class));
+ mContext = spy(RuntimeEnvironment.application);
doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
doReturn(mSubscriptionManager).when(mContext).getSystemService(SubscriptionManager.class);
doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
@@ -138,10 +140,10 @@
@Test
public void handPreferenceTreeClick_fireIntent() {
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+ doNothing().when(mContext).startActivity(captor.capture());
mController.handlePreferenceTreeClick(mPreference);
- verify(mContext).startActivity(captor.capture());
final Intent intent = captor.getValue();
assertThat(intent.getAction()).isEqualTo(Settings.ACTION_APN_SETTINGS);
assertThat(intent.getIntExtra(ApnSettings.SUB_ID, 0)).isEqualTo(SUB_ID);
diff --git a/tests/robotests/src/com/android/settings/network/telephony/DataServiceSetupPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/DataServiceSetupPreferenceControllerTest.java
index 8907164..46e6978 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/DataServiceSetupPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/DataServiceSetupPreferenceControllerTest.java
@@ -21,6 +21,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -49,6 +50,7 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class DataServiceSetupPreferenceControllerTest {
@@ -72,7 +74,7 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
- mContext = spy(Robolectric.setupActivity(Activity.class));
+ mContext = spy(RuntimeEnvironment.application);
doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId(
@@ -125,11 +127,10 @@
@Test
public void handlePreferenceTreeClick_startActivity() {
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+ doNothing().when(mContext).startActivity(captor.capture());
mController.handlePreferenceTreeClick(mPreference);
- verify(mContext).startActivity(captor.capture());
-
final Intent intent = captor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
assertThat(intent.getData()).isEqualTo(
diff --git a/tests/robotests/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.java
index 7a097e7..7681f44 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.java
@@ -17,6 +17,7 @@
package com.android.settings.network.telephony;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -40,6 +41,7 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowTelephonyManager;
import org.robolectric.util.ReflectionHelpers;
@@ -58,7 +60,7 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
- mContext = spy(Robolectric.setupActivity(Activity.class));
+ mContext = spy(RuntimeEnvironment.application);
final TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
final ShadowTelephonyManager shadowTelephonyManager = Shadows.shadowOf(telephonyManager);
@@ -91,9 +93,10 @@
@Test
public void handlePreferenceTreeClick_needDialog_showDialog() {
final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+ doNothing().when(mContext).startActivity(captor.capture());
+
mController.handlePreferenceTreeClick(mPreference);
- verify(mContext).startActivity(captor.capture());
final Intent intent = captor.getValue();
assertThat(intent.getAction()).isEqualTo(Settings.ACTION_MOBILE_DATA_USAGE);
diff --git a/tests/robotests/src/com/android/settings/network/telephony/EuiccPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/EuiccPreferenceControllerTest.java
index 7fbddb4..bb60fd6 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/EuiccPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/EuiccPreferenceControllerTest.java
@@ -18,33 +18,32 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
+import static org.robolectric.Shadows.shadowOf;
-import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.telephony.euicc.EuiccManager;
import androidx.preference.Preference;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowTelephonyManager;
-@RunWith(RobolectricTestRunner.class)
+@RunWith(AndroidJUnit4.class)
public class EuiccPreferenceControllerTest {
private static final int SUB_ID = 2;
- @Mock
private TelephonyManager mTelephonyManager;
+ private ShadowTelephonyManager mShadowTelephonyManager;
private EuiccPreferenceController mController;
private Preference mPreference;
@@ -54,9 +53,11 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
- mContext = spy(Robolectric.setupActivity(Activity.class));
- doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
- doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+ mContext = spy(RuntimeEnvironment.application.getBaseContext());
+
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+ mShadowTelephonyManager = shadowOf(mTelephonyManager);
+ mShadowTelephonyManager.setTelephonyManagerForSubscriptionId(SUB_ID, mTelephonyManager);
mPreference = new Preference(mContext);
mController = new EuiccPreferenceController(mContext, "euicc");
@@ -67,10 +68,10 @@
@Test
public void handlePreferenceTreeClick_startActivity() {
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+ doNothing().when(mContext).startActivity(captor.capture());
mController.handlePreferenceTreeClick(mPreference);
- verify(mContext).startActivity(captor.capture());
assertThat(captor.getValue().getAction()).isEqualTo(
EuiccManager.ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS);
}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
index 86f2355..1a11c49 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
@@ -99,7 +99,7 @@
doReturn(true).when(mTelephonyManager).isDataEnabled();
doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID);
doReturn(mSubscriptionInfo).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
- doReturn(1).when(mTelephonyManager).getSimCount();
+ doReturn(1).when(mTelephonyManager).getActiveModemCount();
assertThat(mController.isDialogNeeded()).isFalse();
}
@@ -110,7 +110,7 @@
doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID);
doReturn(true).when(mSubscriptionManager).isActiveSubscriptionId(SUB_ID_OTHER);
ShadowSubscriptionManager.setDefaultDataSubscriptionId(SUB_ID_OTHER);
- doReturn(2).when(mTelephonyManager).getSimCount();
+ doReturn(2).when(mTelephonyManager).getActiveModemCount();
assertThat(mController.isDialogNeeded()).isTrue();
assertThat(mController.mDialogType).isEqualTo(
@@ -131,7 +131,7 @@
doReturn(true).when(mTelephonyManager).isDataEnabled();
doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID);
doReturn(mSubscriptionInfo).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
- doReturn(1).when(mTelephonyManager).getSimCount();
+ doReturn(1).when(mTelephonyManager).getActiveModemCount();
mController.onPreferenceChange(mPreference, true);
@@ -143,7 +143,7 @@
doReturn(true).when(mTelephonyManager).isDataEnabled();
doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID);
doReturn(mSubscriptionInfo).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
- doReturn(2).when(mTelephonyManager).getSimCount();
+ doReturn(2).when(mTelephonyManager).getActiveModemCount();
mController.onPreferenceChange(mPreference, true);
diff --git a/tests/robotests/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragmentTest.java b/tests/robotests/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragmentTest.java
index 53b4f00..0d94928 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragmentTest.java
@@ -86,7 +86,8 @@
final ServiceState serviceState = mock(ServiceState.class);
when(serviceState.getOperatorAlphaLong()).thenReturn("fake carrier name");
- when(mTelephonyMgr.getServiceStateForSubscriber(mSubscriptionId)).thenReturn(serviceState);
+ when(mTelephonyMgr.createForSubscriptionId(anyInt())).thenReturn(mTelephonyMgr);
+ when(mTelephonyMgr.getServiceState()).thenReturn(serviceState);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java
index a883c51..0abd6d5 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java
@@ -80,7 +80,7 @@
doReturn(mFragmentTransaction).when(mFragmentManager).beginTransaction();
mPreference = spy(new RestrictedSwitchPreference(mContext));
- mController = new RoamingPreferenceController(mContext, "roaming");
+ mController = spy(new RoamingPreferenceController(mContext, "roaming"));
mController.init(mFragmentManager, SUB_ID);
mPreference.setKey(mController.getPreferenceKey());
}
@@ -118,7 +118,7 @@
@Test
public void handlePreferenceTreeClick_needDialog_showDialog() {
- mController.mNeedDialog = true;
+ doReturn(true).when(mController).isDialogNeeded();
mController.handlePreferenceTreeClick(mPreference);
diff --git a/tests/robotests/src/com/android/settings/panel/SettingsPanelActivityTest.java b/tests/robotests/src/com/android/settings/panel/SettingsPanelActivityTest.java
index 8ad2156..a4b7aa5 100644
--- a/tests/robotests/src/com/android/settings/panel/SettingsPanelActivityTest.java
+++ b/tests/robotests/src/com/android/settings/panel/SettingsPanelActivityTest.java
@@ -16,6 +16,8 @@
package com.android.settings.panel;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
import static com.android.settings.panel.SettingsPanelActivity.KEY_MEDIA_PACKAGE_NAME;
import static com.android.settings.panel.SettingsPanelActivity.KEY_PANEL_TYPE_ARGUMENT;
@@ -28,17 +30,23 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.app.settings.SettingsEnums;
import android.content.Intent;
-import android.view.MotionEvent;
+import android.os.Build;
+import android.view.Window;
+import android.view.WindowManager;
+import com.android.settings.core.HideNonSystemOverlayMixin;
import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.android.controller.ActivityController;
+import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
public class SettingsPanelActivityTest {
@@ -50,6 +58,7 @@
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
mSettingsPanelActivity = spy(
Robolectric.buildActivity(FakeSettingsPanelActivity.class).create().get());
@@ -87,4 +96,47 @@
assertThat(activity.mBundle.getString(KEY_PANEL_TYPE_ARGUMENT))
.isEqualTo("com.android.settings.panel.action.MEDIA_OUTPUT");
}
+
+ @Test
+ public void onStart_isNotDebuggable_shouldHideSystemOverlay() {
+ ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", false);
+
+ final ActivityController<SettingsPanelActivity> activityController =
+ Robolectric.buildActivity(SettingsPanelActivity.class).create();
+ final SettingsPanelActivity activity = spy(activityController.get());
+ final Window window = mock(Window.class);
+ when(activity.getWindow()).thenReturn(window);
+ activity.getLifecycle().addObserver(new HideNonSystemOverlayMixin(activity));
+
+ activityController.start();
+
+ verify(window).addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+ }
+
+ @Test
+ public void onStop_isNotDebuggable_shouldRemoveHideSystemOverlay() {
+ ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", false);
+
+ final ActivityController<SettingsPanelActivity> activityController =
+ Robolectric.buildActivity(SettingsPanelActivity.class).create();
+ final SettingsPanelActivity activity = spy(activityController.get());
+ final Window window = mock(Window.class);
+ when(activity.getWindow()).thenReturn(window);
+ activity.getLifecycle().addObserver(new HideNonSystemOverlayMixin(activity));
+
+ activityController.start();
+
+ verify(window).addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+
+ final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
+ when(window.getAttributes()).thenReturn(layoutParams);
+
+ activityController.stop();
+ final ArgumentCaptor<WindowManager.LayoutParams> paramCaptor = ArgumentCaptor.forClass(
+ WindowManager.LayoutParams.class);
+
+ verify(window).setAttributes(paramCaptor.capture());
+ assertThat(paramCaptor.getValue().privateFlags
+ & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS).isEqualTo(0);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/privacy/PermissionBarChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/privacy/PermissionBarChartPreferenceControllerTest.java
deleted file mode 100644
index 1335db5..0000000
--- a/tests/robotests/src/com/android/settings/privacy/PermissionBarChartPreferenceControllerTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2019 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.settings.privacy;
-
-import static android.Manifest.permission_group.CALENDAR;
-import static android.Manifest.permission_group.CAMERA;
-import static android.Manifest.permission_group.CONTACTS;
-import static android.Manifest.permission_group.LOCATION;
-import static android.Manifest.permission_group.MICROPHONE;
-import static android.Manifest.permission_group.PHONE;
-import static android.Manifest.permission_group.SMS;
-
-import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
-import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-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 android.content.Context;
-import android.content.pm.UserInfo;
-import android.os.UserManager;
-import android.permission.RuntimePermissionUsageInfo;
-import android.provider.DeviceConfig;
-import android.view.accessibility.AccessibilityManager;
-
-import androidx.preference.PreferenceScreen;
-
-import com.android.internal.widget.LockPatternUtils;
-import com.android.settings.Utils;
-import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settings.testutils.shadow.ShadowDeviceConfig;
-import com.android.settings.testutils.shadow.ShadowPermissionControllerManager;
-import com.android.settings.testutils.shadow.ShadowUserManager;
-import com.android.settingslib.widget.BarChartInfo;
-import com.android.settingslib.widget.BarChartPreference;
-import com.android.settingslib.widget.BarViewInfo;
-
-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.annotation.Config;
-import org.robolectric.shadow.api.Shadow;
-import org.robolectric.shadows.ShadowAccessibilityManager;
-import org.robolectric.shadows.androidx.fragment.FragmentController;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(RobolectricTestRunner.class)
-@Config(shadows = {ShadowDeviceConfig.class, ShadowUserManager.class,
- ShadowPermissionControllerManager.class})
-public class PermissionBarChartPreferenceControllerTest {
-
- @Mock
- private PreferenceScreen mScreen;
- @Mock
- private LockPatternUtils mLockPatternUtils;
-
- private PermissionBarChartPreferenceController mController;
- private BarChartPreference mPreference;
- private PrivacyDashboardFragment mFragment;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- final Context context = RuntimeEnvironment.application;
- final UserManager userManager = context.getSystemService(UserManager.class);
- final ShadowUserManager shadowUserManager = Shadow.extract(userManager);
- final ShadowAccessibilityManager accessibilityManager = Shadow.extract(
- AccessibilityManager.getInstance(context));
- accessibilityManager.setEnabledAccessibilityServiceList(new ArrayList<>());
- shadowUserManager.addProfile(new UserInfo(123, null, 0));
- when(FakeFeatureFactory.setupForTest().securityFeatureProvider.getLockPatternUtils(
- any(Context.class))).thenReturn(mLockPatternUtils);
-
- mController = spy(new PermissionBarChartPreferenceController(context, "test_key"));
- mFragment = spy(FragmentController.of(new PrivacyDashboardFragment())
- .create().start().get());
- mController.setFragment(mFragment);
- mPreference = spy(new BarChartPreference(context));
- when(mScreen.findPreference(mController.getPreferenceKey()))
- .thenReturn((BarChartPreference) mPreference);
- }
-
- @After
- public void tearDown() {
- ShadowDeviceConfig.reset();
- }
-
- @Test
- public void getAvailabilityStatus_permissionHubNotSet_shouldReturnUnsupported() {
- // We have not yet set the property to show the Permissions Hub.
- assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
- }
-}
diff --git a/tests/robotests/src/com/android/settings/privacy/PrivacyDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/privacy/PrivacyDashboardFragmentTest.java
deleted file mode 100644
index 80f3900..0000000
--- a/tests/robotests/src/com/android/settings/privacy/PrivacyDashboardFragmentTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2019 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.settings.privacy;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.pm.UserInfo;
-import android.os.Bundle;
-import android.os.UserManager;
-import android.permission.PermissionControllerManager;
-import android.view.View;
-import android.view.accessibility.AccessibilityManager;
-
-import com.android.internal.widget.LockPatternUtils;
-import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settings.testutils.shadow.ShadowPermissionControllerManager;
-import com.android.settings.testutils.shadow.ShadowUserManager;
-
-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.annotation.Config;
-import org.robolectric.shadow.api.Shadow;
-import org.robolectric.shadows.ShadowAccessibilityManager;
-import org.robolectric.shadows.androidx.fragment.FragmentController;
-
-import java.util.ArrayList;
-
-
-@RunWith(RobolectricTestRunner.class)
-@Config(shadows = {ShadowUserManager.class, ShadowPermissionControllerManager.class})
-public class PrivacyDashboardFragmentTest {
-
- @Mock
- private LockPatternUtils mLockPatternUtils;
- @Mock
- private PermissionControllerManager mPCM;
-
- private Context mContext;
- private PrivacyDashboardFragment mFragment;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mContext = RuntimeEnvironment.application;
- final UserManager userManager = mContext.getSystemService(UserManager.class);
- final ShadowUserManager shadowUserManager = Shadow.extract(userManager);
- final ShadowAccessibilityManager accessibilityManager = Shadow.extract(
- AccessibilityManager.getInstance(mContext));
- accessibilityManager.setEnabledAccessibilityServiceList(new ArrayList<>());
- shadowUserManager.addProfile(new UserInfo(123, null, 0));
- when(FakeFeatureFactory.setupForTest().securityFeatureProvider.getLockPatternUtils(
- any(Context.class))).thenReturn(mLockPatternUtils);
- mFragment = spy(FragmentController.of(new PrivacyDashboardFragment())
- .create().start().get());
- }
-
- @Test
- public void onViewCreated_shouldSetActionBarShadowAnimation() {
- mFragment.onViewCreated(new View(mContext), new Bundle());
-
- assertThat(mFragment.getActivity().getActionBar().getElevation()).isEqualTo(0.f);
- }
-
- @Test
- public void onViewCreated_shouldInitLinearProgressBar() {
- mFragment.onViewCreated(new View(mContext), new Bundle());
-
- verify(mFragment).initLoadingBar();
- }
-
- @Test
- public void updateLinearProgressbar_isVisible_shouldShowProgressBar() {
- mFragment.setLoadingEnabled(true /* enabled */);
-
- assertThat(mFragment.mProgressHeader.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mFragment.mProgressAnimation.getVisibility()).isEqualTo(View.VISIBLE);
- }
-
- @Test
- public void updateLinearProgressbar_isInVisible_shouldHideProgressBar() {
- mFragment.setLoadingEnabled(false /* enabled */);
-
- assertThat(mFragment.mProgressHeader.getVisibility()).isEqualTo(View.INVISIBLE);
- assertThat(mFragment.mProgressAnimation.getVisibility()).isEqualTo(View.INVISIBLE);
- }
-}