Merge "Fix crash when there is no emergencybroadcast app on device" into oc-dev
diff --git a/res/layout/enable_accessibility_service_dialog_content.xml b/res/layout/enable_accessibility_service_dialog_content.xml
index 3ca40ac..f212eb1 100644
--- a/res/layout/enable_accessibility_service_dialog_content.xml
+++ b/res/layout/enable_accessibility_service_dialog_content.xml
@@ -18,6 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
+ android:textDirection="locale"
android:scrollbarStyle="outsideOverlay"
android:gravity="top">
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 58703a5..28c6b4b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4304,6 +4304,11 @@
can't verify user consent. [CHAR LIMIT=NONE] -->
<string name="touch_filtered_warning">Because an app is obscuring a permission request, Settings
can’t verify your response.</string>
+ <!-- Warning shown when user input has been blocked due to another app overlaying screen
+ content. Since we don't know what the app is showing on top of the input target, we
+ can't verify user consent. [CHAR LIMIT=NONE] -->
+ <string name="window_obscured_warning">Because another app is displaying on top of these options,
+ Settings can\u2019t respond to your action.</string>
<!-- Warning that the device data will not be encrypted with password or PIN if
enabling an accessibility service and there is a secure lock setup. [CHAR LIMIT=NONE] -->
<string name="enable_service_encryption_warning">If you turn on <xliff:g id="service"
diff --git a/src/com/android/settings/DeviceAdminAdd.java b/src/com/android/settings/DeviceAdminAdd.java
index fb2f29f..3bb82cf 100644
--- a/src/com/android/settings/DeviceAdminAdd.java
+++ b/src/com/android/settings/DeviceAdminAdd.java
@@ -65,6 +65,8 @@
import com.android.settings.users.UserDialogs;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.SecureTouchListener;
+
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
@@ -350,6 +352,8 @@
final View restrictedAction = findViewById(R.id.restricted_action);
restrictedAction.setFilterTouchesWhenObscured(true);
+ restrictedAction.setOnTouchListener(
+ new SecureTouchListener(getString(R.string.window_obscured_warning)));
restrictedAction.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (mAdding) {
diff --git a/src/com/android/settings/accessibility/AccessibilityServiceWarning.java b/src/com/android/settings/accessibility/AccessibilityServiceWarning.java
index 9f89bc1..e0c58db 100644
--- a/src/com/android/settings/accessibility/AccessibilityServiceWarning.java
+++ b/src/com/android/settings/accessibility/AccessibilityServiceWarning.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.content.DialogInterface;
import android.os.storage.StorageManager;
+import android.text.BidiFormatter;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -34,6 +35,7 @@
import com.android.settings.R;
import java.util.List;
+import java.util.Locale;
/**
* Utility class for creating the dialog that asks users for explicit permission to grant
@@ -44,7 +46,7 @@
AccessibilityServiceInfo info, DialogInterface.OnClickListener listener) {
final AlertDialog ad = new AlertDialog.Builder(parentActivity)
.setTitle(parentActivity.getString(R.string.enable_service_title,
- info.getResolveInfo().loadLabel(parentActivity.getPackageManager())))
+ getServiceName(parentActivity, info)))
.setView(createEnableDialogContentView(parentActivity, info))
.setCancelable(true)
.setPositiveButton(android.R.string.ok, listener)
@@ -97,7 +99,7 @@
R.id.encryption_warning);
if (isFullDiskEncrypted()) {
String text = context.getString(R.string.enable_service_encryption_warning,
- info.getResolveInfo().loadLabel(context.getPackageManager()));
+ getServiceName(context, info));
encryptionWarningView.setText(text);
encryptionWarningView.setVisibility(View.VISIBLE);
} else {
@@ -107,7 +109,7 @@
TextView capabilitiesHeaderView = (TextView) content.findViewById(
R.id.capabilities_header);
capabilitiesHeaderView.setText(context.getString(R.string.capabilities_list_title,
- info.getResolveInfo().loadLabel(context.getPackageManager())));
+ getServiceName(context, info)));
LinearLayout capabilitiesView = (LinearLayout) content.findViewById(R.id.capabilities);
@@ -161,4 +163,12 @@
return content;
}
+
+ // Get the service name and bidi wrap it to protect from bidi side effects.
+ private static CharSequence getServiceName(Context context, AccessibilityServiceInfo info) {
+ final Locale locale = context.getResources().getConfiguration().getLocales().get(0);
+ final CharSequence label =
+ info.getResolveInfo().loadLabel(context.getPackageManager());
+ return BidiFormatter.getInstance(locale).unicodeWrap(label);
+ }
}
diff --git a/src/com/android/settings/applications/AppCounter.java b/src/com/android/settings/applications/AppCounter.java
index 8758b14..8eff526 100644
--- a/src/com/android/settings/applications/AppCounter.java
+++ b/src/com/android/settings/applications/AppCounter.java
@@ -32,7 +32,7 @@
public AppCounter(Context context, PackageManagerWrapper packageManager) {
mPm = packageManager;
- mUm = UserManager.get(context);
+ mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
}
@Override
diff --git a/src/com/android/settings/applications/AppStateAppOpsBridge.java b/src/com/android/settings/applications/AppStateAppOpsBridge.java
index cfbb2fc..420d955 100644
--- a/src/com/android/settings/applications/AppStateAppOpsBridge.java
+++ b/src/com/android/settings/applications/AppStateAppOpsBridge.java
@@ -19,12 +19,12 @@
import android.app.AppOpsManager;
import android.app.AppOpsManager.PackageOps;
import android.content.Context;
-import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.support.annotation.VisibleForTesting;
import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseArray;
@@ -46,7 +46,7 @@
private static final String TAG = "AppStateAppOpsBridge";
- private final IPackageManager mIPackageManager;
+ private final IPackageManagerWrapper mIPackageManager;
private final UserManager mUserManager;
private final List<UserHandle> mProfiles;
private final AppOpsManager mAppOpsManager;
@@ -56,9 +56,16 @@
public AppStateAppOpsBridge(Context context, ApplicationsState appState, Callback callback,
int appOpsOpCode, String[] permissions) {
+ this(context, appState, callback, appOpsOpCode, permissions,
+ new IPackageManagerWrapperImpl(AppGlobals.getPackageManager()));
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+ AppStateAppOpsBridge(Context context, ApplicationsState appState, Callback callback,
+ int appOpsOpCode, String[] permissions, IPackageManagerWrapper packageManager) {
super(appState, callback);
mContext = context;
- mIPackageManager = AppGlobals.getPackageManager();
+ mIPackageManager = packageManager;
mUserManager = UserManager.get(context);
mProfiles = mUserManager.getUserProfiles();
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
@@ -92,18 +99,21 @@
.getUserId(uid)));
try {
permissionState.packageInfo = mIPackageManager.getPackageInfo(pkg,
- PackageManager.GET_PERMISSIONS | PackageManager.MATCH_UNINSTALLED_PACKAGES,
+ PackageManager.GET_PERMISSIONS | PackageManager.MATCH_ANY_USER,
permissionState.userHandle.getIdentifier());
- // Check static permission state (whatever that is declared in package manifest)
- String[] requestedPermissions = permissionState.packageInfo.requestedPermissions;
- int[] permissionFlags = permissionState.packageInfo.requestedPermissionsFlags;
- if (requestedPermissions != null) {
- for (int i = 0; i < requestedPermissions.length; i++) {
- if (doesAnyPermissionMatch(requestedPermissions[i], mPermissions)) {
- permissionState.permissionDeclared = true;
- if ((permissionFlags[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0) {
- permissionState.staticPermissionGranted = true;
- break;
+ if (permissionState.packageInfo != null) {
+ // Check static permission state (whatever that is declared in package manifest)
+ String[] requestedPermissions = permissionState.packageInfo.requestedPermissions;
+ int[] permissionFlags = permissionState.packageInfo.requestedPermissionsFlags;
+ if (requestedPermissions != null) {
+ for (int i = 0; i < requestedPermissions.length; i++) {
+ if (doesAnyPermissionMatch(requestedPermissions[i], mPermissions)) {
+ permissionState.permissionDeclared = true;
+ if ((permissionFlags[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED)
+ != 0) {
+ permissionState.staticPermissionGranted = true;
+ break;
+ }
}
}
}
diff --git a/src/com/android/settings/applications/IPackageManagerWrapper.java b/src/com/android/settings/applications/IPackageManagerWrapper.java
index f885985..b4d1b85 100644
--- a/src/com/android/settings/applications/IPackageManagerWrapper.java
+++ b/src/com/android/settings/applications/IPackageManagerWrapper.java
@@ -17,6 +17,8 @@
package com.android.settings.applications;
import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.os.RemoteException;
@@ -41,4 +43,33 @@
* @see android.content.pm.IPackageManager#findPersistentPreferredActivity
*/
ResolveInfo findPersistentPreferredActivity(Intent intent, int userId) throws RemoteException;
+
+ /**
+ * Calls {@code IPackageManager.getPackageInfo()}.
+ *
+ * @see android.content.pm.IPackageManager#getPackageInfo
+ */
+ PackageInfo getPackageInfo(String packageName, int flags, int userId) throws RemoteException;
+
+ /**
+ * Calls {@code IPackageManager.getAppOpPermissionPackages()}.
+ *
+ * @see android.content.pm.IPackageManager#getAppOpPermissionPackages
+ */
+ String[] getAppOpPermissionPackages(String permissionName) throws RemoteException;
+
+ /**
+ * Calls {@code IPackageManager.isPackageAvailable()}.
+ *
+ * @see android.content.pm.IPackageManager#isPackageAvailable
+ */
+ boolean isPackageAvailable(String packageName, int userId) throws RemoteException;
+
+ /**
+ * Calls {@code IPackageManager.getPackagesHoldingPermissions()}.
+ *
+ * @see android.content.pm.IPackageManager#getPackagesHoldingPermissions
+ */
+ ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(
+ String[] permissions, int flags, int userId) throws RemoteException;
}
diff --git a/src/com/android/settings/applications/IPackageManagerWrapperImpl.java b/src/com/android/settings/applications/IPackageManagerWrapperImpl.java
index 5ea15b9..af5f378 100644
--- a/src/com/android/settings/applications/IPackageManagerWrapperImpl.java
+++ b/src/com/android/settings/applications/IPackageManagerWrapperImpl.java
@@ -18,6 +18,8 @@
import android.content.Intent;
import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.os.RemoteException;
@@ -39,4 +41,27 @@
throws RemoteException {
return mPms.findPersistentPreferredActivity(intent, userId);
}
+
+ @Override
+ public PackageInfo getPackageInfo(String packageName, int flags, int userId)
+ throws RemoteException {
+ return mPms.getPackageInfo(packageName, flags, userId);
+ }
+
+ @Override
+ public String[] getAppOpPermissionPackages(String permissionName) throws RemoteException {
+ return mPms.getAppOpPermissionPackages(permissionName);
+ }
+
+ @Override
+ public boolean isPackageAvailable(String packageName, int userId) throws RemoteException {
+ return mPms.isPackageAvailable(packageName, userId);
+ }
+
+ @Override
+ public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(
+ String[] permissions, int flags, int userId) throws RemoteException {
+ return mPms.getPackagesHoldingPermissions(permissions, flags, userId);
+ }
+
}
diff --git a/src/com/android/settings/applications/RunningState.java b/src/com/android/settings/applications/RunningState.java
index dd44887..d4abe6c 100644
--- a/src/com/android/settings/applications/RunningState.java
+++ b/src/com/android/settings/applications/RunningState.java
@@ -500,7 +500,7 @@
si.mRunningService = service;
try {
si.mServiceInfo = ActivityThread.getPackageManager().getServiceInfo(
- service.service, PackageManager.MATCH_UNINSTALLED_PACKAGES,
+ service.service, PackageManager.MATCH_ANY_USER,
UserHandle.getUserId(service.uid));
if (si.mServiceInfo == null) {
diff --git a/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java b/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
index 6c23b39..69f174b 100644
--- a/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
+++ b/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
@@ -144,7 +144,7 @@
} catch (Exception e) {
}
try {
- pm.getPackageInfo(value, PackageManager.MATCH_UNINSTALLED_PACKAGES);
+ pm.getPackageInfo(value, PackageManager.MATCH_ANY_USER);
logPackageName(key, value);
} catch (PackageManager.NameNotFoundException e) {
// Clearly not a package, and it's unlikely this preference is in prefSet, so
diff --git a/src/com/android/settings/network/TetherPreferenceController.java b/src/com/android/settings/network/TetherPreferenceController.java
index f23118a..19a22ba 100644
--- a/src/com/android/settings/network/TetherPreferenceController.java
+++ b/src/com/android/settings/network/TetherPreferenceController.java
@@ -19,8 +19,12 @@
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
+import android.database.ContentObserver;
import android.net.ConnectivityManager;
+import android.net.Uri;
+import android.os.Handler;
import android.os.UserHandle;
+import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
@@ -31,6 +35,8 @@
import com.android.settings.core.lifecycle.Lifecycle;
import com.android.settings.core.lifecycle.LifecycleObserver;
import com.android.settings.core.lifecycle.events.OnDestroy;
+import com.android.settings.core.lifecycle.events.OnPause;
+import com.android.settings.core.lifecycle.events.OnResume;
import java.util.concurrent.atomic.AtomicReference;
@@ -39,7 +45,7 @@
import static com.android.settingslib.RestrictedLockUtils.hasBaseUserRestriction;
public class TetherPreferenceController extends PreferenceController
- implements LifecycleObserver, OnDestroy {
+ implements LifecycleObserver, OnResume, OnPause, OnDestroy {
private static final String KEY_TETHER_SETTINGS = "tether_settings";
@@ -47,7 +53,6 @@
private final AtomicReference<BluetoothPan> mBluetoothPan;
private final ConnectivityManager mConnectivityManager;
private final BluetoothAdapter mBluetoothAdapter;
-
private final BluetoothProfile.ServiceListener mBtProfileServiceListener =
new android.bluetooth.BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
@@ -60,6 +65,7 @@
}
};
+ private SettingObserver mAirplaneModeObserver;
private Preference mPreference;
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
@@ -121,6 +127,22 @@
}
@Override
+ public void onResume() {
+ if (mAirplaneModeObserver == null) {
+ mAirplaneModeObserver = new SettingObserver();
+ }
+ mContext.getContentResolver()
+ .registerContentObserver(mAirplaneModeObserver.uri, false, mAirplaneModeObserver);
+ }
+
+ @Override
+ public void onPause() {
+ if (mAirplaneModeObserver != null) {
+ mContext.getContentResolver().unregisterContentObserver(mAirplaneModeObserver);
+ }
+ }
+
+ @Override
public void onDestroy() {
final BluetoothProfile profile = mBluetoothPan.getAndSet(null);
if (profile != null && mBluetoothAdapter != null) {
@@ -128,7 +150,7 @@
}
}
- @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ @VisibleForTesting
void updateSummary() {
if (mPreference == null) {
// Preference is not ready yet.
@@ -183,4 +205,37 @@
mPreference.setSummary(R.string.tether_settings_summary_hotspot_off_tether_on);
}
}
+
+ private void updateSummaryToOff() {
+ if (mPreference == null) {
+ // Preference is not ready yet.
+ return;
+ }
+ mPreference.setSummary(R.string.switch_off_text);
+ }
+
+ class SettingObserver extends ContentObserver {
+
+ public final Uri uri;
+
+ public SettingObserver() {
+ super(new Handler());
+ uri = Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ super.onChange(selfChange, uri);
+ if (this.uri.equals(uri)) {
+ boolean isAirplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
+ if (isAirplaneMode) {
+ // Airplane mode is on. Update summary to say tether is OFF directly. We cannot
+ // go through updateSummary() because turning off tether takes time, and we
+ // might still get "ON" status when rerun updateSummary(). So, just say it's off
+ updateSummaryToOff();
+ }
+ }
+ }
+ }
}
diff --git a/tests/robotests/src/com/android/settings/applications/AppStateAppOpsBridgeTest.java b/tests/robotests/src/com/android/settings/applications/AppStateAppOpsBridgeTest.java
new file mode 100644
index 0000000..f17509a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/AppStateAppOpsBridgeTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2017 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.applications;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.when;
+
+import android.Manifest;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.UserManager;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public final class AppStateAppOpsBridgeTest {
+
+ @Mock private Context mContext;
+ @Mock private UserManager mUserManager;
+ @Mock private IPackageManagerWrapper mPackageManagerService;
+ @Mock private AppOpsManager mAppOpsManager;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+ when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
+ }
+
+ @Test
+ public void getPermissionInfo_nullPackageInfo_shouldNotCrash() throws RemoteException {
+ when(mPackageManagerService.getPackageInfo(anyString(), anyInt(), anyInt()))
+ .thenReturn(null);
+ TestAppStateAppOpsBridge appStateAppOpsBridge = new TestAppStateAppOpsBridge();
+
+ appStateAppOpsBridge.getPermissionInfo("pkg1", 1);
+ // should not crash
+ }
+
+ private class TestAppStateAppOpsBridge extends AppStateAppOpsBridge {
+ public TestAppStateAppOpsBridge() {
+ super(mContext, null, null, AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
+ new String[] {Manifest.permission.SYSTEM_ALERT_WINDOW},
+ mPackageManagerService);
+ }
+
+ @Override
+ protected void updateExtraInfo(AppEntry app, String pkg, int uid) {
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java
index 6f751eb..7e92bc5 100644
--- a/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java
@@ -21,7 +21,9 @@
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
+import android.database.ContentObserver;
import android.net.ConnectivityManager;
+import android.provider.Settings;
import android.support.v7.preference.Preference;
import com.android.settings.R;
@@ -33,6 +35,7 @@
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
@@ -42,6 +45,7 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
@RunWith(SettingsRobolectricTestRunner.class)
@@ -66,6 +70,7 @@
ReflectionHelpers.setField(mController, "mContext", mContext);
ReflectionHelpers.setField(mController, "mConnectivityManager", mConnectivityManager);
ReflectionHelpers.setField(mController, "mBluetoothAdapter", mBluetoothAdapter);
+ ReflectionHelpers.setField(mController, "mPreference", mPreference);
}
@Test
@@ -82,13 +87,13 @@
@Test
public void updateSummary_noPreference_noInteractionWithConnectivityManager() {
+ ReflectionHelpers.setField(mController, "mPreference", null);
mController.updateSummary();
verifyNoMoreInteractions(mConnectivityManager);
}
@Test
public void updateSummary_wifiTethered_shouldShowHotspotMessage() {
- ReflectionHelpers.setField(mController, "mPreference", mPreference);
when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[]{"123"});
when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"123"});
@@ -98,7 +103,6 @@
@Test
public void updateSummary_btThetherOn_shouldShowTetherMessage() {
- ReflectionHelpers.setField(mController, "mPreference", mPreference);
when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[]{"123"});
when(mConnectivityManager.getTetherableBluetoothRegexs()).thenReturn(new String[]{"123"});
@@ -108,7 +112,6 @@
@Test
public void updateSummary_tetherOff_shouldShowTetherOffMessage() {
- ReflectionHelpers.setField(mController, "mPreference", mPreference);
when(mConnectivityManager.getTetherableBluetoothRegexs()).thenReturn(new String[]{"123"});
when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"456"});
@@ -118,7 +121,6 @@
@Test
public void updateSummary_wifiBtTetherOn_shouldShowHotspotAndTetherMessage() {
- ReflectionHelpers.setField(mController, "mPreference", mPreference);
when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[]{"123", "456"});
when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"456"});
when(mConnectivityManager.getTetherableBluetoothRegexs()).thenReturn(new String[]{"23"});
@@ -127,4 +129,25 @@
verify(mPreference).setSummary(R.string.tether_settings_summary_hotspot_on_tether_on);
}
+ @Test
+ public void airplaneModeOn_shouldUpdateSummaryToOff() {
+ ReflectionHelpers.setField(mController, "mContext", RuntimeEnvironment.application);
+
+ Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_ON, 0);
+
+ mController.onResume();
+
+ verifyZeroInteractions(mPreference);
+
+ Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_ON, 1);
+
+ final ContentObserver observer = ReflectionHelpers.getField(mController,
+ "mAirplaneModeObserver");
+ observer.onChange(true, Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON));
+
+ verify(mPreference).setSummary(R.string.switch_off_text);
+ }
+
}