Merge "Use framework-tethering-stub instead of framework-tethering"
This commit is contained in:
13
Android.bp
13
Android.bp
@@ -396,7 +396,6 @@ java_defaults {
|
||||
"ext",
|
||||
"unsupportedappusage",
|
||||
"updatable_media_stubs",
|
||||
"framework-tethering",
|
||||
],
|
||||
|
||||
jarjar_rules: ":framework-jarjar-rules",
|
||||
@@ -455,7 +454,10 @@ java_library {
|
||||
name: "framework-minus-apex",
|
||||
defaults: ["framework-defaults"],
|
||||
srcs: [":framework-non-updatable-sources"],
|
||||
libs: ["ike-stubs"],
|
||||
libs: [
|
||||
"ike-stubs",
|
||||
"framework-tethering-stubs",
|
||||
],
|
||||
installable: true,
|
||||
javac_shard_size: 150,
|
||||
required: [
|
||||
@@ -471,6 +473,10 @@ java_library {
|
||||
// For backwards compatibility.
|
||||
stem: "framework",
|
||||
apex_available: ["//apex_available:platform"],
|
||||
visibility: [
|
||||
// TODO(b/147128803) remove the below lines
|
||||
"//frameworks/base/packages/Tethering/tests/unit",
|
||||
],
|
||||
}
|
||||
|
||||
// This "framework" module is NOT installed to the device. It's
|
||||
@@ -490,9 +496,8 @@ java_library {
|
||||
"framework-minus-apex",
|
||||
"updatable_media_stubs",
|
||||
"framework-sdkextensions-stubs-systemapi",
|
||||
// TODO(b/147200698): should be the stub of framework-tethering
|
||||
"framework-tethering",
|
||||
"ike-stubs",
|
||||
"framework-tethering-stubs",
|
||||
],
|
||||
sdk_version: "core_platform",
|
||||
apex_available: ["//apex_available:platform"],
|
||||
|
||||
@@ -9,3 +9,124 @@ package android.annotation {
|
||||
|
||||
}
|
||||
|
||||
package android.net {
|
||||
|
||||
public final class TetheredClient implements android.os.Parcelable {
|
||||
ctor public TetheredClient(@NonNull android.net.MacAddress, @NonNull java.util.Collection<android.net.TetheredClient.AddressInfo>, int);
|
||||
method public int describeContents();
|
||||
method @NonNull public java.util.List<android.net.TetheredClient.AddressInfo> getAddresses();
|
||||
method @NonNull public android.net.MacAddress getMacAddress();
|
||||
method public int getTetheringType();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient> CREATOR;
|
||||
}
|
||||
|
||||
public static final class TetheredClient.AddressInfo implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method @NonNull public android.net.LinkAddress getAddress();
|
||||
method @Nullable public String getHostname();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient.AddressInfo> CREATOR;
|
||||
}
|
||||
|
||||
public class TetheringConstants {
|
||||
ctor public TetheringConstants();
|
||||
field public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
|
||||
field public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
|
||||
field public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
|
||||
field public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
|
||||
field public static final String EXTRA_SET_ALARM = "extraSetAlarm";
|
||||
}
|
||||
|
||||
public class TetheringManager {
|
||||
ctor public TetheringManager(@NonNull android.content.Context, @NonNull java.util.function.Supplier<android.os.IBinder>);
|
||||
method public int getLastTetherError(@NonNull String);
|
||||
method @NonNull public String[] getTetherableBluetoothRegexs();
|
||||
method @NonNull public String[] getTetherableIfaces();
|
||||
method @NonNull public String[] getTetherableUsbRegexs();
|
||||
method @NonNull public String[] getTetherableWifiRegexs();
|
||||
method @NonNull public String[] getTetheredIfaces();
|
||||
method @NonNull public String[] getTetheringErroredIfaces();
|
||||
method public boolean isTetheringSupported();
|
||||
method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheringEventCallback);
|
||||
method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener);
|
||||
method public void requestLatestTetheringEntitlementResult(int, @NonNull android.os.ResultReceiver, boolean);
|
||||
method @Deprecated public int setUsbTethering(boolean);
|
||||
method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(@NonNull android.net.TetheringManager.TetheringRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
|
||||
method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(int, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
|
||||
method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void stopAllTethering();
|
||||
method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void stopTethering(int);
|
||||
method @Deprecated public int tether(@NonNull String);
|
||||
method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.ACCESS_NETWORK_STATE}) public void unregisterTetheringEventCallback(@NonNull android.net.TetheringManager.TetheringEventCallback);
|
||||
method @Deprecated public int untether(@NonNull String);
|
||||
field public static final String ACTION_TETHER_STATE_CHANGED = "android.net.conn.TETHER_STATE_CHANGED";
|
||||
field public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY";
|
||||
field public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
|
||||
field public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
|
||||
field public static final String EXTRA_ERRORED_TETHER = "erroredArray";
|
||||
field public static final int TETHERING_BLUETOOTH = 2; // 0x2
|
||||
field public static final int TETHERING_ETHERNET = 5; // 0x5
|
||||
field public static final int TETHERING_INVALID = -1; // 0xffffffff
|
||||
field public static final int TETHERING_NCM = 4; // 0x4
|
||||
field public static final int TETHERING_USB = 1; // 0x1
|
||||
field public static final int TETHERING_WIFI = 0; // 0x0
|
||||
field public static final int TETHERING_WIFI_P2P = 3; // 0x3
|
||||
field public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12; // 0xc
|
||||
field public static final int TETHER_ERROR_DISABLE_NAT_ERROR = 9; // 0x9
|
||||
field public static final int TETHER_ERROR_ENABLE_NAT_ERROR = 8; // 0x8
|
||||
field public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13; // 0xd
|
||||
field public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10; // 0xa
|
||||
field public static final int TETHER_ERROR_MASTER_ERROR = 5; // 0x5
|
||||
field public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15; // 0xf
|
||||
field public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14; // 0xe
|
||||
field public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
|
||||
field public static final int TETHER_ERROR_PROVISION_FAILED = 11; // 0xb
|
||||
field public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2; // 0x2
|
||||
field public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6; // 0x6
|
||||
field public static final int TETHER_ERROR_UNAVAIL_IFACE = 4; // 0x4
|
||||
field public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; // 0x1
|
||||
field public static final int TETHER_ERROR_UNSUPPORTED = 3; // 0x3
|
||||
field public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7; // 0x7
|
||||
}
|
||||
|
||||
public static interface TetheringManager.OnTetheringEntitlementResultListener {
|
||||
method public void onTetheringEntitlementResult(int);
|
||||
}
|
||||
|
||||
public abstract static class TetheringManager.StartTetheringCallback {
|
||||
ctor public TetheringManager.StartTetheringCallback();
|
||||
method public void onTetheringFailed(int);
|
||||
method public void onTetheringStarted();
|
||||
}
|
||||
|
||||
public abstract static class TetheringManager.TetheringEventCallback {
|
||||
ctor public TetheringManager.TetheringEventCallback();
|
||||
method public void onClientsChanged(@NonNull java.util.Collection<android.net.TetheredClient>);
|
||||
method public void onError(@NonNull String, int);
|
||||
method @Deprecated public void onTetherableInterfaceRegexpsChanged(@NonNull android.net.TetheringManager.TetheringInterfaceRegexps);
|
||||
method public void onTetherableInterfacesChanged(@NonNull java.util.List<java.lang.String>);
|
||||
method public void onTetheredInterfacesChanged(@NonNull java.util.List<java.lang.String>);
|
||||
method public void onTetheringSupported(boolean);
|
||||
method public void onUpstreamChanged(@Nullable android.net.Network);
|
||||
}
|
||||
|
||||
@Deprecated public static class TetheringManager.TetheringInterfaceRegexps {
|
||||
ctor @Deprecated public TetheringManager.TetheringInterfaceRegexps(@NonNull String[], @NonNull String[], @NonNull String[]);
|
||||
method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableBluetoothRegexs();
|
||||
method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableUsbRegexs();
|
||||
method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableWifiRegexs();
|
||||
}
|
||||
|
||||
public static class TetheringManager.TetheringRequest {
|
||||
}
|
||||
|
||||
public static class TetheringManager.TetheringRequest.Builder {
|
||||
ctor public TetheringManager.TetheringRequest.Builder(int);
|
||||
method @NonNull public android.net.TetheringManager.TetheringRequest build();
|
||||
method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder setExemptFromEntitlementCheck(boolean);
|
||||
method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder setSilentProvisioning(boolean);
|
||||
method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder useStaticIpv4Addresses(@NonNull android.net.LinkAddress);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -2424,14 +2424,14 @@ public class ConnectivityManager {
|
||||
/**
|
||||
* Get the set of tethered dhcp ranges.
|
||||
*
|
||||
* @return an array of 0 or more {@code String} of tethered dhcp ranges.
|
||||
* @deprecated This API just return the default value which is not used in DhcpServer.
|
||||
* @deprecated This method is not supported.
|
||||
* TODO: remove this function when all of clients are removed.
|
||||
* {@hide}
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
|
||||
@Deprecated
|
||||
public String[] getTetheredDhcpRanges() {
|
||||
return getTetheringManager().getTetheredDhcpRanges();
|
||||
throw new UnsupportedOperationException("getTetheredDhcpRanges is not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -59,16 +59,33 @@ java_library {
|
||||
],
|
||||
|
||||
hostdex: true, // for hiddenapi check
|
||||
visibility: [
|
||||
"//frameworks/base/packages/Tethering:__subpackages__",
|
||||
//TODO(b/147200698) remove below lines when the platform is built with stubs
|
||||
"//frameworks/base",
|
||||
"//frameworks/base/services",
|
||||
"//frameworks/base/services/core",
|
||||
],
|
||||
visibility: ["//frameworks/base/packages/Tethering:__subpackages__"],
|
||||
apex_available: ["com.android.tethering"],
|
||||
}
|
||||
|
||||
droidstubs {
|
||||
name: "framework-tethering-stubs-sources",
|
||||
defaults: ["framework-module-stubs-defaults-module_libs_api"],
|
||||
srcs: [
|
||||
"src/android/net/TetheredClient.java",
|
||||
"src/android/net/TetheringManager.java",
|
||||
"src/android/net/TetheringConstants.java",
|
||||
],
|
||||
libs: [
|
||||
"tethering-aidl-interfaces-java",
|
||||
"framework-all",
|
||||
],
|
||||
sdk_version: "core_platform",
|
||||
}
|
||||
|
||||
java_library {
|
||||
name: "framework-tethering-stubs",
|
||||
srcs: [":framework-tethering-stubs-sources"],
|
||||
libs: ["framework-all"],
|
||||
static_libs: ["tethering-aidl-interfaces-java"],
|
||||
sdk_version: "core_platform",
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "framework-tethering-srcs",
|
||||
srcs: [
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package android.net;
|
||||
|
||||
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemApi;
|
||||
@@ -34,6 +36,7 @@ import java.util.Objects;
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
@TestApi
|
||||
public final class TetheredClient implements Parcelable {
|
||||
@NonNull
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package android.net;
|
||||
|
||||
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
|
||||
|
||||
import android.annotation.SystemApi;
|
||||
import android.os.ResultReceiver;
|
||||
|
||||
/**
|
||||
@@ -28,39 +31,30 @@ import android.os.ResultReceiver;
|
||||
* symbols from framework-tethering even when they are in a non-hidden class.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public class TetheringConstants {
|
||||
/**
|
||||
* Extra used for communicating with the TetherService. Includes the type of tethering to
|
||||
* enable if any.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
|
||||
/**
|
||||
* Extra used for communicating with the TetherService. Includes the type of tethering for
|
||||
* which to cancel provisioning.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
|
||||
/**
|
||||
* Extra used for communicating with the TetherService. True to schedule a recheck of tether
|
||||
* provisioning.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public static final String EXTRA_SET_ALARM = "extraSetAlarm";
|
||||
/**
|
||||
* Tells the TetherService to run a provision check now.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
|
||||
/**
|
||||
* Extra used for communicating with the TetherService. Contains the {@link ResultReceiver}
|
||||
* which will receive provisioning results. Can be left empty.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package android.net;
|
||||
|
||||
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -50,6 +52,7 @@ import java.util.function.Supplier;
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
@TestApi
|
||||
public class TetheringManager {
|
||||
private static final String TAG = TetheringManager.class.getSimpleName();
|
||||
@@ -177,6 +180,7 @@ public class TetheringManager {
|
||||
* service is not connected.
|
||||
* {@hide}
|
||||
*/
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public TetheringManager(@NonNull final Context context,
|
||||
@NonNull Supplier<IBinder> connectorSupplier) {
|
||||
mContext = context;
|
||||
@@ -395,6 +399,7 @@ public class TetheringManager {
|
||||
* {@hide}
|
||||
*/
|
||||
@Deprecated
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public int tether(@NonNull final String iface) {
|
||||
final String callerPkg = mContext.getOpPackageName();
|
||||
Log.i(TAG, "tether caller:" + callerPkg);
|
||||
@@ -418,6 +423,7 @@ public class TetheringManager {
|
||||
* {@hide}
|
||||
*/
|
||||
@Deprecated
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public int untether(@NonNull final String iface) {
|
||||
final String callerPkg = mContext.getOpPackageName();
|
||||
Log.i(TAG, "untether caller:" + callerPkg);
|
||||
@@ -444,6 +450,7 @@ public class TetheringManager {
|
||||
* {@hide}
|
||||
*/
|
||||
@Deprecated
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public int setUsbTethering(final boolean enable) {
|
||||
final String callerPkg = mContext.getOpPackageName();
|
||||
Log.i(TAG, "setUsbTethering caller:" + callerPkg);
|
||||
@@ -702,6 +709,7 @@ public class TetheringManager {
|
||||
* {@hide}
|
||||
*/
|
||||
// TODO: improve the usage of ResultReceiver, b/145096122
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public void requestLatestTetheringEntitlementResult(final int type,
|
||||
@NonNull final ResultReceiver receiver, final boolean showEntitlementUi) {
|
||||
final String callerPkg = mContext.getOpPackageName();
|
||||
@@ -982,6 +990,7 @@ public class TetheringManager {
|
||||
* interface
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public int getLastTetherError(@NonNull final String iface) {
|
||||
mCallback.waitForStarted();
|
||||
if (mTetherStatesParcel == null) return TETHER_ERROR_NO_ERROR;
|
||||
@@ -1004,6 +1013,7 @@ public class TetheringManager {
|
||||
* what interfaces are considered tetherable usb interfaces.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public @NonNull String[] getTetherableUsbRegexs() {
|
||||
mCallback.waitForStarted();
|
||||
return mTetheringConfiguration.tetherableUsbRegexs;
|
||||
@@ -1018,6 +1028,7 @@ public class TetheringManager {
|
||||
* what interfaces are considered tetherable wifi interfaces.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public @NonNull String[] getTetherableWifiRegexs() {
|
||||
mCallback.waitForStarted();
|
||||
return mTetheringConfiguration.tetherableWifiRegexs;
|
||||
@@ -1032,6 +1043,7 @@ public class TetheringManager {
|
||||
* what interfaces are considered tetherable bluetooth interfaces.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public @NonNull String[] getTetherableBluetoothRegexs() {
|
||||
mCallback.waitForStarted();
|
||||
return mTetheringConfiguration.tetherableBluetoothRegexs;
|
||||
@@ -1044,6 +1056,7 @@ public class TetheringManager {
|
||||
* @return an array of 0 or more Strings of tetherable interface names.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public @NonNull String[] getTetherableIfaces() {
|
||||
mCallback.waitForStarted();
|
||||
if (mTetherStatesParcel == null) return new String[0];
|
||||
@@ -1057,6 +1070,7 @@ public class TetheringManager {
|
||||
* @return an array of 0 or more String of currently tethered interface names.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public @NonNull String[] getTetheredIfaces() {
|
||||
mCallback.waitForStarted();
|
||||
if (mTetherStatesParcel == null) return new String[0];
|
||||
@@ -1076,6 +1090,7 @@ public class TetheringManager {
|
||||
* which failed to tether.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public @NonNull String[] getTetheringErroredIfaces() {
|
||||
mCallback.waitForStarted();
|
||||
if (mTetherStatesParcel == null) return new String[0];
|
||||
@@ -1103,6 +1118,7 @@ public class TetheringManager {
|
||||
* @return a boolean - {@code true} indicating Tethering is supported.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public boolean isTetheringSupported() {
|
||||
final String callerPkg = mContext.getOpPackageName();
|
||||
|
||||
|
||||
@@ -34,7 +34,13 @@ android_test {
|
||||
"TetheringApiCurrentLib",
|
||||
"testables",
|
||||
],
|
||||
// TODO(b/147200698) change sdk_version to module-current and
|
||||
// remove framework-minus-apex, ext, and framework-res
|
||||
sdk_version: "core_platform",
|
||||
libs: [
|
||||
"framework-minus-apex",
|
||||
"ext",
|
||||
"framework-res",
|
||||
"android.test.runner",
|
||||
"android.test.base",
|
||||
"android.test.mock",
|
||||
|
||||
@@ -72,7 +72,7 @@ java_library {
|
||||
|
||||
libs: [
|
||||
"android.hidl.manager-V1.0-java",
|
||||
"framework-tethering"
|
||||
"framework-tethering-stubs",
|
||||
],
|
||||
|
||||
plugins: [
|
||||
|
||||
@@ -29,7 +29,7 @@ java_library_static {
|
||||
"android.hardware.tv.cec-V1.0-java",
|
||||
"android.hardware.vibrator-java",
|
||||
"app-compat-annotations",
|
||||
"framework-tethering",
|
||||
"framework-tethering-stubs",
|
||||
],
|
||||
|
||||
required: [
|
||||
|
||||
Reference in New Issue
Block a user