diff --git a/res/values/strings.xml b/res/values/strings.xml
index d8c0d377b1e..cbb5e3be3ad 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -9458,6 +9458,11 @@
Contact search
Allow contact searches by your organization to identify callers and contacts
+
+ Cross-profile calendar
+
+ Show work events on personal calendar
+
@@ -10245,15 +10250,13 @@
Scan again
-
-
+
+
- %1$d device connected
- %1$d devices connected
-
- Bluetooth Devices
-
- No connected devices
+
+ No Bluetooth devices
Settings Panel
diff --git a/res/xml/managed_profile_settings.xml b/res/xml/managed_profile_settings.xml
index ee1e4fadec3..bd44cc1a307 100644
--- a/res/xml/managed_profile_settings.xml
+++ b/res/xml/managed_profile_settings.xml
@@ -32,4 +32,11 @@
settings:useAdditionalSummary="true"
settings:controller="com.android.settings.accounts.ContactSearchPreferenceController"/>
+
+
\ No newline at end of file
diff --git a/src/com/android/settings/CryptKeeper.java b/src/com/android/settings/CryptKeeper.java
index ca54b07dcd5..05054b4a55d 100644
--- a/src/com/android/settings/CryptKeeper.java
+++ b/src/com/android/settings/CryptKeeper.java
@@ -772,9 +772,10 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
if (imeSwitcher != null && hasMultipleEnabledIMEsOrSubtypes(imm, false)) {
imeSwitcher.setVisibility(View.VISIBLE);
imeSwitcher.setOnClickListener(new OnClickListener() {
- @Override
+ @Override
public void onClick(View v) {
- imm.showInputMethodPicker(false /* showAuxiliarySubtypes */);
+ imm.showInputMethodPickerFromSystem(false /* showAuxiliarySubtypes */,
+ v.getDisplay().getDisplayId());
}
});
}
diff --git a/src/com/android/settings/accounts/CrossProfileCalendarPreferenceController.java b/src/com/android/settings/accounts/CrossProfileCalendarPreferenceController.java
new file mode 100644
index 00000000000..38c95dcc7ad
--- /dev/null
+++ b/src/com/android/settings/accounts/CrossProfileCalendarPreferenceController.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2018 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.accounts;
+
+import static android.provider.Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.slices.SliceData;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+import androidx.preference.Preference;
+
+public class CrossProfileCalendarPreferenceController extends TogglePreferenceController {
+
+ private UserHandle mManagedUser;
+
+ public CrossProfileCalendarPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ public void setManagedUser(UserHandle managedUser) {
+ mManagedUser = managedUser;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return (mManagedUser != null) ? AVAILABLE : DISABLED_FOR_USER;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (preference instanceof RestrictedSwitchPreference && mManagedUser != null) {
+ final RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
+ final RestrictedLockUtils.EnforcedAdmin enforcedAdmin =
+ RestrictedLockUtilsInternal.getCrossProfileCalendarEnforcingAdmin(
+ mContext, mManagedUser.getIdentifier());
+ pref.setDisabledByAdmin(enforcedAdmin);
+ }
+ }
+
+ @Override
+ public boolean isChecked() {
+ if (mManagedUser == null) {
+ return false;
+ }
+ return Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ CROSS_PROFILE_CALENDAR_ENABLED, /* default= */ 0,
+ mManagedUser.getIdentifier()) == 1;
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ if (mManagedUser == null) {
+ return false;
+ }
+ final int value = isChecked ? 1 : 0;
+ return Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ CROSS_PROFILE_CALENDAR_ENABLED, value, mManagedUser.getIdentifier());
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/accounts/ManagedProfileSettings.java b/src/com/android/settings/accounts/ManagedProfileSettings.java
index 07e58458983..dccd7f67499 100644
--- a/src/com/android/settings/accounts/ManagedProfileSettings.java
+++ b/src/com/android/settings/accounts/ManagedProfileSettings.java
@@ -23,17 +23,25 @@ import android.content.IntentFilter;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.SearchIndexableResource;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settingslib.search.SearchIndexable;
+
+import java.util.ArrayList;
+import java.util.List;
/**
* Setting page for managed profile.
* FIXME: It currently assumes there is only one managed profile.
*/
+@SearchIndexable
public class ManagedProfileSettings extends DashboardFragment {
private UserManager mUserManager;
@@ -63,6 +71,7 @@ public class ManagedProfileSettings extends DashboardFragment {
}
use(WorkModePreferenceController.class).setManagedUser(mManagedUser);
use(ContactSearchPreferenceController.class).setManagedUser(mManagedUser);
+ use(CrossProfileCalendarPreferenceController.class).setManagedUser(mManagedUser);
}
@Override
@@ -99,6 +108,23 @@ public class ManagedProfileSettings extends DashboardFragment {
return MetricsProto.MetricsEvent.ACCOUNTS_WORK_PROFILE_SETTINGS;
}
+ public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List getXmlResourcesToIndex(Context context,
+ boolean enabled) {
+ final ArrayList result = new ArrayList<>();
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.managed_profile_settings;
+ result.add(sir);
+ return result;
+ }
+ @Override
+ protected boolean isPageSearchEnabled(Context context) {
+ return false;
+ }
+ };
+
private class ManagedProfileBroadcastReceiver extends BroadcastReceiver {
@Override
diff --git a/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java b/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java
index de8902a8ffa..19339cd60ec 100644
--- a/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java
+++ b/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java
@@ -199,20 +199,7 @@ public class BluetoothPermissionActivity extends AlertActivity implements
private void onNegative() {
if (DEBUG) Log.d(TAG, "onNegative");
-
- boolean always = true;
- if (mRequestType == BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS) {
- LocalBluetoothManager bluetoothManager = Utils.getLocalBtManager(this);
- CachedBluetoothDeviceManager cachedDeviceManager =
- bluetoothManager.getCachedDeviceManager();
- CachedBluetoothDevice cachedDevice = cachedDeviceManager.findDevice(mDevice);
- if (cachedDevice == null) {
- cachedDevice = cachedDeviceManager.addDevice(mDevice);
- }
- always = cachedDevice.checkAndIncreaseMessageRejectionCount();
- }
-
- sendReplyIntentToReceiver(false, always);
+ sendReplyIntentToReceiver(false, true);
}
private void sendReplyIntentToReceiver(final boolean allowed, final boolean always) {
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
index 6373519c770..e631d22e216 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
@@ -20,7 +20,7 @@ import static android.app.slice.Slice.HINT_ERROR;
import static androidx.slice.widget.SliceLiveData.SUPPORTED_SPECS;
-import static com.android.settings.slices.CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI;
+import static com.android.settings.slices.CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI;
import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
import android.content.ContentProviderClient;
@@ -196,7 +196,7 @@ public class ContextualCardLoader extends AsyncLoaderCompat
private int getNumberOfLargeCard(List cards) {
return (int) cards.stream()
.filter(card -> card.getSliceUri().equals(WIFI_SLICE_URI)
- || card.getSliceUri().equals(CONNECTED_DEVICE_SLICE_URI))
+ || card.getSliceUri().equals(BLUETOOTH_DEVICES_SLICE_URI))
.count();
}
diff --git a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
index 376bb83606a..d5500fb37e3 100644
--- a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
+++ b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
@@ -40,8 +40,8 @@ public class SettingsContextualCardProvider extends ContextualCardProvider {
.build();
final ContextualCard connectedDeviceCard =
ContextualCard.newBuilder()
- .setSliceUri(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI.toString())
- .setCardName(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI.toString())
+ .setSliceUri(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI.toString())
+ .setCardName(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI.toString())
.setCardCategory(ContextualCard.Category.IMPORTANT)
.build();
final ContextualCard lowStorageCard =
diff --git a/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
similarity index 82%
rename from src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java
rename to src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
index b5d58b6176c..ad8d4a644aa 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
@@ -57,19 +57,12 @@ import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
-/**
- * TODO(b/114807655): Contextual Home Page - Connected Device
- *
- * Show connected device info if one is currently connected. UI for connected device should
- * match Connected Devices > Currently Connected Devices
- *
- * TODO This class will be refactor for Bluetooth connected devices only.
- */
-public class ConnectedDeviceSlice implements CustomSliceable {
+public class BluetoothDevicesSlice implements CustomSliceable {
/**
- * To sort the Bluetooth devices by {@link CachedBluetoothDevice}.
- * Refer compareTo method from {@link com.android.settings.bluetooth.BluetoothDevicePreference}.
+ * TODO(b/114807655): Contextual Home Page - Connected Device
+ * Re-design sorting for new rule:
+ * Sorting rule: Audio Streaming > Last connected > Recently connected.
*/
private static final Comparator COMPARATOR
= Comparator.naturalOrder();
@@ -80,11 +73,11 @@ public class ConnectedDeviceSlice implements CustomSliceable {
*/
private static final int DEFAULT_EXPANDED_ROW_COUNT = 3;
- private static final String TAG = "ConnectedDeviceSlice";
+ private static final String TAG = "BluetoothDevicesSlice";
private final Context mContext;
- public ConnectedDeviceSlice(Context context) {
+ public BluetoothDevicesSlice(Context context) {
mContext = context;
}
@@ -101,38 +94,38 @@ public class ConnectedDeviceSlice implements CustomSliceable {
@Override
public Uri getUri() {
- return CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI;
+ return CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI;
}
@Override
public Slice getSlice() {
final IconCompat icon = IconCompat.createWithResource(mContext,
- R.drawable.ic_homepage_connected_device);
- final CharSequence title = mContext.getText(R.string.bluetooth_connected_devices);
- final CharSequence titleNoConnectedDevices = mContext.getText(
- R.string.no_connected_devices);
+ R.drawable.ic_settings_bluetooth);
+ final CharSequence title = mContext.getText(R.string.bluetooth_devices);
+ final CharSequence titleNoBluetoothDevices = mContext.getText(
+ R.string.no_bluetooth_devices);
final PendingIntent primaryActionIntent = PendingIntent.getActivity(mContext, 0,
getIntent(), 0);
final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryActionIntent, icon,
ListBuilder.ICON_IMAGE, title);
final ListBuilder listBuilder =
- new ListBuilder(mContext, CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI,
+ new ListBuilder(mContext, CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext));
- // Get row builders by connected devices, e.g. Bluetooth.
+ // Get row builders by Bluetooth devices.
final List rows = getBluetoothRowBuilder(primarySliceAction);
- // Return a header with IsError flag, if no connected devices.
+ // Return a header with IsError flag, if no Bluetooth devices.
if (rows.isEmpty()) {
return listBuilder.setHeader(new ListBuilder.HeaderBuilder()
- .setTitle(titleNoConnectedDevices)
+ .setTitle(titleNoBluetoothDevices)
.setPrimaryAction(primarySliceAction))
.setIsError(true)
.build();
}
- // According the number of connected devices to set sub title of header.
+ // According the number of Bluetooth devices to set sub title of header.
listBuilder.setHeader(new ListBuilder.HeaderBuilder()
.setTitle(title)
.setSubtitle(getSubTitle(rows.size()))
@@ -161,7 +154,7 @@ public class ConnectedDeviceSlice implements CustomSliceable {
screenTitle,
MetricsProto.MetricsEvent.SLICE)
.setClassName(mContext.getPackageName(), SubSettings.class.getName())
- .setData(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI);
+ .setData(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI);
}
@Override
@@ -174,25 +167,30 @@ public class ConnectedDeviceSlice implements CustomSliceable {
}
@VisibleForTesting
- List getBluetoothConnectedDevices() {
- final List connectedBluetoothList = new ArrayList<>();
+ List getBluetoothDevices() {
+ final List bluetoothDeviceList = new ArrayList<>();
// If Bluetooth is disable, skip to get the bluetooth devices.
if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) {
- Log.i(TAG, "Cannot get Bluetooth connected devices, Bluetooth is disabled.");
- return connectedBluetoothList;
+ Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is disabled.");
+ return bluetoothDeviceList;
}
// Get the Bluetooth devices from LocalBluetoothManager.
final LocalBluetoothManager bluetoothManager =
com.android.settings.bluetooth.Utils.getLocalBtManager(mContext);
if (bluetoothManager == null) {
- Log.i(TAG, "Cannot get Bluetooth connected devices, Bluetooth is unsupported.");
- return connectedBluetoothList;
+ Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is unsupported.");
+ return bluetoothDeviceList;
}
final Collection cachedDevices =
bluetoothManager.getCachedDeviceManager().getCachedDevicesCopy();
+ /**
+ * TODO(b/114807655): Contextual Home Page - Connected Device
+ * Re-design to get all Bluetooth devices and sort them by new rule:
+ * Sorting rule: Audio Streaming > Last connected > Recently connected.
+ */
// Get connected Bluetooth devices and sort them.
return cachedDevices.stream().filter(device -> device.isConnected()).sorted(
COMPARATOR).collect(Collectors.toList());
@@ -217,25 +215,29 @@ public class ConnectedDeviceSlice implements CustomSliceable {
}
@VisibleForTesting
- IconCompat getConnectedDeviceIcon(CachedBluetoothDevice device) {
+ IconCompat getBluetoothDeviceIcon(CachedBluetoothDevice device) {
final Pair pair = BluetoothUtils
.getBtClassDrawableWithDescription(mContext, device);
if (pair.first != null) {
return IconCompat.createWithBitmap(getBitmapFromVectorDrawable(pair.first));
} else {
- return IconCompat.createWithResource(mContext, R.drawable.ic_homepage_connected_device);
+ return IconCompat.createWithResource(mContext, R.drawable.ic_settings_bluetooth);
}
}
private List getBluetoothRowBuilder(SliceAction primarySliceAction) {
final List bluetoothRows = new ArrayList<>();
- // According Bluetooth connected device to create row builders.
- final List bluetoothDevices = getBluetoothConnectedDevices();
+ /**
+ * TODO(b/114807655): Contextual Home Page - Connected Device
+ * Re-design to do action "activating" in primary action.
+ */
+ // According Bluetooth device to create row builders.
+ final List bluetoothDevices = getBluetoothDevices();
for (CachedBluetoothDevice bluetoothDevice : bluetoothDevices) {
bluetoothRows.add(new ListBuilder.RowBuilder()
- .setTitleItem(getConnectedDeviceIcon(bluetoothDevice), ListBuilder.ICON_IMAGE)
+ .setTitleItem(getBluetoothDeviceIcon(bluetoothDevice), ListBuilder.ICON_IMAGE)
.setTitle(bluetoothDevice.getName())
.setSubtitle(bluetoothDevice.getConnectionSummary())
.setPrimaryAction(primarySliceAction)
@@ -254,7 +256,7 @@ public class ConnectedDeviceSlice implements CustomSliceable {
}
private CharSequence getSubTitle(int deviceCount) {
- return mContext.getResources().getQuantityString(R.plurals.show_connected_devices,
+ return mContext.getResources().getQuantityString(R.plurals.show_bluetooth_devices,
deviceCount, deviceCount);
}
diff --git a/src/com/android/settings/slices/CustomSliceManager.java b/src/com/android/settings/slices/CustomSliceManager.java
index 8f8ee967fc4..4a9de15d841 100644
--- a/src/com/android/settings/slices/CustomSliceManager.java
+++ b/src/com/android/settings/slices/CustomSliceManager.java
@@ -29,7 +29,7 @@ import com.android.settings.homepage.contextualcards.deviceinfo.DeviceInfoSlice;
import com.android.settings.homepage.contextualcards.deviceinfo.EmergencyInfoSlice;
import com.android.settings.homepage.contextualcards.deviceinfo.StorageSlice;
import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;
-import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice;
+import com.android.settings.homepage.contextualcards.slices.BluetoothDevicesSlice;
import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
import com.android.settings.location.LocationSlice;
import com.android.settings.wifi.WifiSlice;
@@ -106,7 +106,7 @@ public class CustomSliceManager {
private void addSlices() {
mUriMap.put(CustomSliceRegistry.BATTERY_FIX_SLICE_URI, BatteryFixSlice.class);
mUriMap.put(CustomSliceRegistry.BATTERY_INFO_SLICE_URI, BatterySlice.class);
- mUriMap.put(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI, ConnectedDeviceSlice.class);
+ mUriMap.put(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI, BluetoothDevicesSlice.class);
mUriMap.put(CustomSliceRegistry.DATA_USAGE_SLICE_URI, DataUsageSlice.class);
mUriMap.put(CustomSliceRegistry.DEVICE_INFO_SLICE_URI, DeviceInfoSlice.class);
mUriMap.put(CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI, EmergencyInfoSlice.class);
diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java
index 80de3b2b9eb..1b8cffef509 100644
--- a/src/com/android/settings/slices/CustomSliceRegistry.java
+++ b/src/com/android/settings/slices/CustomSliceRegistry.java
@@ -72,13 +72,13 @@ public class CustomSliceRegistry {
.build();
/**
- * Backing Uri for Connected device Slice.
+ * Backing Uri for Bluetooth devices Slice.
*/
- public static final Uri CONNECTED_DEVICE_SLICE_URI = new Uri.Builder()
+ public static final Uri BLUETOOTH_DEVICES_SLICE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
- .appendPath("connected_device")
+ .appendPath("bluetooth_devices")
.build();
/**
* Backing Uri for the Data usage Slice.
diff --git a/src/com/android/settings/wifi/WifiSlice.java b/src/com/android/settings/wifi/WifiSlice.java
index 2382abb2873..64e3fc3fb16 100644
--- a/src/com/android/settings/wifi/WifiSlice.java
+++ b/src/com/android/settings/wifi/WifiSlice.java
@@ -37,7 +37,6 @@ import androidx.annotation.VisibleForTesting;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.builders.ListBuilder;
-import androidx.slice.builders.ListBuilder.RowBuilder;
import androidx.slice.builders.SliceAction;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -64,9 +63,11 @@ public class WifiSlice implements CustomSliceable {
static final int DEFAULT_EXPANDED_ROW_COUNT = 3;
private final Context mContext;
+ private final WifiManager mWifiManager;
public WifiSlice(Context context) {
mContext = context;
+ mWifiManager = mContext.getSystemService(WifiManager.class);
}
@Override
@@ -100,7 +101,7 @@ public class WifiSlice implements CustomSliceable {
final ListBuilder listBuilder = new ListBuilder(mContext, WIFI_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(color)
- .addRow(new RowBuilder()
+ .addRow(new ListBuilder.RowBuilder()
.setTitle(title)
.setSubtitle(summary)
.addEndItem(toggleSliceAction)
@@ -110,18 +111,25 @@ public class WifiSlice implements CustomSliceable {
return listBuilder.build();
}
- List results = SliceBackgroundWorker.getInstance(mContext, this).getResults();
- if (results == null) {
- results = new ArrayList<>();
- }
- final int apCount = results.size();
+ final List results =
+ SliceBackgroundWorker.getInstance(mContext, this).getResults();
+
+ // Need a loading text when results are not ready.
+ boolean needLoadingRow = results == null;
+ final int apCount = needLoadingRow ? 0 : results.size();
+
// Add AP rows
final CharSequence placeholder = mContext.getText(R.string.summary_placeholder);
for (int i = 0; i < DEFAULT_EXPANDED_ROW_COUNT; i++) {
if (i < apCount) {
listBuilder.addRow(getAccessPointRow(results.get(i)));
+ } else if (needLoadingRow) {
+ listBuilder.addRow(new ListBuilder.RowBuilder()
+ .setTitle(mContext.getText(R.string.wifi_empty_list_wifi_on))
+ .setSubtitle(placeholder));
+ needLoadingRow = false;
} else {
- listBuilder.addRow(new RowBuilder()
+ listBuilder.addRow(new ListBuilder.RowBuilder()
.setTitle(placeholder)
.setSubtitle(placeholder));
}
@@ -129,12 +137,12 @@ public class WifiSlice implements CustomSliceable {
return listBuilder.build();
}
- private RowBuilder getAccessPointRow(AccessPoint accessPoint) {
+ private ListBuilder.RowBuilder getAccessPointRow(AccessPoint accessPoint) {
final String title = accessPoint.getConfigName();
final IconCompat levelIcon = IconCompat.createWithResource(mContext,
com.android.settingslib.Utils.getWifiIconResource(accessPoint.getLevel()));
final CharSequence apSummary = accessPoint.getSettingsSummary();
- final RowBuilder rowBuilder = new RowBuilder()
+ final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder()
.setTitleItem(levelIcon, ListBuilder.ICON_IMAGE)
.setTitle(title)
.setSubtitle(!TextUtils.isEmpty(apSummary)
@@ -188,10 +196,9 @@ public class WifiSlice implements CustomSliceable {
*/
@Override
public void onNotifyChange(Intent intent) {
- final WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
final boolean newState = intent.getBooleanExtra(EXTRA_TOGGLE_STATE,
- wifiManager.isWifiEnabled());
- wifiManager.setWifiEnabled(newState);
+ mWifiManager.isWifiEnabled());
+ mWifiManager.setWifiEnabled(newState);
// Do not notifyChange on Uri. The service takes longer to update the current value than it
// does for the Slice to check the current value again. Let {@link SliceBroadcastRelay}
// handle it.
@@ -211,26 +218,19 @@ public class WifiSlice implements CustomSliceable {
}
private boolean isWifiEnabled() {
- final WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
-
- switch (wifiManager.getWifiState()) {
+ switch (mWifiManager.getWifiState()) {
case WifiManager.WIFI_STATE_ENABLED:
case WifiManager.WIFI_STATE_ENABLING:
return true;
- case WifiManager.WIFI_STATE_DISABLED:
- case WifiManager.WIFI_STATE_DISABLING:
- case WifiManager.WIFI_STATE_UNKNOWN:
default:
return false;
}
}
private CharSequence getSummary() {
- final WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
-
- switch (wifiManager.getWifiState()) {
+ switch (mWifiManager.getWifiState()) {
case WifiManager.WIFI_STATE_ENABLED:
- final String ssid = WifiInfo.removeDoubleQuotes(wifiManager.getConnectionInfo()
+ final String ssid = WifiInfo.removeDoubleQuotes(mWifiManager.getConnectionInfo()
.getSSID());
if (TextUtils.equals(ssid, WifiSsid.NONE)) {
return mContext.getText(R.string.disconnected);
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index e105dfc898e..ab06f751c77 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -7,7 +7,6 @@ com.android.settings.accessibility.ToggleScreenReaderPreferenceFragmentForSetupW
com.android.settings.accessibility.ToggleSelectToSpeakPreferenceFragmentForSetupWizard
com.android.settings.accounts.AccountDetailDashboardFragment
com.android.settings.accounts.AccountSyncSettings
-com.android.settings.accounts.ManagedProfileSettings
com.android.settings.applications.appinfo.AppInfoDashboardFragment
com.android.settings.applications.appinfo.DrawOverlayDetails
com.android.settings.applications.appinfo.ExternalSourcesDetails
diff --git a/tests/robotests/src/com/android/settings/accounts/CrossProfileCalendarPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/CrossProfileCalendarPreferenceControllerTest.java
new file mode 100644
index 00000000000..4469282a366
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accounts/CrossProfileCalendarPreferenceControllerTest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2018 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.accounts;
+
+import static android.provider.Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.RuntimeEnvironment.application;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.ArraySet;
+import android.util.Log;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+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;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowDevicePolicyManager;
+
+import java.util.Collections;
+import java.util.Set;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class CrossProfileCalendarPreferenceControllerTest {
+
+ private static final String PREF_KEY = "cross_profile_calendar";
+ private static final int MANAGED_USER_ID = 10;
+ private static final String TEST_PACKAGE_NAME = "com.test";
+ private static final ComponentName TEST_COMPONENT_NAME = new ComponentName("test", "test");
+
+ @Mock
+ private UserHandle mManagedUser;
+
+ private RestrictedSwitchPreference mPreference;
+ private Context mContext;
+ private CrossProfileCalendarPreferenceController mController;
+ private ShadowDevicePolicyManager dpm;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ mController = new CrossProfileCalendarPreferenceController(mContext, PREF_KEY);
+ mController.setManagedUser(mManagedUser);
+ mPreference = spy(new RestrictedSwitchPreference(mContext));
+ dpm = Shadows.shadowOf(application.getSystemService(DevicePolicyManager.class));
+
+ when(mManagedUser.getIdentifier()).thenReturn(MANAGED_USER_ID);
+ doReturn(mContext).when(mContext).createPackageContextAsUser(
+ any(String.class), anyInt(), any(UserHandle.class));
+ }
+
+ @Test
+ public void getAvailabilityStatus_noManagedUser_DISABLED() {
+ mController.setManagedUser(null);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isNotEqualTo(CrossProfileCalendarPreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_hasManagedUser_AVAILABLE() {
+ mController.setManagedUser(mManagedUser);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(CrossProfileCalendarPreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void updateStateToDisabled_isNotChecked() {
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ CROSS_PROFILE_CALENDAR_ENABLED, 0, mManagedUser.getIdentifier());
+
+ mController.updateState(mPreference);
+ assertThat(mPreference.isChecked()).isFalse();
+ }
+
+ @Test
+ public void updateStateToEnabled_isChecked() throws Exception {
+ // Put 0 first so we know the value is not originally 1.
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ CROSS_PROFILE_CALENDAR_ENABLED, 0, mManagedUser.getIdentifier());
+ mController.updateState(mPreference);
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ CROSS_PROFILE_CALENDAR_ENABLED, 1, mManagedUser.getIdentifier());
+
+ mController.updateState(mPreference);
+ assertThat(mPreference.isChecked()).isTrue();
+ }
+
+ @Test
+ public void updateState_noPackageAllowed_preferenceShouldBeDisabled() throws Exception {
+ dpm.setProfileOwner(TEST_COMPONENT_NAME);
+
+ mController.updateState(mPreference);
+ verify(mPreference).setDisabledByAdmin(any());
+ }
+
+ @Test
+ public void updateState_somePackagesAllowed_preferenceShouldNotBeDisabled() throws Exception {
+ dpm.setProfileOwner(TEST_COMPONENT_NAME);
+ dpm.addCrossProfileCalendarPackage(TEST_COMPONENT_NAME, TEST_PACKAGE_NAME);
+
+ mController.updateState(mPreference);
+ verify(mPreference).setDisabledByAdmin(null);
+ }
+
+ @Test
+ public void onPreferenceChangeToFalse_shouldUpdateProviderValue() {
+ mController.onPreferenceChange(mPreference, false);
+ assertThat(Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ CROSS_PROFILE_CALENDAR_ENABLED, 1, mManagedUser.getIdentifier()))
+ .isEqualTo(0);
+ }
+
+ @Test
+ public void onPreferenceChangeToTrue_shouldUpdateProviderValue() {
+ // Change to false first so we know the value is not originally 1.
+ mController.onPreferenceChange(mPreference, false);
+
+ mController.onPreferenceChange(mPreference, true);
+ assertThat(Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ CROSS_PROFILE_CALENDAR_ENABLED, 0, mManagedUser.getIdentifier()))
+ .isEqualTo(1);
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
index 4f501970416..98943a0e07c 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
@@ -162,7 +162,7 @@ public class ContextualCardLoaderTest {
cards.add(new ContextualCard.Builder()
.setName("test_connected")
.setCardType(ContextualCard.CardType.SLICE)
- .setSliceUri(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI)
+ .setSliceUri(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI)
.build());
cards.add(new ContextualCard.Builder()
.setName("test_gesture")
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java
similarity index 64%
rename from tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java
rename to tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java
index 14a2c477668..ac6557e67d8 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java
@@ -52,7 +52,7 @@ import java.util.ArrayList;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
-public class ConnectedDeviceSliceTest {
+public class BluetoothDevicesSliceTest {
private static final String BLUETOOTH_MOCK_SUMMARY = "BluetoothSummary";
private static final String BLUETOOTH_MOCK_TITLE = "BluetoothTitle";
@@ -60,8 +60,8 @@ public class ConnectedDeviceSliceTest {
@Mock
private CachedBluetoothDevice mCachedBluetoothDevice;
- private List mBluetoothConnectedDeviceList;
- private ConnectedDeviceSlice mConnectedDeviceSlice;
+ private List mBluetoothDeviceList;
+ private BluetoothDevicesSlice mBluetoothDevicesSlice;
private Context mContext;
private IconCompat mIcon;
private PendingIntent mDetailIntent;
@@ -74,57 +74,53 @@ public class ConnectedDeviceSliceTest {
// Set-up specs for SliceMetadata.
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
- mConnectedDeviceSlice = spy(new ConnectedDeviceSlice(mContext));
+ mBluetoothDevicesSlice = spy(new BluetoothDevicesSlice(mContext));
// Mock the icon and detail intent of Bluetooth.
- mIcon = IconCompat.createWithResource(mContext, R.drawable.ic_homepage_connected_device);
+ mIcon = IconCompat.createWithResource(mContext, R.drawable.ic_settings_bluetooth);
mDetailIntent = PendingIntent.getActivity(mContext, 0, new Intent("test action"), 0);
- doReturn(mIcon).when(mConnectedDeviceSlice).getConnectedDeviceIcon(any());
- doReturn(mDetailIntent).when(mConnectedDeviceSlice).getBluetoothDetailIntent(any());
+ doReturn(mIcon).when(mBluetoothDevicesSlice).getBluetoothDeviceIcon(any());
+ doReturn(mDetailIntent).when(mBluetoothDevicesSlice).getBluetoothDetailIntent(any());
- // Initial Bluetooth connected device list.
- mBluetoothConnectedDeviceList = new ArrayList<>();
+ // Initial Bluetooth device list.
+ mBluetoothDeviceList = new ArrayList<>();
}
@After
public void tearDown() {
- if (!mBluetoothConnectedDeviceList.isEmpty()) {
- mBluetoothConnectedDeviceList.clear();
+ if (!mBluetoothDeviceList.isEmpty()) {
+ mBluetoothDeviceList.clear();
}
}
@Test
- public void getSlice_hasConnectedDevices_shouldHaveConnectedDeviceTitle() {
+ public void getSlice_hasBluetoothDevices_shouldHaveBluetoothDevicesTitle() {
mockBluetoothDeviceList();
- doReturn(mBluetoothConnectedDeviceList).when(
- mConnectedDeviceSlice).getBluetoothConnectedDevices();
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
- final Slice slice = mConnectedDeviceSlice.getSlice();
+ final Slice slice = mBluetoothDevicesSlice.getSlice();
final List sliceItems = slice.getItems();
- SliceTester.assertTitle(sliceItems,
- mContext.getString(R.string.bluetooth_connected_devices));
+ SliceTester.assertTitle(sliceItems, mContext.getString(R.string.bluetooth_devices));
}
@Test
- public void getSlice_hasConnectedDevices_shouldMatchBluetoothMockTitle() {
+ public void getSlice_hasBluetoothDevices_shouldMatchBluetoothMockTitle() {
mockBluetoothDeviceList();
- doReturn(mBluetoothConnectedDeviceList).when(
- mConnectedDeviceSlice).getBluetoothConnectedDevices();
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
- final Slice slice = mConnectedDeviceSlice.getSlice();
+ final Slice slice = mBluetoothDevicesSlice.getSlice();
final List sliceItems = slice.getItems();
SliceTester.assertTitle(sliceItems, BLUETOOTH_MOCK_TITLE);
}
@Test
- public void getSlice_hasConnectedDevices_shouldHavePairNewDevice() {
+ public void getSlice_hasBluetoothDevices_shouldHavePairNewDevice() {
mockBluetoothDeviceList();
- doReturn(mBluetoothConnectedDeviceList).when(
- mConnectedDeviceSlice).getBluetoothConnectedDevices();
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
- final Slice slice = mConnectedDeviceSlice.getSlice();
+ final Slice slice = mBluetoothDevicesSlice.getSlice();
final List sliceItems = slice.getItems();
SliceTester.assertTitle(sliceItems,
@@ -132,22 +128,20 @@ public class ConnectedDeviceSliceTest {
}
@Test
- public void getSlice_noConnectedDevices_shouldHaveNoConnectedDeviceTitle() {
- doReturn(mBluetoothConnectedDeviceList).when(
- mConnectedDeviceSlice).getBluetoothConnectedDevices();
+ public void getSlice_noBluetoothDevices_shouldHaveNoBluetoothDevicesTitle() {
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
- final Slice slice = mConnectedDeviceSlice.getSlice();
+ final Slice slice = mBluetoothDevicesSlice.getSlice();
final List sliceItems = slice.getItems();
- SliceTester.assertTitle(sliceItems, mContext.getString(R.string.no_connected_devices));
+ SliceTester.assertTitle(sliceItems, mContext.getString(R.string.no_bluetooth_devices));
}
@Test
- public void getSlice_noConnectedDevices_shouldNotHavePairNewDevice() {
- doReturn(mBluetoothConnectedDeviceList).when(
- mConnectedDeviceSlice).getBluetoothConnectedDevices();
+ public void getSlice_noBluetoothDevices_shouldNotHavePairNewDevice() {
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
- final Slice slice = mConnectedDeviceSlice.getSlice();
+ final Slice slice = mBluetoothDevicesSlice.getSlice();
final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
assertThat(hasTitle(metadata,
@@ -157,7 +151,7 @@ public class ConnectedDeviceSliceTest {
private void mockBluetoothDeviceList() {
doReturn(BLUETOOTH_MOCK_TITLE).when(mCachedBluetoothDevice).getName();
doReturn(BLUETOOTH_MOCK_SUMMARY).when(mCachedBluetoothDevice).getConnectionSummary();
- mBluetoothConnectedDeviceList.add(mCachedBluetoothDevice);
+ mBluetoothDeviceList.add(mCachedBluetoothDevice);
}
private boolean hasTitle(SliceMetadata metadata, String title) {
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRuntimePermissionPresenter.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRuntimePermissionPresenter.java
index f11d9e889d2..e0576b2e6db 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRuntimePermissionPresenter.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRuntimePermissionPresenter.java
@@ -17,7 +17,7 @@
package com.android.settings.testutils.shadow;
import android.content.Context;
-import android.content.pm.permission.RuntimePermissionPresenter;
+import android.permission.RuntimePermissionPresenter;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java
index 5ac25ed5cd5..cdd1664d47b 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java
@@ -53,14 +53,17 @@ public class WifiSliceTest {
private Context mContext;
+ private WifiManager mWifiManager;
private WifiSlice mWifiSlice;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
+ mWifiManager = mContext.getSystemService(WifiManager.class);
// Set-up specs for SliceMetadata.
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+ mWifiManager.setWifiEnabled(true);
mWifiSlice = new WifiSlice(mContext);
}
@@ -83,13 +86,30 @@ public class WifiSliceTest {
}
@Test
- public void getWifiSlice_noAp_shouldReturnPlaceholder() {
+ public void getWifiSlice_wifiOff_shouldReturnSingleRow() {
+ mWifiManager.setWifiEnabled(false);
+
final Slice wifiSlice = mWifiSlice.getSlice();
- int rows = SliceQuery.findAll(wifiSlice, FORMAT_SLICE, HINT_LIST_ITEM,
+ final int rows = SliceQuery.findAll(wifiSlice, FORMAT_SLICE, HINT_LIST_ITEM,
null /* nonHints */).size();
+
+ // Title row
+ assertThat(rows).isEqualTo(1);
+ }
+
+ @Test
+ public void getWifiSlice_noAp_shouldReturnLoadingRow() {
+ final Slice wifiSlice = mWifiSlice.getSlice();
+
+ final int rows = SliceQuery.findAll(wifiSlice, FORMAT_SLICE, HINT_LIST_ITEM,
+ null /* nonHints */).size();
+ final List sliceItems = wifiSlice.getItems();
+
// All AP rows + title row
assertThat(rows).isEqualTo(DEFAULT_EXPANDED_ROW_COUNT + 1);
+ // Has scanning text
+ SliceTester.assertTitle(sliceItems, mContext.getString(R.string.wifi_empty_list_wifi_on));
}
@Test