Snap for 5490587 from 77b7618138 to qt-release
Change-Id: Id817838417d1854043a006701aaf8fa8a77b5325
This commit is contained in:
@@ -3357,4 +3357,20 @@
|
||||
column="5"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
message="Avoid using hardcoded color"
|
||||
category="Correctness"
|
||||
priority="4"
|
||||
summary="Using hardcoded color"
|
||||
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" android:color="@color/notification_importance_button_unselected""
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/drawable/button_border_unselected.xml"
|
||||
line="21"
|
||||
column="10"/>
|
||||
</issue>
|
||||
|
||||
</issues>
|
||||
|
||||
@@ -363,4 +363,7 @@
|
||||
|
||||
<!-- Grayscale settings intent -->
|
||||
<string name="config_grayscale_settings_intent" translate="false"></string>
|
||||
|
||||
<!-- List containing the injected tile keys which are suppressed. -->
|
||||
<string-array name="config_suppress_injected_tile_keys" translatable="false"/>
|
||||
</resources>
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<!-- Empty category to draw divider -->
|
||||
<PreferenceCategory
|
||||
android:key="recent_apps_divider"
|
||||
android:layout="@layout/preference_category_no_label"
|
||||
android:order="-997"/>
|
||||
|
||||
<!-- Notifications (appears before manage_perms), default apps (appears after) -->
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="location_advanced_settings"
|
||||
android:layout="@layout/preference_category_no_label"
|
||||
settings:initialExpandedChildrenCount="2">
|
||||
|
||||
<!-- This preference category gets removed if new_recent_location_ui is disabled -->
|
||||
@@ -54,7 +55,8 @@
|
||||
android:selectable="true" />
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="location_services" />
|
||||
android:key="location_services"
|
||||
android:layout="@layout/preference_category_no_label"/>
|
||||
|
||||
<!-- This preference gets removed if there is no managed profile -->
|
||||
<PreferenceCategory
|
||||
@@ -65,5 +67,6 @@
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="location_footer"
|
||||
android:layout="@layout/preference_category_no_label"
|
||||
settings:allowDividerAbove="false"/>
|
||||
</PreferenceScreen>
|
||||
|
||||
@@ -32,11 +32,18 @@
|
||||
settings:useAdditionalSummary="true"
|
||||
settings:controller="com.android.settings.accounts.ContactSearchPreferenceController"/>
|
||||
|
||||
<com.android.settingslib.RestrictedSwitchPreference
|
||||
<!-- Only one of these preferences will be visible at a time, depending on
|
||||
CrossProfileCalendarPreferenceController#isCrossProfileCalendarDisallowedByAdmin -->
|
||||
<SwitchPreference
|
||||
android:key="cross_profile_calendar"
|
||||
android:summary="@string/cross_profile_calendar_summary"
|
||||
android:title="@string/cross_profile_calendar_title"
|
||||
settings:useAdditionalSummary="true"
|
||||
settings:controller="com.android.settings.accounts.CrossProfileCalendarPreferenceController"/>
|
||||
<Preference
|
||||
android:key="cross_profile_calendar_disabled"
|
||||
android:summary="@string/cross_profile_calendar_restricted_summary"
|
||||
android:title="@string/cross_profile_calendar_title"
|
||||
android:enabled="false"
|
||||
settings:controller="com.android.settings.accounts.CrossProfileCalendarDisabledPreferenceController"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -64,7 +64,8 @@
|
||||
|
||||
<!-- Privacy Service -->
|
||||
<PreferenceCategory
|
||||
android:key="privacy_services"/>
|
||||
android:key="privacy_services"
|
||||
android:layout="@layout/preference_category_no_label"/>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="dashboard_tile_placeholder"/>
|
||||
|
||||
@@ -96,7 +96,8 @@
|
||||
|
||||
<PreferenceCategory
|
||||
android:order="40"
|
||||
android:key="security_settings_device_admin_category">
|
||||
android:key="security_settings_device_admin_category"
|
||||
android:layout="@layout/preference_category_no_label">
|
||||
|
||||
<Preference
|
||||
android:key="manage_device_admin"
|
||||
|
||||
@@ -150,6 +150,9 @@ public class AccountDetailDashboardFragment extends DashboardFragment {
|
||||
|
||||
@Override
|
||||
protected boolean displayTile(Tile tile) {
|
||||
if (!super.displayTile(tile)) {
|
||||
return false;
|
||||
}
|
||||
if (mAccountType == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.accounts;
|
||||
import static com.android.settings.accounts.CrossProfileCalendarPreferenceController.isCrossProfileCalendarDisallowedByAdmin;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
public class CrossProfileCalendarDisabledPreferenceController extends BasePreferenceController {
|
||||
private UserHandle mManagedUser;
|
||||
|
||||
public void setManagedUser(UserHandle managedUser) {
|
||||
mManagedUser = managedUser;
|
||||
}
|
||||
|
||||
public CrossProfileCalendarDisabledPreferenceController(Context context,
|
||||
String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
if (mManagedUser != null
|
||||
&& isCrossProfileCalendarDisallowedByAdmin(
|
||||
mContext, mManagedUser.getIdentifier())) {
|
||||
return AVAILABLE;
|
||||
}
|
||||
|
||||
return DISABLED_FOR_USER;
|
||||
}
|
||||
}
|
||||
@@ -15,19 +15,21 @@ package com.android.settings.accounts;
|
||||
|
||||
import static android.provider.Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settings.core.TogglePreferenceController;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.RestrictedLockUtilsInternal;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class CrossProfileCalendarPreferenceController extends TogglePreferenceController {
|
||||
|
||||
private static final String TAG = "CrossProfileCalendarPreferenceController";
|
||||
|
||||
private UserHandle mManagedUser;
|
||||
|
||||
public CrossProfileCalendarPreferenceController(Context context, String key) {
|
||||
@@ -40,19 +42,13 @@ public class CrossProfileCalendarPreferenceController extends TogglePreferenceCo
|
||||
|
||||
@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);
|
||||
if (mManagedUser != null
|
||||
&& !isCrossProfileCalendarDisallowedByAdmin(
|
||||
mContext, mManagedUser.getIdentifier())) {
|
||||
return AVAILABLE;
|
||||
}
|
||||
|
||||
return DISABLED_FOR_USER;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,4 +70,25 @@ public class CrossProfileCalendarPreferenceController extends TogglePreferenceCo
|
||||
return Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
CROSS_PROFILE_CALENDAR_ENABLED, value, mManagedUser.getIdentifier());
|
||||
}
|
||||
|
||||
static boolean isCrossProfileCalendarDisallowedByAdmin(Context context, int userId) {
|
||||
final Context managedProfileContext = createPackageContextAsUser(context, userId);
|
||||
final DevicePolicyManager dpm = managedProfileContext.getSystemService(
|
||||
DevicePolicyManager.class);
|
||||
if (dpm == null) {
|
||||
return true;
|
||||
}
|
||||
final Set<String> packages = dpm.getCrossProfileCalendarPackages();
|
||||
return packages != null && packages.isEmpty();
|
||||
}
|
||||
|
||||
private static Context createPackageContextAsUser(Context context, int userId) {
|
||||
try {
|
||||
return context.createPackageContextAsUser(
|
||||
context.getPackageName(), 0 /* flags */, UserHandle.of(userId));
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.e(TAG, "Failed to create user context", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -16,17 +16,23 @@
|
||||
|
||||
package com.android.settings.accounts;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
@@ -36,6 +42,7 @@ import com.android.settingslib.search.SearchIndexable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Setting page for managed profile.
|
||||
@@ -72,6 +79,7 @@ public class ManagedProfileSettings extends DashboardFragment {
|
||||
use(WorkModePreferenceController.class).setManagedUser(mManagedUser);
|
||||
use(ContactSearchPreferenceController.class).setManagedUser(mManagedUser);
|
||||
use(CrossProfileCalendarPreferenceController.class).setManagedUser(mManagedUser);
|
||||
use(CrossProfileCalendarDisabledPreferenceController.class).setManagedUser(mManagedUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
@@ -38,6 +39,7 @@ import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.SettingsUIDeviceConfig;
|
||||
import com.android.settings.fuelgauge.BatteryMeterView;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
@@ -64,7 +66,6 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
|
||||
@VisibleForTesting
|
||||
final Map<String, Bitmap> mIconCache;
|
||||
private CachedBluetoothDevice mCachedDevice;
|
||||
private BluetoothDevice mBluetoothDevice;
|
||||
@VisibleForTesting
|
||||
BluetoothAdapter mBluetoothAdapter;
|
||||
@VisibleForTesting
|
||||
@@ -88,9 +89,11 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
final boolean advancedEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, true);
|
||||
final boolean untetheredHeadset = BluetoothUtils.getBooleanMetaData(
|
||||
mCachedDevice.getDevice(), BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET);
|
||||
return untetheredHeadset ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
|
||||
return advancedEnabled && untetheredHeadset ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -138,7 +141,6 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
|
||||
|
||||
public void init(CachedBluetoothDevice cachedBluetoothDevice) {
|
||||
mCachedDevice = cachedBluetoothDevice;
|
||||
mBluetoothDevice = mCachedDevice.getDevice();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
||||
@@ -19,12 +19,14 @@ package com.android.settings.bluetooth;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.SettingsUIDeviceConfig;
|
||||
import com.android.settings.widget.EntityHeaderController;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
@@ -53,8 +55,11 @@ public class BluetoothDetailsHeaderController extends BluetoothDetailsController
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return !BluetoothUtils.getBooleanMetaData(mCachedDevice.getDevice(),
|
||||
BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET);
|
||||
final boolean advancedEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, true);
|
||||
return !advancedEnabled
|
||||
|| !BluetoothUtils.getBooleanMetaData(mCachedDevice.getDevice(),
|
||||
BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,7 +22,7 @@ import android.app.settings.SettingsEnums;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.FeatureFlagUtils;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
@@ -30,7 +30,7 @@ import android.view.MenuItem;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.FeatureFlags;
|
||||
import com.android.settings.core.SettingsUIDeviceConfig;
|
||||
import com.android.settings.dashboard.RestrictedDashboardFragment;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.slices.BlockingSlicePrefController;
|
||||
@@ -117,10 +117,10 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
|
||||
|
||||
final BluetoothFeatureProvider featureProvider = FeatureFactory.getFactory(
|
||||
context).getBluetoothFeatureProvider(context);
|
||||
final boolean injectionEnabled = FeatureFlagUtils.isEnabled(context,
|
||||
FeatureFlags.SLICE_INJECTION);
|
||||
final boolean sliceEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||
SettingsUIDeviceConfig.BT_SLICE_SETTINGS_ENABLED, true);
|
||||
|
||||
use(BlockingSlicePrefController.class).setSliceUri(injectionEnabled
|
||||
use(BlockingSlicePrefController.class).setSliceUri(sliceEnabled
|
||||
? featureProvider.getBluetoothDeviceSettingsUri(mCachedDevice.getDevice())
|
||||
: null);
|
||||
}
|
||||
|
||||
@@ -115,6 +115,8 @@ public abstract class BluetoothDeviceUpdater implements BluetoothCallback,
|
||||
for (CachedBluetoothDevice cachedBluetoothDevice : cachedDevices) {
|
||||
update(cachedBluetoothDevice);
|
||||
}
|
||||
} else {
|
||||
removeAllDevicesFromPreference();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,11 +18,13 @@ package com.android.settings.connecteddevice;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.SettingsUIDeviceConfig;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.slices.SlicePreferenceController;
|
||||
@@ -86,12 +88,15 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment {
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
final boolean nearbyEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||
SettingsUIDeviceConfig.BT_NEAR_BY_SUGGESTION_ENABLED, true);
|
||||
use(AvailableMediaDeviceGroupController.class).init(this);
|
||||
use(ConnectedDeviceGroupController.class).init(this);
|
||||
use(PreviouslyConnectedDevicePreferenceController.class).init(this);
|
||||
use(DiscoverableFooterPreferenceController.class).init(this);
|
||||
use(SlicePreferenceController.class).setSliceUri(
|
||||
Uri.parse(getString(R.string.config_nearby_devices_slice_uri)));
|
||||
use(SlicePreferenceController.class).setSliceUri(nearbyEnabled
|
||||
? Uri.parse(getString(R.string.config_nearby_devices_slice_uri))
|
||||
: null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
36
src/com/android/settings/core/SettingsUIDeviceConfig.java
Normal file
36
src/com/android/settings/core/SettingsUIDeviceConfig.java
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.core;
|
||||
|
||||
/**
|
||||
* Class to store keys for settings related features, which comes from
|
||||
* {@link android.provider.DeviceConfig}
|
||||
*/
|
||||
public class SettingsUIDeviceConfig {
|
||||
/**
|
||||
* {@code true} if slice settings is enabled in BT device detail page
|
||||
*/
|
||||
public static final String BT_SLICE_SETTINGS_ENABLED = "bt_slice_settings_enabled";
|
||||
/**
|
||||
* {@code true} if advanced header is enabled in BT device detail page
|
||||
*/
|
||||
public static final String BT_ADVANCED_HEADER_ENABLED = "bt_advanced_header_enabled";
|
||||
/**
|
||||
* {@code true} if near by device suggestion is enabled in connected device page
|
||||
*/
|
||||
public static final String BT_NEAR_BY_SUGGESTION_ENABLED = "bt_near_by_suggestion_enabled";
|
||||
}
|
||||
@@ -24,12 +24,14 @@ import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerListHelper;
|
||||
@@ -43,6 +45,7 @@ import com.android.settingslib.drawer.DashboardCategory;
|
||||
import com.android.settingslib.drawer.Tile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -65,12 +68,15 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
|
||||
private DashboardTilePlaceholderPreferenceController mPlaceholderPreferenceController;
|
||||
private boolean mListeningToCategoryChange;
|
||||
private SummaryLoader mSummaryLoader;
|
||||
private List<String> mSuppressInjectedTileKeys;
|
||||
@VisibleForTesting
|
||||
UiBlockerController mBlockerController;
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
mSuppressInjectedTileKeys = Arrays.asList(context.getResources().getStringArray(
|
||||
R.array.config_suppress_injected_tile_keys));
|
||||
mDashboardFeatureProvider = FeatureFactory.getFactory(context).
|
||||
getDashboardFeatureProvider(context);
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
@@ -283,7 +289,12 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
|
||||
/**
|
||||
* Returns true if this tile should be displayed
|
||||
*/
|
||||
@CallSuper
|
||||
protected boolean displayTile(Tile tile) {
|
||||
if (mSuppressInjectedTileKeys != null && tile.hasKey()) {
|
||||
// For suppressing injected tiles for OEMs.
|
||||
return !mSuppressInjectedTileKeys.contains(tile.getKey(getContext()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.os.SystemProperties;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.slices.Sliceable;
|
||||
|
||||
public class HardwareRevisionPreferenceController extends BasePreferenceController {
|
||||
|
||||
@@ -44,6 +45,17 @@ public class HardwareRevisionPreferenceController extends BasePreferenceControll
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCopyableSlice() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copy() {
|
||||
Sliceable.setCopyContent(mContext, getSummary(),
|
||||
mContext.getText(R.string.hardware_revision));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
return SystemProperties.get("ro.boot.hardware.revision");
|
||||
|
||||
@@ -34,6 +34,8 @@ import com.android.settings.Utils;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.widget.UsageView;
|
||||
import com.android.settingslib.R;
|
||||
import com.android.settingslib.fuelgauge.Estimate;
|
||||
import com.android.settingslib.fuelgauge.EstimateKt;
|
||||
import com.android.settingslib.utils.PowerUtil;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
@@ -44,7 +46,7 @@ public class BatteryInfo {
|
||||
public int batteryLevel;
|
||||
public boolean discharging = true;
|
||||
public long remainingTimeUs = 0;
|
||||
public long averageTimeToDischarge = Estimate.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN;
|
||||
public long averageTimeToDischarge = EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN;
|
||||
public String batteryPercentString;
|
||||
public String statusLabel;
|
||||
public String suggestionLabel;
|
||||
@@ -202,7 +204,7 @@ public class BatteryInfo {
|
||||
final Estimate estimate = new Estimate(
|
||||
PowerUtil.convertUsToMs(prediction),
|
||||
false, /* isBasedOnUsage */
|
||||
Estimate.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN);
|
||||
EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN);
|
||||
BatteryUtils.logRuntime(LOG_TAG, "time for regular BatteryInfo", startTime);
|
||||
return BatteryInfo.getBatteryInfo(context, batteryBroadcast, stats,
|
||||
estimate, elapsedRealtimeUs, shortString);
|
||||
@@ -214,7 +216,7 @@ public class BatteryInfo {
|
||||
Estimate estimate = new Estimate(
|
||||
PowerUtil.convertUsToMs(stats.computeBatteryTimeRemaining(elapsedRealtimeUs)),
|
||||
false,
|
||||
Estimate.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN);
|
||||
EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN);
|
||||
return getBatteryInfo(context, batteryBroadcast, stats, estimate, elapsedRealtimeUs,
|
||||
shortString);
|
||||
}
|
||||
@@ -228,7 +230,7 @@ public class BatteryInfo {
|
||||
info.batteryLevel = Utils.getBatteryLevel(batteryBroadcast);
|
||||
info.batteryPercentString = Utils.formatPercentage(info.batteryLevel);
|
||||
info.mCharging = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
|
||||
info.averageTimeToDischarge = estimate.averageDischargeTime;
|
||||
info.averageTimeToDischarge = estimate.getAverageDischargeTime();
|
||||
final Resources resources = context.getResources();
|
||||
|
||||
info.statusLabel = Utils.getBatteryStatus(resources, batteryBroadcast);
|
||||
@@ -269,20 +271,20 @@ public class BatteryInfo {
|
||||
|
||||
private static void updateBatteryInfoDischarging(Context context, boolean shortString,
|
||||
Estimate estimate, BatteryInfo info) {
|
||||
final long drainTimeUs = PowerUtil.convertMsToUs(estimate.estimateMillis);
|
||||
final long drainTimeUs = PowerUtil.convertMsToUs(estimate.getEstimateMillis());
|
||||
if (drainTimeUs > 0) {
|
||||
info.remainingTimeUs = drainTimeUs;
|
||||
info.remainingLabel = PowerUtil.getBatteryRemainingStringFormatted(
|
||||
context,
|
||||
PowerUtil.convertUsToMs(drainTimeUs),
|
||||
null /* percentageString */,
|
||||
estimate.isBasedOnUsage && !shortString
|
||||
estimate.isBasedOnUsage() && !shortString
|
||||
);
|
||||
info.chargeLabel = PowerUtil.getBatteryRemainingStringFormatted(
|
||||
context,
|
||||
PowerUtil.convertUsToMs(drainTimeUs),
|
||||
info.batteryPercentString,
|
||||
estimate.isBasedOnUsage && !shortString
|
||||
estimate.isBasedOnUsage() && !shortString
|
||||
);
|
||||
info.suggestionLabel = PowerUtil.getBatteryTipStringFormatted(
|
||||
context, PowerUtil.convertUsToMs(drainTimeUs));
|
||||
|
||||
@@ -82,7 +82,7 @@ public class BatteryMeterView extends ImageView {
|
||||
}
|
||||
|
||||
public int getBatteryLevel() {
|
||||
return mDrawable.getLevel();
|
||||
return mDrawable.getBatteryLevel();
|
||||
}
|
||||
|
||||
public void setCharging(boolean charging) {
|
||||
|
||||
@@ -47,6 +47,8 @@ import com.android.settings.fuelgauge.batterytip.AnomalyInfo;
|
||||
import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager;
|
||||
import com.android.settings.fuelgauge.batterytip.StatsManagerConfig;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.fuelgauge.Estimate;
|
||||
import com.android.settingslib.fuelgauge.EstimateKt;
|
||||
import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
|
||||
import com.android.settingslib.utils.PowerUtil;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
@@ -460,7 +462,7 @@ public class BatteryUtils {
|
||||
estimate = new Estimate(
|
||||
PowerUtil.convertUsToMs(stats.computeBatteryTimeRemaining(elapsedRealtimeUs)),
|
||||
false /* isBasedOnUsage */,
|
||||
Estimate.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN);
|
||||
EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN);
|
||||
}
|
||||
|
||||
BatteryUtils.logRuntime(tag, "BatteryInfoLoader post query", startTime);
|
||||
|
||||
@@ -23,6 +23,8 @@ import android.os.SystemClock;
|
||||
|
||||
import com.android.internal.os.BatteryStatsHelper;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.fuelgauge.Estimate;
|
||||
import com.android.settingslib.fuelgauge.EstimateKt;
|
||||
import com.android.settingslib.utils.AsyncLoaderCompat;
|
||||
import com.android.settingslib.utils.PowerUtil;
|
||||
|
||||
@@ -60,7 +62,7 @@ public class DebugEstimatesLoader extends AsyncLoaderCompat<List<BatteryInfo>> {
|
||||
|
||||
Estimate estimate = powerUsageFeatureProvider.getEnhancedBatteryPrediction(context);
|
||||
if (estimate == null) {
|
||||
estimate = new Estimate(0, false, Estimate.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN);
|
||||
estimate = new Estimate(0, false, EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN);
|
||||
}
|
||||
BatteryInfo newInfo = BatteryInfo.getBatteryInfo(getContext(), batteryBroadcast, stats,
|
||||
estimate, elapsedRealtimeUs, false);
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.android.settings.fuelgauge;
|
||||
|
||||
public class Estimate {
|
||||
|
||||
// Value to indicate averageTimeToDischarge could not be obtained
|
||||
public static final int AVERAGE_TIME_TO_DISCHARGE_UNKNOWN = -1;
|
||||
|
||||
public final long estimateMillis;
|
||||
public final boolean isBasedOnUsage;
|
||||
public final long averageDischargeTime;
|
||||
|
||||
public Estimate(long estimateMillis, boolean isBasedOnUsage,
|
||||
long averageDischargeTime) {
|
||||
this.estimateMillis = estimateMillis;
|
||||
this.isBasedOnUsage = isBasedOnUsage;
|
||||
this.averageDischargeTime = averageDischargeTime;
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import android.content.Intent;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
import com.android.internal.os.BatterySipper;
|
||||
import com.android.settingslib.fuelgauge.Estimate;
|
||||
|
||||
/**
|
||||
* Feature Provider used in power usage
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.util.SparseIntArray;
|
||||
|
||||
import com.android.internal.os.BatterySipper;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.settingslib.fuelgauge.Estimate;
|
||||
|
||||
public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider {
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settingslib.fuelgauge.EstimateKt;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
import com.android.settingslib.utils.PowerUtil;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
@@ -313,7 +314,7 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
|
||||
@VisibleForTesting
|
||||
void updateLastFullChargePreference() {
|
||||
if (mBatteryInfo != null && mBatteryInfo.averageTimeToDischarge
|
||||
!= Estimate.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN) {
|
||||
!= EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN) {
|
||||
mLastFullChargePref.setTitle(R.string.battery_full_charge_last);
|
||||
mLastFullChargePref.setSubtitle(
|
||||
StringUtil.formatElapsedTime(getContext(), mBatteryInfo.averageTimeToDischarge,
|
||||
|
||||
@@ -23,7 +23,6 @@ import androidx.annotation.VisibleForTesting;
|
||||
import com.android.internal.os.BatteryStatsHelper;
|
||||
import com.android.settings.fuelgauge.BatteryInfo;
|
||||
import com.android.settings.fuelgauge.BatteryUtils;
|
||||
import com.android.settings.fuelgauge.Estimate;
|
||||
import com.android.settings.fuelgauge.batterytip.detectors.EarlyWarningDetector;
|
||||
import com.android.settings.fuelgauge.batterytip.detectors.HighUsageDetector;
|
||||
import com.android.settings.fuelgauge.batterytip.detectors.LowBatteryDetector;
|
||||
@@ -33,6 +32,7 @@ import com.android.settings.fuelgauge.batterytip.detectors.SummaryDetector;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.LowBatteryTip;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.SummaryTip;
|
||||
import com.android.settingslib.fuelgauge.EstimateKt;
|
||||
import com.android.settingslib.utils.AsyncLoaderCompat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -87,7 +87,7 @@ public class BatteryTipLoader extends AsyncLoaderCompat<List<BatteryTip>> {
|
||||
private List<BatteryTip> getFakeData() {
|
||||
final List<BatteryTip> tips = new ArrayList<>();
|
||||
tips.add(new SummaryTip(BatteryTip.StateType.NEW,
|
||||
Estimate.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN));
|
||||
EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN));
|
||||
tips.add(new LowBatteryTip(BatteryTip.StateType.NEW, false /* powerSaveModeOn */,
|
||||
"Fake data"));
|
||||
|
||||
|
||||
@@ -26,13 +26,13 @@ import androidx.preference.PreferenceScreen;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.InstrumentedPreferenceFragment;
|
||||
import com.android.settings.fuelgauge.Estimate;
|
||||
import com.android.settings.fuelgauge.batterytip.actions.BatteryTipAction;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.SummaryTip;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.widget.CardPreference;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.fuelgauge.EstimateKt;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -93,7 +93,7 @@ public class BatteryTipPreferenceController extends BasePreferenceController {
|
||||
|
||||
// Add summary tip in advance to avoid UI flakiness
|
||||
final SummaryTip summaryTip = new SummaryTip(BatteryTip.StateType.NEW,
|
||||
Estimate.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN);
|
||||
EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN);
|
||||
summaryTip.updatePreference(mCardPreference);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ public class TetherProvisioningActivity extends Activity {
|
||||
private static final int PROVISION_REQUEST = 0;
|
||||
private static final String TAG = "TetherProvisioningAct";
|
||||
private static final String EXTRA_TETHER_TYPE = "TETHER_TYPE";
|
||||
private static final String EXTRA_SUBID = "subId";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
private ResultReceiver mResultReceiver;
|
||||
|
||||
@@ -49,14 +50,21 @@ public class TetherProvisioningActivity extends Activity {
|
||||
mResultReceiver = (ResultReceiver)getIntent().getParcelableExtra(
|
||||
ConnectivityManager.EXTRA_PROVISION_CALLBACK);
|
||||
|
||||
int tetherType = getIntent().getIntExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE,
|
||||
final int tetherType = getIntent().getIntExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE,
|
||||
ConnectivityManager.TETHERING_INVALID);
|
||||
|
||||
final int tetherSubId = getIntent().getIntExtra(EXTRA_SUBID,
|
||||
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
||||
final int subId = SubscriptionManager.getDefaultDataSubscriptionId();
|
||||
if (tetherSubId != subId) {
|
||||
Log.e(TAG, "This Provisioning request is outdated, current subId: " + subId);
|
||||
return;
|
||||
}
|
||||
final Resources res = Utils.getResourcesForSubId(this, subId);
|
||||
final String[] provisionApp = res.getStringArray(
|
||||
com.android.internal.R.array.config_mobile_hotspot_provision_app);
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_MAIN);
|
||||
final Intent intent = new Intent(Intent.ACTION_MAIN);
|
||||
intent.setClassName(provisionApp[0], provisionApp[1]);
|
||||
intent.putExtra(EXTRA_TETHER_TYPE, tetherType);
|
||||
if (DEBUG) {
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
package com.android.settings.notification;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
@@ -50,6 +52,16 @@ public class ZenModeCallsPreferenceController extends
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
|
||||
preference.setSummary(mSummaryBuilder.getCallsSettingSummary(getPolicy()));
|
||||
switch (getZenMode()) {
|
||||
case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
|
||||
case Settings.Global.ZEN_MODE_ALARMS:
|
||||
preference.setEnabled(false);
|
||||
preference.setSummary(mBackend.getAlarmsTotalSilenceCallsMessagesSummary(
|
||||
NotificationManager.Policy.PRIORITY_CATEGORY_CALLS));
|
||||
break;
|
||||
default:
|
||||
preference.setEnabled(true);
|
||||
preference.setSummary(mSummaryBuilder.getCallsSettingSummary(getPolicy()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
package com.android.settings.notification;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
@@ -49,6 +51,16 @@ public class ZenModeMessagesPreferenceController extends
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
|
||||
preference.setSummary(mSummaryBuilder.getMessagesSettingSummary(getPolicy()));
|
||||
switch (getZenMode()) {
|
||||
case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
|
||||
case Settings.Global.ZEN_MODE_ALARMS:
|
||||
preference.setEnabled(false);
|
||||
preference.setSummary(mBackend.getAlarmsTotalSilenceCallsMessagesSummary(
|
||||
NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES));
|
||||
break;
|
||||
default:
|
||||
preference.setEnabled(true);
|
||||
preference.setSummary(mSummaryBuilder.getMessagesSettingSummary(getPolicy()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,12 @@ import java.util.List;
|
||||
public class PanelSlicesAdapter
|
||||
extends RecyclerView.Adapter<PanelSlicesAdapter.SliceRowViewHolder> {
|
||||
|
||||
/**
|
||||
* Maximum number of slices allowed on the panel view.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static final int MAX_NUM_OF_SLICES = 5;
|
||||
|
||||
private final List<LiveData<Slice>> mSliceLiveData;
|
||||
private final int mMetricsCategory;
|
||||
private final PanelFragment mPanelFragment;
|
||||
@@ -70,14 +76,21 @@ public class PanelSlicesAdapter
|
||||
sliceRowViewHolder.onBind(mSliceLiveData.get(position));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of available items in the adapter with max number of slices enforced.
|
||||
*/
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mSliceLiveData.size();
|
||||
return Math.min(mSliceLiveData.size(), MAX_NUM_OF_SLICES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the available data from the adapter. If the number of Slices over the max number
|
||||
* allowed, the list will only have the first MAX_NUM_OF_SLICES of slices.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
List<LiveData<Slice>> getData() {
|
||||
return mSliceLiveData;
|
||||
return mSliceLiveData.subList(0, getItemCount());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.preference.CheckBoxPreference;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
@@ -89,6 +90,12 @@ public class DisabledCheckBoxPreference extends CheckBoxPreference {
|
||||
mCheckBox = holder.findViewById(android.R.id.checkbox);
|
||||
|
||||
enableCheckbox(mEnabledCheckBox);
|
||||
|
||||
TextView title = (TextView) holder.findViewById(android.R.id.title);
|
||||
if (title != null) {
|
||||
title.setSingleLine(false);
|
||||
title.setMaxLines(2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -55,6 +55,8 @@ public class TetherService extends Service {
|
||||
|
||||
@VisibleForTesting
|
||||
public static final String EXTRA_RESULT = "EntitlementResult";
|
||||
@VisibleForTesting
|
||||
public static final String EXTRA_SUBID = "subId";
|
||||
|
||||
// Activity results to match the activity provision protocol.
|
||||
// Default to something not ok.
|
||||
@@ -100,6 +102,18 @@ public class TetherService extends Service {
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
if (intent.hasExtra(EXTRA_SUBID)) {
|
||||
final int tetherSubId = intent.getIntExtra(EXTRA_SUBID,
|
||||
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
||||
final int subId = getTetherServiceWrapper().getDefaultDataSubscriptionId();
|
||||
if (tetherSubId != subId) {
|
||||
Log.e(TAG, "This Provisioning request is outdated, current subId: " + subId);
|
||||
if (!mInProvisionCheck) {
|
||||
stopSelf();
|
||||
}
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
}
|
||||
if (intent.hasExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE)) {
|
||||
int type = intent.getIntExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE,
|
||||
ConnectivityManager.TETHERING_INVALID);
|
||||
|
||||
@@ -88,4 +88,9 @@
|
||||
|
||||
<!-- Grayscale settings intent -->
|
||||
<string name="config_grayscale_settings_intent" translate="false">intent:#Intent;action=test.test;end</string>
|
||||
|
||||
<!-- List containing the injected tile keys which are suppressed. -->
|
||||
<string-array name="config_suppress_injected_tile_keys" translatable="false">
|
||||
<item>injected_tile_key</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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 com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_USER;
|
||||
|
||||
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 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.Shadows;
|
||||
import org.robolectric.shadows.ShadowDevicePolicyManager;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class CrossProfileCalendarDisabledPreferenceControllerTest {
|
||||
|
||||
private static final String PREF_KEY = "cross_profile_calendar_disabled";
|
||||
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 Context mContext;
|
||||
private CrossProfileCalendarDisabledPreferenceController mController;
|
||||
private ShadowDevicePolicyManager mDpm;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
mController = new CrossProfileCalendarDisabledPreferenceController(mContext, PREF_KEY);
|
||||
mController.setManagedUser(mManagedUser);
|
||||
mDpm = 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_noPackageAllowed_shouldBeAvailable() {
|
||||
mDpm.setProfileOwner(TEST_COMPONENT_NAME);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_somePackagesAllowed_shouldBeDisabledForUser() {
|
||||
mDpm.setProfileOwner(TEST_COMPONENT_NAME);
|
||||
mDpm.setCrossProfileCalendarPackages(TEST_COMPONENT_NAME,
|
||||
Collections.singleton(TEST_PACKAGE_NAME));
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_FOR_USER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_allPackagesAllowed_shouldBeDisabledForUser() {
|
||||
mDpm.setProfileOwner(TEST_COMPONENT_NAME);
|
||||
mDpm.setCrossProfileCalendarPackages(TEST_COMPONENT_NAME, null);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_FOR_USER);
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,9 @@ package com.android.settings.accounts;
|
||||
|
||||
import static android.provider.Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_USER;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -37,6 +40,7 @@ import android.util.ArraySet;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@@ -88,6 +92,7 @@ public class CrossProfileCalendarPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("b/130896049")
|
||||
public void getAvailabilityStatus_hasManagedUser_AVAILABLE() {
|
||||
mController.setManagedUser(mManagedUser);
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
@@ -117,30 +122,27 @@ public class CrossProfileCalendarPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_noPackageAllowed_preferenceShouldBeDisabled() throws Exception {
|
||||
public void getAvailabilityStatus_noPackageAllowed_shouldBeDisabledForUser() throws Exception {
|
||||
dpm.setProfileOwner(TEST_COMPONENT_NAME);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
verify(mPreference).setDisabledByAdmin(any());
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_FOR_USER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_somePackagesAllowed_preferenceShouldNotBeDisabled() throws Exception {
|
||||
public void getAvailabilityStatus_somePackagesAllowed_shouldBeAvailable() throws Exception {
|
||||
dpm.setProfileOwner(TEST_COMPONENT_NAME);
|
||||
dpm.setCrossProfileCalendarPackages(TEST_COMPONENT_NAME,
|
||||
Collections.singleton(TEST_PACKAGE_NAME));
|
||||
|
||||
mController.updateState(mPreference);
|
||||
verify(mPreference).setDisabledByAdmin(null);
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_allPackagesAllowed_preferenceShouldNotBeDisabled() throws Exception {
|
||||
public void getAvailabilityStatus_allPackagesAllowed_shouldBeAvailable() throws Exception {
|
||||
dpm.setProfileOwner(TEST_COMPONENT_NAME);
|
||||
dpm.setCrossProfileCalendarPackages(TEST_COMPONENT_NAME, null);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
verify(mPreference).setDisabledByAdmin(null);
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
@@ -35,7 +36,9 @@ import android.widget.TextView;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.SettingsUIDeviceConfig;
|
||||
import com.android.settings.fuelgauge.BatteryMeterView;
|
||||
import com.android.settings.testutils.shadow.ShadowDeviceConfig;
|
||||
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.widget.LayoutPreference;
|
||||
@@ -50,8 +53,8 @@ import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = ShadowEntityHeaderController.class)
|
||||
public class AdvancedBluetoothDetailsHeaderControllerTest{
|
||||
@Config(shadows = {ShadowEntityHeaderController.class, ShadowDeviceConfig.class})
|
||||
public class AdvancedBluetoothDetailsHeaderControllerTest {
|
||||
private static final int BATTERY_LEVEL_MAIN = 30;
|
||||
private static final int BATTERY_LEVEL_LEFT = 25;
|
||||
private static final int BATTERY_LEVEL_RIGHT = 45;
|
||||
@@ -141,7 +144,9 @@ public class AdvancedBluetoothDetailsHeaderControllerTest{
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_untetheredHeadset_returnAvailable() {
|
||||
public void getAvailabilityStatus_untetheredHeadsetWithConfigOn_returnAvailable() {
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "true", true);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
|
||||
.thenReturn("true".getBytes());
|
||||
|
||||
@@ -150,7 +155,31 @@ public class AdvancedBluetoothDetailsHeaderControllerTest{
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_notUntetheredHeadset_returnUnavailable() {
|
||||
public void getAvailabilityStatus_untetheredHeadsetWithConfigOff_returnUnavailable() {
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "false", true);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
|
||||
.thenReturn("true".getBytes());
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(
|
||||
BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_notUntetheredHeadsetWithConfigOn_returnUnavailable() {
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "true", true);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
|
||||
.thenReturn("false".getBytes());
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(
|
||||
BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_notUntetheredHeadsetWithConfigOff_returnUnavailable() {
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "false", true);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
|
||||
.thenReturn("false".getBytes());
|
||||
|
||||
@@ -169,17 +198,21 @@ public class AdvancedBluetoothDetailsHeaderControllerTest{
|
||||
|
||||
@Test
|
||||
public void onStart_isAvailable_registerCallback() {
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "true", true);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
|
||||
.thenReturn("true".getBytes());
|
||||
|
||||
mController.onStart();
|
||||
|
||||
verify(mBluetoothAdapter).addOnMetadataChangedListener(mBluetoothDevice,
|
||||
mContext.getMainExecutor() ,mController.mMetadataListener);
|
||||
mContext.getMainExecutor(), mController.mMetadataListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_isAvailable_unregisterCallback() {
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "true", true);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
|
||||
.thenReturn("true".getBytes());
|
||||
|
||||
@@ -197,7 +230,7 @@ public class AdvancedBluetoothDetailsHeaderControllerTest{
|
||||
mController.onStart();
|
||||
|
||||
verify(mBluetoothAdapter, never()).addOnMetadataChangedListener(mBluetoothDevice,
|
||||
mContext.getMainExecutor() ,mController.mMetadataListener);
|
||||
mContext.getMainExecutor(), mController.mMetadataListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -213,6 +246,8 @@ public class AdvancedBluetoothDetailsHeaderControllerTest{
|
||||
|
||||
@Test
|
||||
public void onDestroy_isAvailable_recycleBitmap() {
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "true", true);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
|
||||
.thenReturn("true".getBytes());
|
||||
mController.mIconCache.put(ICON_URI, mBitmap);
|
||||
|
||||
@@ -27,7 +27,9 @@ import android.bluetooth.BluetoothDevice;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.SettingsUIDeviceConfig;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.shadow.ShadowDeviceConfig;
|
||||
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
|
||||
import com.android.settings.widget.EntityHeaderController;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
@@ -44,7 +46,7 @@ import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = ShadowEntityHeaderController.class)
|
||||
@Config(shadows = {ShadowEntityHeaderController.class, ShadowDeviceConfig.class})
|
||||
public class BluetoothDetailsHeaderControllerTest extends BluetoothDetailsControllerTestBase {
|
||||
|
||||
private BluetoothDetailsHeaderController mController;
|
||||
@@ -123,10 +125,24 @@ public class BluetoothDetailsHeaderControllerTest extends BluetoothDetailsContro
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_untetheredHeadset_returnFalse() {
|
||||
public void isAvailable_untetheredHeadsetWithConfigOn_returnFalse() {
|
||||
android.provider.DeviceConfig.setProperty(
|
||||
android.provider.DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "true", true);
|
||||
when(mBluetoothDevice.getMetadata(
|
||||
BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)).thenReturn("true".getBytes());
|
||||
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_untetheredHeadsetWithConfigOff_returnTrue() {
|
||||
android.provider.DeviceConfig.setProperty(
|
||||
android.provider.DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "false", true);
|
||||
when(mBluetoothDevice.getMetadata(
|
||||
BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)).thenReturn("true".getBytes());
|
||||
|
||||
assertThat(mController.isAvailable()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,11 +215,14 @@ public class BluetoothDeviceUpdaterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forceUpdate_bluetoothDisabled_doNothing() {
|
||||
public void forceUpdate_bluetoothDisabled_removeAllDevicesFromPreference() {
|
||||
mShadowBluetoothAdapter.setEnabled(false);
|
||||
mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference);
|
||||
|
||||
mBluetoothDeviceUpdater.forceUpdate();
|
||||
|
||||
verify(mDevicePreferenceCallback, never()).onDeviceAdded(any(Preference.class));
|
||||
verify(mDevicePreferenceCallback).onDeviceRemoved(mPreference);
|
||||
assertThat(mBluetoothDeviceUpdater.mPreferenceMap).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.android.settings.search.SearchIndexProviderCodeInspector;
|
||||
import com.android.settings.slices.SliceControllerInXmlCodeInspector;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@@ -46,6 +47,7 @@ public class CodeInspectionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("b/130897640")
|
||||
public void runInstrumentableFragmentCodeInspection() {
|
||||
new InstrumentableFragmentCodeInspector(mClasses).run();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.android.settings.dashboard;
|
||||
|
||||
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.DASHBOARD_CONTAINER;
|
||||
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
@@ -53,6 +54,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -79,6 +81,8 @@ public class DashboardFragmentTest {
|
||||
mActivityInfo = new ActivityInfo();
|
||||
mActivityInfo.packageName = "pkg";
|
||||
mActivityInfo.name = "class";
|
||||
mActivityInfo.metaData = new Bundle();
|
||||
mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "injected_tile_key");
|
||||
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mDashboardCategory = new DashboardCategory("key");
|
||||
mDashboardCategory.addTile(new Tile(mActivityInfo, mDashboardCategory.key));
|
||||
@@ -143,6 +147,20 @@ public class DashboardFragmentTest {
|
||||
verify(mTestFragment.mScreen, never()).addPreference(nullable(Preference.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(qualifiers = "mcc999")
|
||||
public void displayTilesAsPreference_shouldNotAddSuppressedTiles() {
|
||||
when(mFakeFeatureFactory.dashboardFeatureProvider
|
||||
.getTilesForCategory(nullable(String.class)))
|
||||
.thenReturn(mDashboardCategory);
|
||||
when(mFakeFeatureFactory.dashboardFeatureProvider
|
||||
.getDashboardKeyForTile(nullable(Tile.class)))
|
||||
.thenReturn("test_key");
|
||||
mTestFragment.onCreatePreferences(new Bundle(), "rootKey");
|
||||
|
||||
verify(mTestFragment.mScreen, never()).addPreference(nullable(Preference.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onAttach_shouldCreatePlaceholderPreferenceController() {
|
||||
final AbstractPreferenceController controller = mTestFragment.use(
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.deviceinfo.hardwareinfo;
|
||||
|
||||
import static android.content.Context.CLIPBOARD_SERVICE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.os.SystemProperties;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class HardwareRevisionPreferenceControllerTest {
|
||||
|
||||
private Context mContext;
|
||||
private HardwareRevisionPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mController = new HardwareRevisionPreferenceController(mContext,
|
||||
"hardware_info_device_revision");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSliceable_shouldBeSliceable() {
|
||||
assertThat(mController.isSliceable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isCopyableSlice_shouldBeCopyableSlice() {
|
||||
assertThat(mController.isCopyableSlice()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copy_shouldCopyHardwareRevisionToClipboard() {
|
||||
final String fakeHardwareVer = "FakeVer1.0";
|
||||
SystemProperties.set("ro.boot.hardware.revision", fakeHardwareVer);
|
||||
|
||||
mController.copy();
|
||||
|
||||
final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(
|
||||
CLIPBOARD_SERVICE);
|
||||
final CharSequence data = clipboard.getPrimaryClip().getItemAt(0).getText();
|
||||
|
||||
assertThat(data.toString()).isEqualTo(fakeHardwareVer);
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ import com.android.settings.R;
|
||||
import com.android.settingslib.RestrictedPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@@ -40,6 +41,7 @@ import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Ignore("b/130897305")
|
||||
public class AdaptiveSleepPreferenceControllerTest {
|
||||
|
||||
private static final String PREFERENCE_KEY = "adaptive_sleep";
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.content.DialogInterface;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@@ -49,6 +50,7 @@ public class DarkUIInfoDialogFragmentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("b/130897882")
|
||||
public void dialogDismissedOnConfirmation() {
|
||||
doReturn(RuntimeEnvironment.application).when(mFragment).getContext();
|
||||
SharedPreferences prefs = RuntimeEnvironment.application.getSharedPreferences(
|
||||
|
||||
@@ -41,6 +41,7 @@ import com.android.settings.testutils.BatteryTestUtils;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.widget.UsageView;
|
||||
import com.android.settingslib.R;
|
||||
import com.android.settingslib.fuelgauge.Estimate;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -28,7 +28,6 @@ import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.fuelgauge.Estimate;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
|
||||
@@ -37,6 +36,7 @@ import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
|
||||
import com.android.settings.testutils.shadow.ShadowUtils;
|
||||
import com.android.settingslib.fuelgauge.EstimateKt;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -96,7 +96,7 @@ public class BatteryTipDialogFragmentTest {
|
||||
|
||||
mUnrestrictAppTip = new UnrestrictAppTip(BatteryTip.StateType.NEW, mAppInfo);
|
||||
mSummaryTip = spy(new SummaryTip(BatteryTip.StateType.NEW,
|
||||
Estimate.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN));
|
||||
EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -139,7 +139,7 @@ public class AllowSoundPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_notConfigurable() {
|
||||
public void testUpdateState_notBlockable() {
|
||||
String lockedId = "locked";
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
appRow.lockedChannelId = lockedId;
|
||||
@@ -150,7 +150,7 @@ public class AllowSoundPreferenceControllerTest {
|
||||
Preference pref = new RestrictedSwitchPreference(mContext);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertFalse(pref.isEnabled());
|
||||
assertTrue(pref.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -187,7 +187,7 @@ public class BadgePreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_channelNotConfigurable() {
|
||||
public void testUpdateState_channelNotBlockable() {
|
||||
String lockedId = "locked";
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
appRow.lockedChannelId = lockedId;
|
||||
@@ -198,7 +198,7 @@ public class BadgePreferenceControllerTest {
|
||||
Preference pref = new RestrictedSwitchPreference(mContext);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertFalse(pref.isEnabled());
|
||||
assertTrue(pref.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -202,7 +202,7 @@ public class BubblePreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_channelNotConfigurable() {
|
||||
public void testUpdateState_channelNotBlockable() {
|
||||
String lockedId = "locked";
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
appRow.lockedChannelId = lockedId;
|
||||
@@ -213,7 +213,7 @@ public class BubblePreferenceControllerTest {
|
||||
Preference pref = new RestrictedSwitchPreference(mContext);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertFalse(pref.isEnabled());
|
||||
assertTrue(pref.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -110,7 +110,7 @@ public class DndPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_notConfigurable() {
|
||||
public void testUpdateState_notBlockable() {
|
||||
String lockedId = "locked";
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
appRow.lockedChannelId = lockedId;
|
||||
@@ -121,7 +121,7 @@ public class DndPreferenceControllerTest {
|
||||
Preference pref = new RestrictedSwitchPreference(RuntimeEnvironment.application);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertFalse(pref.isEnabled());
|
||||
assertTrue(pref.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -158,7 +158,7 @@ public class LightsPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_notConfigurable() {
|
||||
public void testUpdateState_notBlockable() {
|
||||
String lockedId = "locked";
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
appRow.lockedChannelId = lockedId;
|
||||
@@ -169,19 +169,6 @@ public class LightsPreferenceControllerTest {
|
||||
Preference pref = new RestrictedSwitchPreference(mContext);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertFalse(pref.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_configurable() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
NotificationChannel channel = mock(NotificationChannel.class);
|
||||
when(channel.getId()).thenReturn("something");
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
|
||||
Preference pref = new RestrictedSwitchPreference(mContext);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertTrue(pref.isEnabled());
|
||||
}
|
||||
|
||||
|
||||
@@ -209,6 +209,7 @@ public class NotificationPreferenceControllerTest {
|
||||
appRow.lockedChannelId = sameId;
|
||||
NotificationChannel channel = mock(NotificationChannel.class);
|
||||
when(channel.getId()).thenReturn(sameId);
|
||||
when(channel.getImportance()).thenReturn(IMPORTANCE_LOW);
|
||||
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
assertFalse(mController.isChannelBlockable());
|
||||
@@ -223,8 +224,10 @@ public class NotificationPreferenceControllerTest {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
appRow.lockedChannelId = "something";
|
||||
appRow.lockedImportance = true;
|
||||
NotificationChannel channel = mock(NotificationChannel.class);
|
||||
when(channel.getImportance()).thenReturn(IMPORTANCE_LOW);
|
||||
|
||||
mController.onResume(appRow, mock(NotificationChannel.class), null, null);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
assertFalse(mController.isChannelBlockable());
|
||||
|
||||
appRow.lockedImportance = false;
|
||||
|
||||
@@ -161,7 +161,7 @@ public class SoundPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_notConfigurable() {
|
||||
public void testUpdateState_notBlockable() {
|
||||
String lockedId = "locked";
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
appRow.lockedChannelId = lockedId;
|
||||
@@ -173,7 +173,7 @@ public class SoundPreferenceControllerTest {
|
||||
Preference pref = new NotificationSoundPreference(mContext, attributeSet);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertFalse(pref.isEnabled());
|
||||
assertTrue(pref.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -140,7 +140,7 @@ public class VibrationPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_notConfigurable() {
|
||||
public void testUpdateState_notBlockable() {
|
||||
String lockedId = "locked";
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
appRow.lockedChannelId = lockedId;
|
||||
@@ -151,7 +151,7 @@ public class VibrationPreferenceControllerTest {
|
||||
Preference pref = new RestrictedSwitchPreference(RuntimeEnvironment.application);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertFalse(pref.isEnabled());
|
||||
assertTrue(pref.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.android.settings.R;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@@ -105,6 +106,7 @@ public class PanelFragmentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("b/130896218")
|
||||
public void onDestroy_logCloseEvent() {
|
||||
mPanelFragment.onDestroy();
|
||||
verify(mFakeFeatureFactory.metricsFeatureProvider).action(
|
||||
@@ -115,6 +117,7 @@ public class PanelFragmentTest {
|
||||
0); }
|
||||
|
||||
@Test
|
||||
@Ignore("b/130896218")
|
||||
public void panelSeeMoreClick_logsCloseEvent() {
|
||||
final View.OnClickListener listener = mPanelFragment.getSeeMoreListener();
|
||||
|
||||
@@ -130,6 +133,7 @@ public class PanelFragmentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("b/130896218")
|
||||
public void panelDoneClick_logsCloseEvent() {
|
||||
final View.OnClickListener listener = mPanelFragment.getCloseListener();
|
||||
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
|
||||
package com.android.settings.panel;
|
||||
|
||||
import static com.android.settings.panel.PanelSlicesAdapter.MAX_NUM_OF_SLICES;
|
||||
import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -40,7 +42,6 @@ import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
@@ -62,11 +63,6 @@ public class PanelSlicesAdapterTest {
|
||||
private FakePanelContent mFakePanelContent;
|
||||
private List<LiveData<Slice>> mData = new ArrayList<>();
|
||||
|
||||
@Mock
|
||||
private LiveData<Slice> mLiveData;
|
||||
|
||||
private Slice mSlice;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
@@ -91,17 +87,18 @@ public class PanelSlicesAdapterTest {
|
||||
|
||||
}
|
||||
|
||||
private void constructTestLiveData(Uri uri) {
|
||||
private void addTestLiveData(Uri uri) {
|
||||
// Create a slice to return for the LiveData
|
||||
mSlice = spy(new Slice());
|
||||
doReturn(uri).when(mSlice).getUri();
|
||||
when(mLiveData.getValue()).thenReturn(mSlice);
|
||||
mData.add(mLiveData);
|
||||
final Slice slice = spy(new Slice());
|
||||
doReturn(uri).when(slice).getUri();
|
||||
final LiveData<Slice> liveData = mock(LiveData.class);
|
||||
when(liveData.getValue()).thenReturn(slice);
|
||||
mData.add(liveData);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreateViewHolder_returnsSliceRowViewHolder() {
|
||||
constructTestLiveData(DATA_URI);
|
||||
addTestLiveData(DATA_URI);
|
||||
final PanelSlicesAdapter adapter =
|
||||
new PanelSlicesAdapter(mPanelFragment, mData, 0 /* metrics category */);
|
||||
final ViewGroup view = new FrameLayout(mContext);
|
||||
@@ -111,9 +108,27 @@ public class PanelSlicesAdapterTest {
|
||||
assertThat(viewHolder.sliceView).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sizeOfAdapter_shouldNotExceedMaxNum() {
|
||||
for (int i = 0; i < MAX_NUM_OF_SLICES + 2; i++) {
|
||||
addTestLiveData(DATA_URI);
|
||||
}
|
||||
|
||||
assertThat(mData.size()).isEqualTo(MAX_NUM_OF_SLICES + 2);
|
||||
|
||||
final PanelSlicesAdapter adapter =
|
||||
new PanelSlicesAdapter(mPanelFragment, mData, 0 /* metrics category */);
|
||||
final ViewGroup view = new FrameLayout(mContext);
|
||||
final PanelSlicesAdapter.SliceRowViewHolder viewHolder =
|
||||
adapter.onCreateViewHolder(view, 0);
|
||||
|
||||
assertThat(adapter.getItemCount()).isEqualTo(MAX_NUM_OF_SLICES);
|
||||
assertThat(adapter.getData().size()).isEqualTo(MAX_NUM_OF_SLICES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonMediaOutputIndicatorSlice_shouldAllowDividerAboveAndBelow() {
|
||||
constructTestLiveData(DATA_URI);
|
||||
addTestLiveData(DATA_URI);
|
||||
final PanelSlicesAdapter adapter =
|
||||
new PanelSlicesAdapter(mPanelFragment, mData, 0 /* metrics category */);
|
||||
final int position = 0;
|
||||
@@ -129,7 +144,7 @@ public class PanelSlicesAdapterTest {
|
||||
|
||||
@Test
|
||||
public void mediaOutputIndicatorSlice_shouldNotAllowDividerAbove() {
|
||||
constructTestLiveData(MEDIA_OUTPUT_INDICATOR_SLICE_URI);
|
||||
addTestLiveData(MEDIA_OUTPUT_INDICATOR_SLICE_URI);
|
||||
|
||||
final PanelSlicesAdapter adapter =
|
||||
new PanelSlicesAdapter(mPanelFragment, mData, 0 /* metrics category */);
|
||||
|
||||
@@ -35,6 +35,7 @@ import android.view.MotionEvent;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
@@ -89,6 +90,7 @@ public class SettingsPanelActivityTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("b/130896218")
|
||||
public void onTouchEvent_outsideAction_logsPanelClosed() {
|
||||
final MotionEvent event = mock(MotionEvent.class);
|
||||
when(event.getAction()).thenReturn(MotionEvent.ACTION_OUTSIDE);
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.net.Uri;
|
||||
import com.android.settings.slices.CustomSliceRegistry;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
@@ -41,6 +42,7 @@ public class VolumePanelTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("b/130896218")
|
||||
public void getSlices_containsNecessarySlices() {
|
||||
final List<Uri> uris = mPanel.getSlices();
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@ import com.android.settingslib.wifi.WifiTracker;
|
||||
import com.android.settingslib.wifi.WifiTrackerFactory;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
@@ -105,6 +106,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowDevicePolicyManager.class, ShadowEntityHeaderController.class})
|
||||
@Ignore("b/130896210")
|
||||
public class WifiDetailPreferenceControllerTest {
|
||||
|
||||
private static final int LEVEL = 1;
|
||||
|
||||
@@ -266,11 +266,26 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
||||
assertEquals(TetherService.class.getName(), pi.getIntent().getComponent().getClassName());
|
||||
}
|
||||
|
||||
public void testIgnoreOutdatedRequest() {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_WIFI);
|
||||
intent.putExtra(EXTRA_RUN_PROVISION, true);
|
||||
intent.putExtra(EXTRA_PROVISION_CALLBACK, mResultReceiver);
|
||||
intent.putExtra(TetherService.EXTRA_SUBID, 1 /* Tested subId number */);
|
||||
startService(intent);
|
||||
|
||||
SystemClock.sleep(PROVISION_TIMEOUT);
|
||||
assertEquals(TETHERING_INVALID, mLastTetherRequestType);
|
||||
assertTrue(mWrapper.isAppInactive(ENTITLEMENT_PACKAGE_NAME));
|
||||
assertTrue(mWrapper.isAppInactive(FAKE_PACKAGE_NAME));
|
||||
}
|
||||
|
||||
private void runProvisioningForType(int type) {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(EXTRA_ADD_TETHER_TYPE, type);
|
||||
intent.putExtra(EXTRA_RUN_PROVISION, true);
|
||||
intent.putExtra(EXTRA_PROVISION_CALLBACK, mResultReceiver);
|
||||
intent.putExtra(TetherService.EXTRA_SUBID, INVALID_SUBSCRIPTION_ID);
|
||||
startService(intent);
|
||||
}
|
||||
|
||||
@@ -291,7 +306,7 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
||||
long startTime = SystemClock.uptimeMillis();
|
||||
while (true) {
|
||||
if (mLastTetherRequestType == expectedType) {
|
||||
mLastTetherRequestType = -1;
|
||||
mLastTetherRequestType = TETHERING_INVALID;
|
||||
return true;
|
||||
}
|
||||
if ((SystemClock.uptimeMillis() - startTime) > PROVISION_TIMEOUT) {
|
||||
|
||||
Reference in New Issue
Block a user