Snap for 7199033 from e9355553ee to sc-release
Change-Id: I78501e3c670a14c1eeb9c25c91bdd66372d84136
This commit is contained in:
45
res/drawable/one_handed_guideline.xml
Normal file
45
res/drawable/one_handed_guideline.xml
Normal file
@@ -0,0 +1,45 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="412dp"
|
||||
android:height="264dp"
|
||||
android:viewportWidth="412"
|
||||
android:viewportHeight="264">
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M0,0h412v264h-412z"/>
|
||||
<path
|
||||
android:pathData="M126,-246C109.431,-246 96,-232.569 96,-216V195C96,211.569 109.431,225 126,225H284.5C301.069,225 314.5,211.569 314.5,195V-216C314.5,-232.569 301.069,-246 284.5,-246H126ZM122,-235C110.954,-235 102,-226.046 102,-215V189.5C102,200.546 110.954,209.5 122,209.5H288C299.046,209.5 308,200.546 308,189.5V-215C308,-226.046 299.046,-235 288,-235H122Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M122.12,-233L288.12,-233A20,20 0,0 1,308.12 -213L308.12,191.5A20,20 0,0 1,288.12 211.5L122.12,211.5A20,20 0,0 1,102.12 191.5L102.12,-213A20,20 0,0 1,122.12 -233z"
|
||||
android:fillColor="#EAF1FF"/>
|
||||
<path
|
||||
android:pathData="M102.16,193.12H308.08C308.08,203.326 299.806,211.6 289.6,211.6H120.64C110.434,211.6 102.16,203.326 102.16,193.12Z"
|
||||
android:fillColor="#B5CFFC"/>
|
||||
<path
|
||||
android:pathData="M187.5,202.72L222.5,202.72A0.5,0.5 0,0 1,223 203.22L223,203.22A0.5,0.5 0,0 1,222.5 203.72L187.5,203.72A0.5,0.5 0,0 1,187 203.22L187,203.22A0.5,0.5 0,0 1,187.5 202.72z"
|
||||
android:fillColor="#666666"/>
|
||||
<path
|
||||
android:pathData="M197,115h36v94.684h-36z"
|
||||
android:strokeAlpha="0.8"
|
||||
android:fillAlpha="0.8">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:startY="189.19"
|
||||
android:startX="212.951"
|
||||
android:endY="168.637"
|
||||
android:endX="212.447"
|
||||
android:type="linear">
|
||||
<item android:offset="0" android:color="#FF4285F4"/>
|
||||
<item android:offset="1" android:color="#004385F5"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M197,206.899a18,18.101 0,1 0,36 0a18,18.101 0,1 0,-36 0z"
|
||||
android:strokeAlpha="0.8"
|
||||
android:fillColor="#3B7BE4"
|
||||
android:fillAlpha="0.8"/>
|
||||
</group>
|
||||
</vector>
|
||||
29
res/layout/one_handed_header.xml
Normal file
29
res/layout/one_handed_header.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2021 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.
|
||||
-->
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="centerCrop"
|
||||
android:cropToPadding="true"
|
||||
android:src="@drawable/one_handed_guideline"
|
||||
android:contentDescription="@null" />
|
||||
|
||||
</FrameLayout>
|
||||
@@ -39,7 +39,7 @@
|
||||
app:statusBarScrim="?android:attr/colorPrimary"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed"
|
||||
app:expandedTitleMarginStart="18dp"
|
||||
app:expandedTitleMarginEnd="18dp"
|
||||
app:expandedTitleMarginEnd="16dp"
|
||||
app:toolbarId="@id/action_bar">
|
||||
|
||||
<Toolbar
|
||||
|
||||
@@ -10496,8 +10496,6 @@
|
||||
<string name="disabled_by_policy_title_suspend_packages">Can’t open this app</string>
|
||||
<!-- Dialog title. This dialog lets a user know that a specific setting is blocked by their credit provider. Since the user purchased the device from the credit provider, the credit provider controls what they can access. [CHAR LIMIT=50] -->
|
||||
<string name="disabled_by_policy_title_financed_device">Blocked by your credit provider</string>
|
||||
<!-- Shown when the user tries to change a settings locked by an admin [CHAR LIMIT=200] -->
|
||||
<string name="default_admin_support_msg">If you have questions, contact your IT admin</string>
|
||||
<!-- Shown in dialog to allow user to see more information about the device admin [CHAR LIMIT=30] -->
|
||||
<string name="admin_support_more_info">More details</string>
|
||||
<!-- Shown in admin details page to warn user about policies the admin can set in a work profile. [CHAR LIMIT=NONE] -->
|
||||
@@ -12725,10 +12723,8 @@
|
||||
<string name="view_airplane_safe_networks">View airplane mode networks</string>
|
||||
<!-- Text of message for viewing the networks that are available in airplane mode. [CHAR LIMIT=60] -->
|
||||
<string name="viewing_airplane_mode_networks">Viewing airplane mode networks</string>
|
||||
<!-- Slice title text for turning on networks (e.g. Wi-Fi). [CHAR LIMIT=40] -->
|
||||
<string name="turn_on_networks">Turn on networks</string>
|
||||
<!-- Slice title text for turning off networks (e.g. Wi-Fi). [CHAR LIMIT=40] -->
|
||||
<string name="turn_off_networks">Turn off networks</string>
|
||||
<!-- Slice title text for turning on the Wi-Fi networks. [CHAR LIMIT=40] -->
|
||||
<string name="turn_on_wifi">Turn on Wi\u2011Fi</string>
|
||||
<!-- Title for interrupting the voice call alert. [CHAR_LIMIT=NONE] -->
|
||||
<string name="reset_your_internet_title">Reset your internet?</string>
|
||||
<!-- Description for interrupting the voice call alert. [CHAR_LIMIT=NONE] -->
|
||||
|
||||
@@ -21,6 +21,14 @@
|
||||
android:persistent="false"
|
||||
android:title="@string/one_handed_title">
|
||||
|
||||
<com.android.settingslib.widget.LayoutPreference
|
||||
android:key="one_handed_header"
|
||||
android:layout="@layout/one_handed_header"
|
||||
android:persistent="false"
|
||||
android:selectable="false"
|
||||
settings:allowDividerBelow="false"
|
||||
settings:searchable="false"/>
|
||||
|
||||
<SwitchPreference
|
||||
android:key="gesture_one_handed_mode_enabled"
|
||||
android:title="@string/one_handed_mode_enabled"
|
||||
|
||||
@@ -48,7 +48,7 @@ public class AppDashboardFragment extends DashboardFragment {
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return SettingsEnums.SETTINGS_APP_NOTIF_CATEGORY;
|
||||
return SettingsEnums.MANAGE_APPLICATIONS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -31,6 +31,7 @@ import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
@@ -47,16 +48,23 @@ public class PasswordsPreferenceController extends BasePreferenceController {
|
||||
private final List<AutofillServiceInfo> mServices;
|
||||
|
||||
public PasswordsPreferenceController(Context context, String preferenceKey) {
|
||||
this(context, preferenceKey,
|
||||
AutofillServiceInfo.getAvailableServices(context, UserHandle.myUserId()));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public PasswordsPreferenceController(
|
||||
Context context, String preferenceKey, List<AutofillServiceInfo> availableServices) {
|
||||
super(context, preferenceKey);
|
||||
mPm = context.getPackageManager();
|
||||
mIconFactory = IconDrawableFactory.newInstance(mContext);
|
||||
mServices = AutofillServiceInfo.getAvailableServices(mContext, UserHandle.myUserId());
|
||||
for (int i = mServices.size() - 1; i >= 0; i--) {
|
||||
final String passwordsActivity = mServices.get(i).getPasswordsActivity();
|
||||
for (int i = availableServices.size() - 1; i >= 0; i--) {
|
||||
final String passwordsActivity = availableServices.get(i).getPasswordsActivity();
|
||||
if (TextUtils.isEmpty(passwordsActivity)) {
|
||||
mServices.remove(i);
|
||||
availableServices.remove(i);
|
||||
}
|
||||
}
|
||||
mServices = availableServices;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -233,8 +233,6 @@ public class ActionDisabledByAdminDialogHelper {
|
||||
final TextView textView = root.findViewById(R.id.admin_support_msg);
|
||||
if (supportMessage != null) {
|
||||
textView.setText(supportMessage);
|
||||
} else if (!isFinancedDevice()) {
|
||||
textView.setText(R.string.default_admin_support_msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,217 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.network;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
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 androidx.slice.core.SliceHints;
|
||||
|
||||
import com.android.settings.AirplaneModeEnabler;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.slices.CustomSliceRegistry;
|
||||
import com.android.settings.slices.CustomSliceable;
|
||||
import com.android.settings.slices.SliceBackgroundWorker;
|
||||
import com.android.settings.slices.SliceBroadcastReceiver;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* {@link CustomSliceable} for airplane-safe networks, used by generic clients.
|
||||
*/
|
||||
public class AirplaneSafeNetworksSlice implements CustomSliceable,
|
||||
AirplaneModeEnabler.OnAirplaneModeChangedListener {
|
||||
|
||||
private static final String TAG = "AirplaneSafeNetworksSlice";
|
||||
|
||||
public static final String ACTION_INTENT_EXTRA = "action";
|
||||
|
||||
/**
|
||||
* Annotation for different action of the slice.
|
||||
*
|
||||
* {@code TURN_ON_NETWORKS} for action of turning on Wi-Fi networks.
|
||||
* {@code TURN_OFF_NETWORKS} for action of turning off Wi-Fi networks.
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(value = {
|
||||
Action.TURN_ON_NETWORKS,
|
||||
Action.TURN_OFF_NETWORKS,
|
||||
})
|
||||
public @interface Action {
|
||||
int TURN_ON_NETWORKS = 1;
|
||||
int TURN_OFF_NETWORKS = 2;
|
||||
}
|
||||
|
||||
private final Context mContext;
|
||||
private final AirplaneModeEnabler mAirplaneModeEnabler;
|
||||
private final WifiManager mWifiManager;
|
||||
|
||||
private boolean mIsAirplaneModeOn;
|
||||
|
||||
public AirplaneSafeNetworksSlice(Context context) {
|
||||
mContext = context;
|
||||
mAirplaneModeEnabler = new AirplaneModeEnabler(context, this);
|
||||
mIsAirplaneModeOn = mAirplaneModeEnabler.isAirplaneModeOn();
|
||||
mWifiManager = mContext.getSystemService(WifiManager.class);
|
||||
}
|
||||
|
||||
private static void logd(String s) {
|
||||
Log.d(TAG, s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice getSlice() {
|
||||
final ListBuilder listBuilder = new ListBuilder(mContext, getUri(), ListBuilder.INFINITY);
|
||||
if (mIsAirplaneModeOn) {
|
||||
listBuilder.addRow(new RowBuilder()
|
||||
.setTitle(getTitle())
|
||||
.addEndItem(getEndIcon(), SliceHints.ICON_IMAGE)
|
||||
.setPrimaryAction(getSliceAction()));
|
||||
}
|
||||
return listBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri getUri() {
|
||||
return CustomSliceRegistry.AIRPLANE_SAFE_NETWORKS_SLICE_URI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotifyChange(Intent intent) {
|
||||
final int action = intent.getIntExtra(ACTION_INTENT_EXTRA, 0);
|
||||
if (action == Action.TURN_ON_NETWORKS) {
|
||||
if (!mWifiManager.isWifiEnabled()) {
|
||||
logd("Action: turn on Wi-Fi networks");
|
||||
mWifiManager.setWifiEnabled(true);
|
||||
}
|
||||
} else if (action == Action.TURN_OFF_NETWORKS) {
|
||||
if (mWifiManager.isWifiEnabled()) {
|
||||
logd("Action: turn off Wi-Fi networks");
|
||||
mWifiManager.setWifiEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAirplaneModeChanged(boolean isAirplaneModeOn) {
|
||||
mIsAirplaneModeOn = isAirplaneModeOn;
|
||||
final AirplaneSafeNetworksWorker worker = SliceBackgroundWorker.getInstance(getUri());
|
||||
if (worker != null) {
|
||||
worker.updateSlice();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getIntent() {
|
||||
return new Intent(getUri().toString())
|
||||
.setData(getUri())
|
||||
.setClass(mContext, SliceBroadcastReceiver.class)
|
||||
.putExtra(ACTION_INTENT_EXTRA, getAction());
|
||||
}
|
||||
|
||||
@Action
|
||||
private int getAction() {
|
||||
return mWifiManager.isWifiEnabled()
|
||||
? Action.TURN_OFF_NETWORKS
|
||||
: Action.TURN_ON_NETWORKS;
|
||||
}
|
||||
|
||||
private String getTitle() {
|
||||
return mContext.getText(
|
||||
(getAction() == Action.TURN_ON_NETWORKS)
|
||||
? R.string.turn_on_networks
|
||||
: R.string.turn_off_networks).toString();
|
||||
}
|
||||
|
||||
private IconCompat getEndIcon() {
|
||||
final Drawable drawable = mContext.getDrawable(
|
||||
(getAction() == Action.TURN_ON_NETWORKS) ? R.drawable.ic_airplane_safe_networks_24dp
|
||||
: R.drawable.ic_airplanemode_active);
|
||||
if (drawable == null) {
|
||||
return Utils.createIconWithDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
drawable.setTintList(Utils.getColorAttr(mContext, android.R.attr.colorAccent));
|
||||
return Utils.createIconWithDrawable(drawable);
|
||||
}
|
||||
|
||||
private SliceAction getSliceAction() {
|
||||
final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext,
|
||||
0 /* requestCode */, getIntent(),
|
||||
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||
final IconCompat icon = Utils.createIconWithDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
return SliceAction.create(pendingIntent, icon, ListBuilder.ACTION_WITH_LABEL, getTitle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getBackgroundWorkerClass() {
|
||||
return AirplaneSafeNetworksWorker.class;
|
||||
}
|
||||
|
||||
public static class AirplaneSafeNetworksWorker extends SliceBackgroundWorker {
|
||||
|
||||
private final IntentFilter mIntentFilter;
|
||||
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) {
|
||||
notifySliceChange();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public AirplaneSafeNetworksWorker(Context context, Uri uri) {
|
||||
super(context, uri);
|
||||
mIntentFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSlicePinned() {
|
||||
getContext().registerReceiver(mBroadcastReceiver, mIntentFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSliceUnpinned() {
|
||||
getContext().unregisterReceiver(mBroadcastReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
public void updateSlice() {
|
||||
notifySliceChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
147
src/com/android/settings/network/TurnOnWifiSlice.java
Normal file
147
src/com/android/settings/network/TurnOnWifiSlice.java
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.network;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.util.Log;
|
||||
|
||||
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 androidx.slice.core.SliceHints;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.slices.CustomSliceRegistry;
|
||||
import com.android.settings.slices.CustomSliceable;
|
||||
import com.android.settings.slices.SliceBackgroundWorker;
|
||||
import com.android.settings.slices.SliceBroadcastReceiver;
|
||||
|
||||
/**
|
||||
* {@link CustomSliceable} for turning on Wi-Fi, used by generic clients.
|
||||
*/
|
||||
public class TurnOnWifiSlice implements CustomSliceable {
|
||||
|
||||
private static final String TAG = "TurnOnWifiSlice";
|
||||
|
||||
private final Context mContext;
|
||||
private final WifiManager mWifiManager;
|
||||
|
||||
public TurnOnWifiSlice(Context context) {
|
||||
mContext = context;
|
||||
mWifiManager = mContext.getSystemService(WifiManager.class);
|
||||
}
|
||||
|
||||
private static void logd(String s) {
|
||||
Log.d(TAG, s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice getSlice() {
|
||||
if (mWifiManager.isWifiEnabled()) {
|
||||
return null;
|
||||
}
|
||||
final String title = mContext.getText(R.string.turn_on_wifi).toString();
|
||||
final SliceAction primaryAction = SliceAction.create(getBroadcastIntent(mContext),
|
||||
getEndIcon(), ListBuilder.ICON_IMAGE, title);
|
||||
final ListBuilder listBuilder = new ListBuilder(mContext, getUri(), ListBuilder.INFINITY)
|
||||
.addRow(new RowBuilder()
|
||||
.setTitle(title)
|
||||
.addEndItem(getEndIcon(), SliceHints.ICON_IMAGE)
|
||||
.setPrimaryAction(primaryAction));
|
||||
return listBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri getUri() {
|
||||
return CustomSliceRegistry.TURN_ON_WIFI_SLICE_URI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotifyChange(Intent intent) {
|
||||
logd("Action: turn on Wi-Fi networks");
|
||||
mWifiManager.setWifiEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getIntent() {
|
||||
return new Intent(getUri().toString())
|
||||
.setData(getUri())
|
||||
.setClass(mContext, SliceBroadcastReceiver.class);
|
||||
}
|
||||
|
||||
private IconCompat getEndIcon() {
|
||||
final Drawable drawable = mContext.getDrawable(R.drawable.ic_settings_wireless);
|
||||
if (drawable == null) {
|
||||
return Utils.createIconWithDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
drawable.setTintList(Utils.getColorAttr(mContext, android.R.attr.colorAccent));
|
||||
return Utils.createIconWithDrawable(drawable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getBackgroundWorkerClass() {
|
||||
return TurnOnWifiWorker.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Slice background worker {@link SliceBackgroundWorker} is used to listen the Wi-Fi
|
||||
* status change, and then notifies the Slice {@link Uri} to update.
|
||||
*/
|
||||
public static class TurnOnWifiWorker extends SliceBackgroundWorker {
|
||||
|
||||
private final IntentFilter mIntentFilter;
|
||||
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) {
|
||||
notifySliceChange();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public TurnOnWifiWorker(Context context, Uri uri) {
|
||||
super(context, uri);
|
||||
mIntentFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSlicePinned() {
|
||||
getContext().registerReceiver(mBroadcastReceiver, mIntentFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSliceUnpinned() {
|
||||
getContext().unregisterReceiver(mBroadcastReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,7 +113,7 @@ public class InternetConnectivityPanel implements PanelContent, LifecycleObserve
|
||||
final List<Uri> uris = new ArrayList<>();
|
||||
if (mIsProviderModelEnabled) {
|
||||
uris.add(CustomSliceRegistry.PROVIDER_MODEL_SLICE_URI);
|
||||
uris.add(CustomSliceRegistry.AIRPLANE_SAFE_NETWORKS_SLICE_URI);
|
||||
uris.add(CustomSliceRegistry.TURN_ON_WIFI_SLICE_URI);
|
||||
} else {
|
||||
uris.add(CustomSliceRegistry.WIFI_SLICE_URI);
|
||||
uris.add(CustomSliceRegistry.MOBILE_DATA_SLICE_URI);
|
||||
|
||||
@@ -39,8 +39,8 @@ import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
|
||||
import com.android.settings.location.LocationSlice;
|
||||
import com.android.settings.media.MediaOutputIndicatorSlice;
|
||||
import com.android.settings.media.RemoteMediaSlice;
|
||||
import com.android.settings.network.AirplaneSafeNetworksSlice;
|
||||
import com.android.settings.network.ProviderModelSlice;
|
||||
import com.android.settings.network.TurnOnWifiSlice;
|
||||
import com.android.settings.network.telephony.MobileDataSlice;
|
||||
import com.android.settings.notification.zen.ZenModeButtonPreferenceController;
|
||||
import com.android.settings.wifi.calling.WifiCallingSliceHelper;
|
||||
@@ -307,13 +307,13 @@ public class CustomSliceRegistry {
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Backing Uri for the Always On Slice.
|
||||
* Backing Uri for the Turn on Wi-Fi Slice.
|
||||
*/
|
||||
public static final Uri AIRPLANE_SAFE_NETWORKS_SLICE_URI = new Uri.Builder()
|
||||
public static final Uri TURN_ON_WIFI_SLICE_URI = new Uri.Builder()
|
||||
.scheme(ContentResolver.SCHEME_CONTENT)
|
||||
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
|
||||
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
|
||||
.appendPath("airplane_safe_networks")
|
||||
.appendPath("turn_on_wifi")
|
||||
.build();
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -337,7 +337,7 @@ public class CustomSliceRegistry {
|
||||
sUriToSlice.put(DARK_THEME_SLICE_URI, DarkThemeSlice.class);
|
||||
sUriToSlice.put(REMOTE_MEDIA_SLICE_URI, RemoteMediaSlice.class);
|
||||
sUriToSlice.put(ALWAYS_ON_SLICE_URI, AlwaysOnDisplaySlice.class);
|
||||
sUriToSlice.put(AIRPLANE_SAFE_NETWORKS_SLICE_URI, AirplaneSafeNetworksSlice.class);
|
||||
sUriToSlice.put(TURN_ON_WIFI_SLICE_URI, TurnOnWifiSlice.class);
|
||||
}
|
||||
|
||||
public static Class<? extends CustomSliceable> getSliceClassByUri(Uri uri) {
|
||||
|
||||
@@ -194,6 +194,27 @@ public class ActionDisabledByAdminDialogHelperTest {
|
||||
assertEquals("some message", Shadows.shadowOf(textView).innerText());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAdminSupportDetails_shortSupportMessageIsNull() {
|
||||
final ShadowDevicePolicyManager dpmShadow = ShadowDevicePolicyManager.getShadow();
|
||||
final UserManager userManager = RuntimeEnvironment.application.getSystemService(
|
||||
UserManager.class);
|
||||
final ShadowUserManager userManagerShadow = Shadow.extract(userManager);
|
||||
final ViewGroup view = new FrameLayout(mActivity);
|
||||
final ComponentName component = new ComponentName("some.package.name",
|
||||
"some.package.name.SomeClass");
|
||||
final EnforcedAdmin admin = new EnforcedAdmin(component, UserHandle.of(123));
|
||||
final TextView textView = createAdminSupportTextView(view, mActivity);
|
||||
dpmShadow.setShortSupportMessageForUser(component, 123, null);
|
||||
dpmShadow.setIsAdminActiveAsUser(true);
|
||||
createShadowWorkProfile(userManagerShadow);
|
||||
|
||||
mHelper.setAdminSupportDetails(mActivity, view, admin);
|
||||
|
||||
assertNotNull(admin.component);
|
||||
assertEquals("", Shadows.shadowOf(textView).innerText());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAdminSupportDetailsNotAdmin() {
|
||||
final ShadowDevicePolicyManager dpmShadow = ShadowDevicePolicyManager.getShadow();
|
||||
@@ -212,27 +233,6 @@ public class ActionDisabledByAdminDialogHelperTest {
|
||||
mHelper.setAdminSupportDetails(mActivity, textView, admin);
|
||||
|
||||
assertNull(admin.component);
|
||||
assertEquals(mActivity.getString(R.string.default_admin_support_msg),
|
||||
Shadows.shadowOf(textView).innerText());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAdminSupportDetailsForFinancedDevice_shortSupportMessageIsNull() {
|
||||
final ShadowDevicePolicyManager dpmShadow = ShadowDevicePolicyManager.getShadow();
|
||||
final UserManager userManager = RuntimeEnvironment.application.getSystemService(
|
||||
UserManager.class);
|
||||
final ShadowUserManager userManagerShadow = Shadow.extract(userManager);
|
||||
final ViewGroup view = new FrameLayout(mActivity);
|
||||
final ComponentName component = new ComponentName("some.package.name",
|
||||
"some.package.name.SomeClass");
|
||||
final EnforcedAdmin admin = new EnforcedAdmin(component, UserHandle.of(123));
|
||||
final TextView textView = createAdminSupportTextView(view, mActivity);
|
||||
setupFinancedDevice(dpmShadow);
|
||||
createShadowWorkProfile(userManagerShadow);
|
||||
|
||||
mHelper.setAdminSupportDetails(mActivity, view, admin);
|
||||
|
||||
assertNotNull(admin.component);
|
||||
assertEquals("", Shadows.shadowOf(textView).innerText());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications.autofill;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
import android.service.autofill.AutofillServiceInfo;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.google.android.collect.Lists;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class PasswordsPreferenceControllerTest {
|
||||
|
||||
private Context mContext;
|
||||
private PreferenceScreen mScreen;
|
||||
private PreferenceCategory mPasswordsPreferenceCategory;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
if (Looper.myLooper() == null) {
|
||||
Looper.prepare(); // needed to create the preference screen
|
||||
}
|
||||
mScreen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
|
||||
mPasswordsPreferenceCategory = new PreferenceCategory(mContext);
|
||||
mPasswordsPreferenceCategory.setKey("passwords");
|
||||
mScreen.addPreference(mPasswordsPreferenceCategory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_noServices_returnsUnavailable() {
|
||||
PasswordsPreferenceController controller =
|
||||
createControllerWithServices(Collections.emptyList());
|
||||
assertThat(controller.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_noPasswords_returnsUnavailable() {
|
||||
AutofillServiceInfo service = new AutofillServiceInfo.TestDataBuilder().build();
|
||||
PasswordsPreferenceController controller =
|
||||
createControllerWithServices(Lists.newArrayList(service));
|
||||
assertThat(controller.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_withPasswords_returnsAvailable() {
|
||||
PasswordsPreferenceController controller =
|
||||
createControllerWithServices(Lists.newArrayList(createServiceWithPasswords()));
|
||||
assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_noServices_noPreferencesAdded() {
|
||||
PasswordsPreferenceController controller =
|
||||
createControllerWithServices(Collections.emptyList());
|
||||
controller.displayPreference(mScreen);
|
||||
assertThat(mPasswordsPreferenceCategory.getPreferenceCount()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_noPasswords_noPreferencesAdded() {
|
||||
AutofillServiceInfo service = new AutofillServiceInfo.TestDataBuilder().build();
|
||||
PasswordsPreferenceController controller =
|
||||
createControllerWithServices(Lists.newArrayList(service));
|
||||
controller.displayPreference(mScreen);
|
||||
assertThat(mPasswordsPreferenceCategory.getPreferenceCount()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_withPasswords_addsPreference() {
|
||||
AutofillServiceInfo service = createServiceWithPasswords();
|
||||
PasswordsPreferenceController controller =
|
||||
createControllerWithServices(Lists.newArrayList(service));
|
||||
controller.displayPreference(mScreen);
|
||||
|
||||
assertThat(mPasswordsPreferenceCategory.getPreferenceCount()).isEqualTo(1);
|
||||
Preference pref = mPasswordsPreferenceCategory.getPreference(0);
|
||||
assertThat(pref.getIcon()).isNotNull();
|
||||
assertThat(pref.getIntent().getComponent())
|
||||
.isEqualTo(
|
||||
new ComponentName(
|
||||
service.getServiceInfo().packageName,
|
||||
service.getPasswordsActivity()));
|
||||
}
|
||||
|
||||
private PasswordsPreferenceController createControllerWithServices(
|
||||
List<AutofillServiceInfo> availableServices) {
|
||||
return new PasswordsPreferenceController(
|
||||
mContext, mPasswordsPreferenceCategory.getKey(), availableServices);
|
||||
}
|
||||
|
||||
private AutofillServiceInfo createServiceWithPasswords() {
|
||||
return new AutofillServiceInfo.TestDataBuilder()
|
||||
.setPasswordsActivity("com.android.test.Passwords")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.network;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.wifi.WifiManager;
|
||||
|
||||
import androidx.slice.Slice;
|
||||
import androidx.slice.SliceItem;
|
||||
import androidx.slice.SliceMetadata;
|
||||
import androidx.slice.SliceProvider;
|
||||
import androidx.slice.widget.SliceLiveData;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.testutils.ResourcesUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class AirplaneSafeNetworksSliceTest {
|
||||
|
||||
@Rule
|
||||
public MockitoRule mMocks = MockitoJUnit.rule();
|
||||
@Mock
|
||||
private WifiManager mWifiManager;
|
||||
|
||||
private Context mContext;
|
||||
private AirplaneSafeNetworksSlice mAirplaneSafeNetworksSlice;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
|
||||
|
||||
// Set-up specs for SliceMetadata.
|
||||
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
|
||||
|
||||
mAirplaneSafeNetworksSlice = new AirplaneSafeNetworksSlice(mContext);
|
||||
mAirplaneSafeNetworksSlice.onAirplaneModeChanged(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSlice_airplaneModeOff_shouldBeNotNull() {
|
||||
mAirplaneSafeNetworksSlice.onAirplaneModeChanged(false);
|
||||
|
||||
assertThat(mAirplaneSafeNetworksSlice.getSlice()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSlice_wifiDisabled_shouldShowTurnOnNetworks() {
|
||||
when(mWifiManager.isWifiEnabled()).thenReturn(false);
|
||||
|
||||
final Slice slice = mAirplaneSafeNetworksSlice.getSlice();
|
||||
|
||||
assertThat(slice).isNotNull();
|
||||
final SliceItem sliceTitle =
|
||||
SliceMetadata.from(mContext, slice).getListContent().getHeader().getTitleItem();
|
||||
assertThat(sliceTitle.getText()).isEqualTo(
|
||||
ResourcesUtils.getResourcesString(mContext, "turn_on_networks"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSlice_wifiEnabled_shouldShowTurnOffNetworks() {
|
||||
when(mWifiManager.isWifiEnabled()).thenReturn(true);
|
||||
|
||||
final Slice slice = mAirplaneSafeNetworksSlice.getSlice();
|
||||
|
||||
assertThat(slice).isNotNull();
|
||||
final SliceItem sliceTitle =
|
||||
SliceMetadata.from(mContext, slice).getListContent().getHeader().getTitleItem();
|
||||
assertThat(sliceTitle.getText()).isEqualTo(
|
||||
ResourcesUtils.getResourcesString(mContext, "turn_off_networks"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onNotifyChange_turnOnNetworks_shouldSetWifiEnabled() {
|
||||
when(mWifiManager.isWifiEnabled()).thenReturn(false);
|
||||
Intent intent = mAirplaneSafeNetworksSlice.getIntent();
|
||||
|
||||
mAirplaneSafeNetworksSlice.onNotifyChange(intent);
|
||||
|
||||
verify(mWifiManager).setWifiEnabled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onNotifyChange_turnOffNetworks_shouldSetWifiDisabled() {
|
||||
when(mWifiManager.isWifiEnabled()).thenReturn(true);
|
||||
Intent intent = mAirplaneSafeNetworksSlice.getIntent();
|
||||
|
||||
mAirplaneSafeNetworksSlice.onNotifyChange(intent);
|
||||
|
||||
verify(mWifiManager).setWifiEnabled(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.network;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.wifi.WifiManager;
|
||||
|
||||
import androidx.slice.SliceProvider;
|
||||
import androidx.slice.widget.SliceLiveData;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TurnOnWifiSliceTest {
|
||||
|
||||
@Rule
|
||||
public MockitoRule mMocks = MockitoJUnit.rule();
|
||||
@Mock
|
||||
private WifiManager mWifiManager;
|
||||
|
||||
private Context mContext;
|
||||
private TurnOnWifiSlice mSlice;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
|
||||
|
||||
// Set-up specs for SliceMetadata.
|
||||
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
|
||||
mSlice = new TurnOnWifiSlice(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSlice_wifiEnabled_shouldBeNull() {
|
||||
when(mWifiManager.isWifiEnabled()).thenReturn(true);
|
||||
|
||||
assertThat(mSlice.getSlice()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSlice_wifiDisabled_shouldBeNotNull() {
|
||||
when(mWifiManager.isWifiEnabled()).thenReturn(false);
|
||||
|
||||
assertThat(mSlice.getSlice()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onNotifyChange_shouldSetWifiEnabled() {
|
||||
Intent intent = mSlice.getIntent();
|
||||
|
||||
mSlice.onNotifyChange(intent);
|
||||
|
||||
verify(mWifiManager).setWifiEnabled(true);
|
||||
}
|
||||
}
|
||||
@@ -157,7 +157,7 @@ public class InternetConnectivityPanelTest {
|
||||
|
||||
assertThat(uris).containsExactly(
|
||||
CustomSliceRegistry.PROVIDER_MODEL_SLICE_URI,
|
||||
CustomSliceRegistry.AIRPLANE_SAFE_NETWORKS_SLICE_URI);
|
||||
CustomSliceRegistry.TURN_ON_WIFI_SLICE_URI);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user