Implement reminder power dialog and invalid charger dialog.
Bug: 2510318 Bug: 2974431 Change-Id: I92eb419eeffb657e5572a35a490735a96b303d6b
This commit is contained in:
@@ -87,7 +87,7 @@ public class BatteryManager {
|
||||
|
||||
/**
|
||||
* Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
|
||||
* Boolean value set to true if an unsupported charger is attached
|
||||
* Int value set to nonzero if an unsupported charger is attached
|
||||
* to the device.
|
||||
* {@hide}
|
||||
*/
|
||||
|
||||
@@ -290,6 +290,11 @@
|
||||
|
||||
<bool name="config_use_strict_phone_number_comparation">false</bool>
|
||||
|
||||
<!-- Display low battery warning when battery level dips to this value.
|
||||
Also, the battery stats are flushed to disk when we hit this level. -->
|
||||
<integer name="config_criticalBatteryWarningLevel">4</integer>
|
||||
|
||||
<!-- Display low battery warning when battery level dips to this value -->
|
||||
<!-- Display low battery warning when battery level dips to this value -->
|
||||
<integer name="config_lowBatteryWarningLevel">15</integer>
|
||||
|
||||
|
||||
@@ -53,11 +53,17 @@
|
||||
<string name="battery_low_title">Please connect charger</string>
|
||||
|
||||
<!-- When the battery is low, this is displayed to the user in a dialog. The subtitle of the low battery alert. -->
|
||||
<string name="battery_low_subtitle">The battery is getting low:</string>
|
||||
<string name="battery_low_subtitle">The battery is getting low.</string>
|
||||
|
||||
<!-- A message that appears when the battery level is getting low in a dialog. This is appened to the subtitle of the low battery alert. -->
|
||||
<string name="battery_low_percent_format"><xliff:g id="number">%d%%</xliff:g>
|
||||
or less remaining.</string>
|
||||
<!-- A message that appears when the battery level is getting low in a dialog. This is
|
||||
appened to the subtitle of the low battery alert. -->
|
||||
<string name="battery_low_percent_format"><xliff:g id="number">%d%%</xliff:g> remaining</string>
|
||||
|
||||
<!-- A message that appears when a USB charger is plugged in and the device does not
|
||||
support charging on it. That is, a charger that fits into the USB port and goes into
|
||||
a wall socket, not into a computer. (This happens because some devices require more
|
||||
current than the USB spec allows. -->
|
||||
<string name="invalid_charger">USB charging not supported.\nUse only the supplied charger.</string>
|
||||
|
||||
<!-- When the battery is low, this is the label of the button to go to the
|
||||
power usage activity to find out what drained the battery. -->
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.Uri;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Handler;
|
||||
import android.media.AudioManager;
|
||||
import android.media.Ringtone;
|
||||
@@ -46,32 +47,116 @@ public class PowerUI extends SystemUI {
|
||||
|
||||
Handler mHandler = new Handler();
|
||||
|
||||
int mBatteryLevel = 100;
|
||||
int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
|
||||
int mPlugType = 0;
|
||||
int mInvalidCharger = 0;
|
||||
|
||||
int mLowBatteryAlertCloseLevel;
|
||||
int[] mLowBatteryReminderLevels = new int[2];
|
||||
|
||||
AlertDialog mInvalidChargerDialog;
|
||||
AlertDialog mLowBatteryDialog;
|
||||
int mBatteryLevel;
|
||||
TextView mBatteryLevelTextView;
|
||||
|
||||
public void start() {
|
||||
|
||||
mLowBatteryAlertCloseLevel = mContext.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_lowBatteryCloseWarningLevel);
|
||||
mLowBatteryReminderLevels[0] = mContext.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_lowBatteryWarningLevel);
|
||||
mLowBatteryReminderLevels[1] = mContext.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
|
||||
|
||||
// Register for Intent broadcasts for...
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
||||
filter.addAction(Intent.ACTION_BATTERY_LOW);
|
||||
filter.addAction(Intent.ACTION_BATTERY_OKAY);
|
||||
filter.addAction(Intent.ACTION_POWER_CONNECTED);
|
||||
mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Buckets the battery level.
|
||||
*
|
||||
* The code in this function is a little weird because I couldn't comprehend
|
||||
* the bucket going up when the battery level was going down. --joeo
|
||||
*
|
||||
* 1 means that the battery is "ok"
|
||||
* 0 means that the battery is between "ok" and what we should warn about.
|
||||
* less than 0 means that the battery is low
|
||||
*/
|
||||
private int findBatteryLevelBucket(int level) {
|
||||
if (level >= mLowBatteryAlertCloseLevel) {
|
||||
return 1;
|
||||
}
|
||||
if (level >= mLowBatteryReminderLevels[0]) {
|
||||
return 0;
|
||||
}
|
||||
final int N = mLowBatteryReminderLevels.length;
|
||||
for (int i=N-1; i>=0; i--) {
|
||||
if (level <= mLowBatteryReminderLevels[i]) {
|
||||
return -1-i;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("not possible!");
|
||||
}
|
||||
|
||||
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
|
||||
mBatteryLevel = intent.getIntExtra("level", -1);
|
||||
} else if (action.equals(Intent.ACTION_BATTERY_LOW)) {
|
||||
showLowBatteryWarning();
|
||||
} else if (action.equals(Intent.ACTION_BATTERY_OKAY)
|
||||
|| action.equals(Intent.ACTION_POWER_CONNECTED)) {
|
||||
if (mLowBatteryDialog != null) {
|
||||
mLowBatteryDialog.dismiss();
|
||||
final int oldBatteryLevel = mBatteryLevel;
|
||||
mBatteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 100);
|
||||
final int oldBatteryStatus = mBatteryStatus;
|
||||
mBatteryStatus = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
|
||||
BatteryManager.BATTERY_STATUS_UNKNOWN);
|
||||
final int oldPlugType = mPlugType;
|
||||
mPlugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 1);
|
||||
final int oldInvalidCharger = mInvalidCharger;
|
||||
mInvalidCharger = intent.getIntExtra(BatteryManager.EXTRA_INVALID_CHARGER, 0);
|
||||
|
||||
final boolean plugged = mPlugType != 0;
|
||||
final boolean oldPlugged = oldPlugType != 0;
|
||||
|
||||
int oldBucket = findBatteryLevelBucket(oldBatteryLevel);
|
||||
int bucket = findBatteryLevelBucket(mBatteryLevel);
|
||||
|
||||
if (false) {
|
||||
Slog.d(TAG, "buckets ....." + mLowBatteryAlertCloseLevel
|
||||
+ " .. " + mLowBatteryReminderLevels[0]
|
||||
+ " .. " + mLowBatteryReminderLevels[1]);
|
||||
Slog.d(TAG, "level " + oldBatteryLevel + " --> " + mBatteryLevel);
|
||||
Slog.d(TAG, "status " + oldBatteryStatus + " --> " + mBatteryStatus);
|
||||
Slog.d(TAG, "plugType " + oldPlugType + " --> " + mPlugType);
|
||||
Slog.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger);
|
||||
Slog.d(TAG, "bucket " + oldBucket + " --> " + bucket);
|
||||
Slog.d(TAG, "plugged " + oldPlugged + " --> " + plugged);
|
||||
}
|
||||
|
||||
if (oldInvalidCharger == 0 && mInvalidCharger != 0) {
|
||||
Slog.d(TAG, "showing invalid charger warning");
|
||||
showInvalidChargerDialog();
|
||||
return;
|
||||
} else if (oldInvalidCharger != 0 && mInvalidCharger == 0) {
|
||||
Slog.d(TAG, "closing invalid charger warning");
|
||||
dismissInvalidChargerDialog();
|
||||
} else if (mInvalidChargerDialog != null) {
|
||||
// if invalid charger is showing, don't show low battery
|
||||
return;
|
||||
}
|
||||
|
||||
if (!plugged
|
||||
&& (bucket < oldBucket || oldPlugged)
|
||||
&& mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
|
||||
&& bucket < 0) {
|
||||
Slog.d(TAG, "showing low battery warning: level=" + mBatteryLevel);
|
||||
showLowBatteryWarning();
|
||||
} else if (plugged || (bucket > oldBucket && bucket > 0)) {
|
||||
Slog.d(TAG, "closing low battery warning: level=" + mBatteryLevel);
|
||||
dismissLowBatteryWarning();
|
||||
} else if (mBatteryLevelTextView != null) {
|
||||
showLowBatteryWarning();
|
||||
}
|
||||
} else {
|
||||
Slog.w(TAG, "unknown intent: " + intent);
|
||||
@@ -79,6 +164,12 @@ public class PowerUI extends SystemUI {
|
||||
}
|
||||
};
|
||||
|
||||
void dismissLowBatteryWarning() {
|
||||
if (mLowBatteryDialog != null) {
|
||||
mLowBatteryDialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
void showLowBatteryWarning() {
|
||||
CharSequence levelText = mContext.getString(
|
||||
R.string.battery_low_percent_format, mBatteryLevel);
|
||||
@@ -98,25 +189,30 @@ public class PowerUI extends SystemUI {
|
||||
b.setIcon(android.R.drawable.ic_dialog_alert);
|
||||
b.setPositiveButton(android.R.string.ok, null);
|
||||
|
||||
final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK
|
||||
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
|
||||
| Intent.FLAG_ACTIVITY_NO_HISTORY);
|
||||
if (intent.resolveActivity(mContext.getPackageManager()) != null) {
|
||||
b.setNegativeButton(R.string.battery_low_why,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
mContext.startActivity(intent);
|
||||
if (mLowBatteryDialog != null) {
|
||||
mLowBatteryDialog.dismiss();
|
||||
}
|
||||
final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK
|
||||
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
|
||||
| Intent.FLAG_ACTIVITY_NO_HISTORY);
|
||||
if (intent.resolveActivity(mContext.getPackageManager()) != null) {
|
||||
b.setNegativeButton(R.string.battery_low_why,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
mContext.startActivity(intent);
|
||||
if (mLowBatteryDialog != null) {
|
||||
mLowBatteryDialog.dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AlertDialog d = b.create();
|
||||
d.setOnDismissListener(mLowBatteryListener);
|
||||
d.setOnDismissListener(new DialogInterface.OnDismissListener() {
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
mLowBatteryDialog = null;
|
||||
mBatteryLevelTextView = null;
|
||||
}
|
||||
});
|
||||
d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
|
||||
d.show();
|
||||
mLowBatteryDialog = d;
|
||||
@@ -141,45 +237,53 @@ if (false) { // getRingtone ANRs
|
||||
}
|
||||
}
|
||||
|
||||
private DialogInterface.OnDismissListener mLowBatteryListener
|
||||
= new DialogInterface.OnDismissListener() {
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
mLowBatteryDialog = null;
|
||||
mBatteryLevelTextView = null;
|
||||
void dismissInvalidChargerDialog() {
|
||||
if (mInvalidChargerDialog != null) {
|
||||
mInvalidChargerDialog.dismiss();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void showInvalidChargerDialog() {
|
||||
dismissLowBatteryWarning();
|
||||
|
||||
AlertDialog.Builder b = new AlertDialog.Builder(mContext);
|
||||
b.setCancelable(true);
|
||||
b.setMessage(mContext.getString(R.string.invalid_charger));
|
||||
b.setIcon(android.R.drawable.ic_dialog_alert);
|
||||
b.setPositiveButton(android.R.string.ok, null);
|
||||
|
||||
AlertDialog d = b.create();
|
||||
d.setOnDismissListener(new DialogInterface.OnDismissListener() {
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
mInvalidChargerDialog = null;
|
||||
mBatteryLevelTextView = null;
|
||||
}
|
||||
});
|
||||
|
||||
d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
|
||||
d.show();
|
||||
mInvalidChargerDialog = d;
|
||||
}
|
||||
|
||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
if (false) {
|
||||
pw.println("args=" + Arrays.toString(args));
|
||||
}
|
||||
if (args == null || args.length == 0) {
|
||||
pw.print("mLowBatteryDialog=");
|
||||
pw.println(mLowBatteryDialog == null ? "null" : mLowBatteryDialog.toString());
|
||||
pw.print("mBatteryLevel=");
|
||||
pw.println(Integer.toString(mBatteryLevel));
|
||||
}
|
||||
|
||||
// DO NOT SUBMIT with this turned on.
|
||||
if (false) {
|
||||
if (args.length == 3 && "level".equals(args[1])) {
|
||||
try {
|
||||
final int level = Integer.parseInt(args[2]);
|
||||
Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
|
||||
intent.putExtra("level", level);
|
||||
mIntentReceiver.onReceive(mContext, intent);
|
||||
} catch (NumberFormatException ex) {
|
||||
pw.println(ex);
|
||||
}
|
||||
} else if (args.length == 2 && "low".equals(args[1])) {
|
||||
Intent intent = new Intent(Intent.ACTION_BATTERY_LOW);
|
||||
mIntentReceiver.onReceive(mContext, intent);
|
||||
} else if (args.length == 2 && "ok".equals(args[1])) {
|
||||
Intent intent = new Intent(Intent.ACTION_BATTERY_OKAY);
|
||||
mIntentReceiver.onReceive(mContext, intent);
|
||||
}
|
||||
}
|
||||
pw.print("mLowBatteryAlertCloseLevel=");
|
||||
pw.println(mLowBatteryAlertCloseLevel);
|
||||
pw.print("mLowBatteryReminderLevels=");
|
||||
pw.println(Arrays.toString(mLowBatteryReminderLevels));
|
||||
pw.print("mInvalidChargerDialog=");
|
||||
pw.println(mInvalidChargerDialog == null ? "null" : mInvalidChargerDialog.toString());
|
||||
pw.print("mLowBatteryDialog=");
|
||||
pw.println(mLowBatteryDialog == null ? "null" : mLowBatteryDialog.toString());
|
||||
pw.print("mBatteryLevel=");
|
||||
pw.println(Integer.toString(mBatteryLevel));
|
||||
pw.print("mBatteryStatus=");
|
||||
pw.println(Integer.toString(mBatteryStatus));
|
||||
pw.print("mPlugType=");
|
||||
pw.println(Integer.toString(mPlugType));
|
||||
pw.print("mInvalidCharger=");
|
||||
pw.println(Integer.toString(mInvalidCharger));
|
||||
pw.print("bucket: ");
|
||||
pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
/**
|
||||
@@ -76,7 +77,7 @@ class BatteryService extends Binder {
|
||||
|
||||
// Used locally for determining when to make a last ditch effort to log
|
||||
// discharge stats before the device dies.
|
||||
private static final int CRITICAL_BATTERY_LEVEL = 4;
|
||||
private int mCriticalBatteryLevel;
|
||||
|
||||
private static final int DUMP_MAX_LENGTH = 24 * 1024;
|
||||
private static final String[] DUMPSYS_ARGS = new String[] { "--checkin", "-u" };
|
||||
@@ -100,7 +101,7 @@ class BatteryService extends Binder {
|
||||
private int mBatteryTemperature;
|
||||
private String mBatteryTechnology;
|
||||
private boolean mBatteryLevelCritical;
|
||||
private boolean mInvalidCharger;
|
||||
private int mInvalidCharger;
|
||||
|
||||
private int mLastBatteryStatus;
|
||||
private int mLastBatteryHealth;
|
||||
@@ -109,7 +110,7 @@ class BatteryService extends Binder {
|
||||
private int mLastBatteryVoltage;
|
||||
private int mLastBatteryTemperature;
|
||||
private boolean mLastBatteryLevelCritical;
|
||||
private boolean mLastInvalidCharger;
|
||||
private int mLastInvalidCharger;
|
||||
|
||||
private int mLowBatteryWarningLevel;
|
||||
private int mLowBatteryCloseWarningLevel;
|
||||
@@ -129,6 +130,8 @@ class BatteryService extends Binder {
|
||||
mLed = new Led(context, lights);
|
||||
mBatteryStats = BatteryStatsService.getService();
|
||||
|
||||
mCriticalBatteryLevel = mContext.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
|
||||
mLowBatteryWarningLevel = mContext.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_lowBatteryWarningLevel);
|
||||
mLowBatteryCloseWarningLevel = mContext.getResources().getInteger(
|
||||
@@ -183,7 +186,7 @@ class BatteryService extends Binder {
|
||||
private UEventObserver mInvalidChargerObserver = new UEventObserver() {
|
||||
@Override
|
||||
public void onUEvent(UEventObserver.UEvent event) {
|
||||
boolean invalidCharger = "1".equals(event.get("SWITCH_STATE"));
|
||||
int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0;
|
||||
if (mInvalidCharger != invalidCharger) {
|
||||
mInvalidCharger = invalidCharger;
|
||||
update();
|
||||
@@ -228,11 +231,14 @@ class BatteryService extends Binder {
|
||||
|
||||
private synchronized final void update() {
|
||||
native_update();
|
||||
processValues();
|
||||
}
|
||||
|
||||
private void processValues() {
|
||||
boolean logOutlier = false;
|
||||
long dischargeDuration = 0;
|
||||
|
||||
mBatteryLevelCritical = mBatteryLevel <= CRITICAL_BATTERY_LEVEL;
|
||||
mBatteryLevelCritical = mBatteryLevel <= mCriticalBatteryLevel;
|
||||
if (mAcOnline) {
|
||||
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
|
||||
} else if (mUsbOnline) {
|
||||
@@ -384,8 +390,8 @@ class BatteryService extends Binder {
|
||||
intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryTechnology);
|
||||
intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger);
|
||||
|
||||
if (false) {
|
||||
Slog.d(TAG, "updateBattery level:" + mBatteryLevel +
|
||||
if (true) {
|
||||
Slog.d(TAG, "level:" + mBatteryLevel +
|
||||
" scale:" + BATTERY_SCALE + " status:" + mBatteryStatus +
|
||||
" health:" + mBatteryHealth + " present:" + mBatteryPresent +
|
||||
" voltage: " + mBatteryVoltage +
|
||||
@@ -487,18 +493,47 @@ class BatteryService extends Binder {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
pw.println("Current Battery Service state:");
|
||||
pw.println(" AC powered: " + mAcOnline);
|
||||
pw.println(" USB powered: " + mUsbOnline);
|
||||
pw.println(" status: " + mBatteryStatus);
|
||||
pw.println(" health: " + mBatteryHealth);
|
||||
pw.println(" present: " + mBatteryPresent);
|
||||
pw.println(" level: " + mBatteryLevel);
|
||||
pw.println(" scale: " + BATTERY_SCALE);
|
||||
pw.println(" voltage:" + mBatteryVoltage);
|
||||
pw.println(" temperature: " + mBatteryTemperature);
|
||||
pw.println(" technology: " + mBatteryTechnology);
|
||||
if (args == null || args.length == 0) {
|
||||
synchronized (this) {
|
||||
pw.println("Current Battery Service state:");
|
||||
pw.println(" AC powered: " + mAcOnline);
|
||||
pw.println(" USB powered: " + mUsbOnline);
|
||||
pw.println(" status: " + mBatteryStatus);
|
||||
pw.println(" health: " + mBatteryHealth);
|
||||
pw.println(" present: " + mBatteryPresent);
|
||||
pw.println(" level: " + mBatteryLevel);
|
||||
pw.println(" scale: " + BATTERY_SCALE);
|
||||
pw.println(" voltage:" + mBatteryVoltage);
|
||||
pw.println(" temperature: " + mBatteryTemperature);
|
||||
pw.println(" technology: " + mBatteryTechnology);
|
||||
}
|
||||
} else if (false) {
|
||||
// DO NOT SUBMIT WITH THIS TURNED ON
|
||||
if (args.length == 3 && "set".equals(args[0])) {
|
||||
String key = args[1];
|
||||
String value = args[2];
|
||||
try {
|
||||
boolean update = true;
|
||||
if ("ac".equals(key)) {
|
||||
mAcOnline = Integer.parseInt(value) != 0;
|
||||
} else if ("usb".equals(key)) {
|
||||
mUsbOnline = Integer.parseInt(value) != 0;
|
||||
} else if ("status".equals(key)) {
|
||||
mBatteryStatus = Integer.parseInt(value);
|
||||
} else if ("level".equals(key)) {
|
||||
mBatteryLevel = Integer.parseInt(value);
|
||||
} else if ("invalid".equals(key)) {
|
||||
mInvalidCharger = Integer.parseInt(value);
|
||||
} else {
|
||||
update = false;
|
||||
}
|
||||
if (update) {
|
||||
processValues();
|
||||
}
|
||||
} catch (NumberFormatException ex) {
|
||||
pw.println("Bad value: " + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user