am f9f9999d
: am b7b9b31f
: am ad26dc5f
: Merge "Deliver camera launch source for analytics" into mnc-dr-dev
* commit 'f9f9999d3245dffc8463a1f3f5f74dc900aa0196': Deliver camera launch source for analytics
This commit is contained in:
@ -90,6 +90,9 @@ public class StatusBarManager {
|
|||||||
public static final int WINDOW_STATE_HIDING = 1;
|
public static final int WINDOW_STATE_HIDING = 1;
|
||||||
public static final int WINDOW_STATE_HIDDEN = 2;
|
public static final int WINDOW_STATE_HIDDEN = 2;
|
||||||
|
|
||||||
|
public static final int CAMERA_LAUNCH_SOURCE_WIGGLE = 0;
|
||||||
|
public static final int CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = 1;
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private IStatusBarService mService;
|
private IStatusBarService mService;
|
||||||
private IBinder mToken = new Binder();
|
private IBinder mToken = new Binder();
|
||||||
|
@ -72,7 +72,9 @@ oneway interface IStatusBar
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies the status bar that a camera launch gesture has been detected.
|
* Notifies the status bar that a camera launch gesture has been detected.
|
||||||
|
*
|
||||||
|
* @param source the identifier for the gesture, see {@link StatusBarManager}
|
||||||
*/
|
*/
|
||||||
void onCameraLaunchGestureDetected();
|
void onCameraLaunchGestureDetected(int source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ public class CommandQueue extends IStatusBar.Stub {
|
|||||||
public void appTransitionStarting(long startTime, long duration);
|
public void appTransitionStarting(long startTime, long duration);
|
||||||
public void showAssistDisclosure();
|
public void showAssistDisclosure();
|
||||||
public void startAssist(Bundle args);
|
public void startAssist(Bundle args);
|
||||||
public void onCameraLaunchGestureDetected();
|
public void onCameraLaunchGestureDetected(int source);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
|
public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
|
||||||
@ -296,10 +296,10 @@ public class CommandQueue extends IStatusBar.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCameraLaunchGestureDetected() {
|
public void onCameraLaunchGestureDetected(int source) {
|
||||||
synchronized (mList) {
|
synchronized (mList) {
|
||||||
mHandler.removeMessages(MSG_CAMERA_LAUNCH_GESTURE);
|
mHandler.removeMessages(MSG_CAMERA_LAUNCH_GESTURE);
|
||||||
mHandler.obtainMessage(MSG_CAMERA_LAUNCH_GESTURE).sendToTarget();
|
mHandler.obtainMessage(MSG_CAMERA_LAUNCH_GESTURE, source, 0).sendToTarget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,7 +402,7 @@ public class CommandQueue extends IStatusBar.Stub {
|
|||||||
mCallbacks.startAssist((Bundle) msg.obj);
|
mCallbacks.startAssist((Bundle) msg.obj);
|
||||||
break;
|
break;
|
||||||
case MSG_CAMERA_LAUNCH_GESTURE:
|
case MSG_CAMERA_LAUNCH_GESTURE:
|
||||||
mCallbacks.onCameraLaunchGestureDetected();
|
mCallbacks.onCameraLaunchGestureDetected(msg.arg1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,13 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
|||||||
|
|
||||||
final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView";
|
final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView";
|
||||||
|
|
||||||
|
public static final String CAMERA_LAUNCH_SOURCE_AFFORDANCE = "lockscreen_affordance";
|
||||||
|
public static final String CAMERA_LAUNCH_SOURCE_WIGGLE = "wiggle_gesture";
|
||||||
|
public static final String CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = "power_double_tap";
|
||||||
|
|
||||||
|
public static final String EXTRA_CAMERA_LAUNCH_SOURCE
|
||||||
|
= "com.android.systemui.camera_launch_source";
|
||||||
|
|
||||||
private static final Intent SECURE_CAMERA_INTENT =
|
private static final Intent SECURE_CAMERA_INTENT =
|
||||||
new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
|
new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
|
.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
|
||||||
@ -170,7 +177,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
|||||||
CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
|
CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
|
||||||
return true;
|
return true;
|
||||||
} else if (host == mCameraImageView) {
|
} else if (host == mCameraImageView) {
|
||||||
launchCamera();
|
launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
|
||||||
return true;
|
return true;
|
||||||
} else if (host == mLeftAffordanceView) {
|
} else if (host == mLeftAffordanceView) {
|
||||||
launchLeftAffordance();
|
launchLeftAffordance();
|
||||||
@ -349,7 +356,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
if (v == mCameraImageView) {
|
if (v == mCameraImageView) {
|
||||||
launchCamera();
|
launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
|
||||||
} else if (v == mLeftAffordanceView) {
|
} else if (v == mLeftAffordanceView) {
|
||||||
launchLeftAffordance();
|
launchLeftAffordance();
|
||||||
} if (v == mLockIcon) {
|
} if (v == mLockIcon) {
|
||||||
@ -417,8 +424,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void launchCamera() {
|
public void launchCamera(String source) {
|
||||||
final Intent intent = getCameraIntent();
|
final Intent intent = getCameraIntent();
|
||||||
|
intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source);
|
||||||
boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity(
|
boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity(
|
||||||
mContext, intent, KeyguardUpdateMonitor.getCurrentUser());
|
mContext, intent, KeyguardUpdateMonitor.getCurrentUser());
|
||||||
if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
|
if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
|
||||||
|
@ -22,7 +22,7 @@ import android.animation.ObjectAnimator;
|
|||||||
import android.animation.PropertyValuesHolder;
|
import android.animation.PropertyValuesHolder;
|
||||||
import android.animation.ValueAnimator;
|
import android.animation.ValueAnimator;
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.ActivityManager.RunningTaskInfo;
|
import android.app.StatusBarManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
@ -203,6 +203,7 @@ public class NotificationPanelView extends PanelView implements
|
|||||||
private boolean mClosingWithAlphaFadeOut;
|
private boolean mClosingWithAlphaFadeOut;
|
||||||
private boolean mHeadsUpAnimatingAway;
|
private boolean mHeadsUpAnimatingAway;
|
||||||
private boolean mLaunchingAffordance;
|
private boolean mLaunchingAffordance;
|
||||||
|
private String mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
|
||||||
|
|
||||||
private Runnable mHeadsUpExistenceChangedRunnable = new Runnable() {
|
private Runnable mHeadsUpExistenceChangedRunnable = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@ -478,6 +479,7 @@ public class NotificationPanelView extends PanelView implements
|
|||||||
mUnlockIconActive = false;
|
mUnlockIconActive = false;
|
||||||
if (!mLaunchingAffordance) {
|
if (!mLaunchingAffordance) {
|
||||||
mAfforanceHelper.reset(false);
|
mAfforanceHelper.reset(false);
|
||||||
|
mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
|
||||||
}
|
}
|
||||||
closeQs();
|
closeQs();
|
||||||
mStatusBar.dismissPopups();
|
mStatusBar.dismissPopups();
|
||||||
@ -1943,9 +1945,13 @@ public class NotificationPanelView extends PanelView implements
|
|||||||
EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_DIALER, lengthDp, velocityDp);
|
EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_DIALER, lengthDp, velocityDp);
|
||||||
mKeyguardBottomArea.launchLeftAffordance();
|
mKeyguardBottomArea.launchLeftAffordance();
|
||||||
} else {
|
} else {
|
||||||
|
if (KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE.equals(
|
||||||
|
mLastCameraLaunchSource)) {
|
||||||
EventLogTags.writeSysuiLockscreenGesture(
|
EventLogTags.writeSysuiLockscreenGesture(
|
||||||
EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_CAMERA, lengthDp, velocityDp);
|
EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_CAMERA,
|
||||||
mKeyguardBottomArea.launchCamera();
|
lengthDp, velocityDp);
|
||||||
|
}
|
||||||
|
mKeyguardBottomArea.launchCamera(mLastCameraLaunchSource);
|
||||||
}
|
}
|
||||||
mStatusBar.startLaunchTransitionTimeout();
|
mStatusBar.startLaunchTransitionTimeout();
|
||||||
mBlockTouches = true;
|
mBlockTouches = true;
|
||||||
@ -2383,7 +2389,17 @@ public class NotificationPanelView extends PanelView implements
|
|||||||
return !mDozing;
|
return !mDozing;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void launchCamera(boolean animate) {
|
public void launchCamera(boolean animate, int source) {
|
||||||
|
if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) {
|
||||||
|
mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP;
|
||||||
|
} else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE) {
|
||||||
|
mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_WIGGLE;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Default.
|
||||||
|
mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
|
||||||
|
}
|
||||||
|
|
||||||
// If we are launching it when we are occluded already we don't want it to animate,
|
// If we are launching it when we are occluded already we don't want it to animate,
|
||||||
// nor setting these flags, since the occluded state doesn't change anymore, hence it's
|
// nor setting these flags, since the occluded state doesn't change anymore, hence it's
|
||||||
// never reset.
|
// never reset.
|
||||||
|
@ -489,6 +489,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
|||||||
private ExpandableNotificationRow mDraggedDownRow;
|
private ExpandableNotificationRow mDraggedDownRow;
|
||||||
private boolean mLaunchCameraOnScreenTurningOn;
|
private boolean mLaunchCameraOnScreenTurningOn;
|
||||||
private boolean mLaunchCameraOnFinishedGoingToSleep;
|
private boolean mLaunchCameraOnFinishedGoingToSleep;
|
||||||
|
private int mLastCameraLaunchSource;
|
||||||
private PowerManager.WakeLock mGestureWakeLock;
|
private PowerManager.WakeLock mGestureWakeLock;
|
||||||
private Vibrator mVibrator;
|
private Vibrator mVibrator;
|
||||||
|
|
||||||
@ -3936,7 +3937,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
|||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
onCameraLaunchGestureDetected();
|
onCameraLaunchGestureDetected(mLastCameraLaunchSource);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -3953,7 +3954,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
|||||||
mScreenTurningOn = true;
|
mScreenTurningOn = true;
|
||||||
mNotificationPanel.onScreenTurningOn();
|
mNotificationPanel.onScreenTurningOn();
|
||||||
if (mLaunchCameraOnScreenTurningOn) {
|
if (mLaunchCameraOnScreenTurningOn) {
|
||||||
mNotificationPanel.launchCamera(false);
|
mNotificationPanel.launchCamera(false, mLastCameraLaunchSource);
|
||||||
mLaunchCameraOnScreenTurningOn = false;
|
mLaunchCameraOnScreenTurningOn = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4118,7 +4119,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCameraLaunchGestureDetected() {
|
public void onCameraLaunchGestureDetected(int source) {
|
||||||
|
mLastCameraLaunchSource = source;
|
||||||
if (mStartedGoingToSleep) {
|
if (mStartedGoingToSleep) {
|
||||||
mLaunchCameraOnFinishedGoingToSleep = true;
|
mLaunchCameraOnFinishedGoingToSleep = true;
|
||||||
return;
|
return;
|
||||||
@ -4144,7 +4146,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
|||||||
mGestureWakeLock.acquire(LAUNCH_TRANSITION_TIMEOUT_MS + 1000L);
|
mGestureWakeLock.acquire(LAUNCH_TRANSITION_TIMEOUT_MS + 1000L);
|
||||||
}
|
}
|
||||||
if (mScreenTurningOn || mStatusBarKeyguardViewManager.isScreenTurnedOn()) {
|
if (mScreenTurningOn || mStatusBarKeyguardViewManager.isScreenTurnedOn()) {
|
||||||
mNotificationPanel.launchCamera(mDeviceInteractive /* animate */);
|
mNotificationPanel.launchCamera(mDeviceInteractive /* animate */, source);
|
||||||
} else {
|
} else {
|
||||||
// We need to defer the camera launch until the screen comes on, since otherwise
|
// We need to defer the camera launch until the screen comes on, since otherwise
|
||||||
// we will dismiss us too early since we are waiting on an activity to be drawn and
|
// we will dismiss us too early since we are waiting on an activity to be drawn and
|
||||||
|
@ -171,7 +171,7 @@ public class TvStatusBar extends BaseStatusBar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCameraLaunchGestureDetected() {
|
public void onCameraLaunchGestureDetected(int source) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package com.android.server;
|
package com.android.server;
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
|
import android.app.StatusBarManager;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -263,7 +264,8 @@ public class GestureLauncherService extends SystemService {
|
|||||||
}
|
}
|
||||||
if (launched) {
|
if (launched) {
|
||||||
Slog.i(TAG, "Power button double tap gesture detected, launching camera.");
|
Slog.i(TAG, "Power button double tap gesture detected, launching camera.");
|
||||||
launched = handleCameraLaunchGesture(false /* useWakelock */);
|
launched = handleCameraLaunchGesture(false /* useWakelock */,
|
||||||
|
StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
|
||||||
if (launched) {
|
if (launched) {
|
||||||
MetricsLogger.action(mContext, MetricsLogger.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE,
|
MetricsLogger.action(mContext, MetricsLogger.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE,
|
||||||
(int) doubleTapInterval);
|
(int) doubleTapInterval);
|
||||||
@ -276,7 +278,7 @@ public class GestureLauncherService extends SystemService {
|
|||||||
/**
|
/**
|
||||||
* @return true if camera was launched, false otherwise.
|
* @return true if camera was launched, false otherwise.
|
||||||
*/
|
*/
|
||||||
private boolean handleCameraLaunchGesture(boolean useWakelock) {
|
private boolean handleCameraLaunchGesture(boolean useWakelock, int source) {
|
||||||
boolean userSetupComplete = Settings.Secure.getInt(mContext.getContentResolver(),
|
boolean userSetupComplete = Settings.Secure.getInt(mContext.getContentResolver(),
|
||||||
Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
|
Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
|
||||||
if (!userSetupComplete) {
|
if (!userSetupComplete) {
|
||||||
@ -295,7 +297,7 @@ public class GestureLauncherService extends SystemService {
|
|||||||
}
|
}
|
||||||
StatusBarManagerInternal service = LocalServices.getService(
|
StatusBarManagerInternal service = LocalServices.getService(
|
||||||
StatusBarManagerInternal.class);
|
StatusBarManagerInternal.class);
|
||||||
service.onCameraLaunchGestureDetected();
|
service.onCameraLaunchGestureDetected(source);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,7 +336,8 @@ public class GestureLauncherService extends SystemService {
|
|||||||
Slog.d(TAG, String.format("Received a camera launch event: " +
|
Slog.d(TAG, String.format("Received a camera launch event: " +
|
||||||
"values=[%.4f, %.4f, %.4f].", values[0], values[1], values[2]));
|
"values=[%.4f, %.4f, %.4f].", values[0], values[1], values[2]));
|
||||||
}
|
}
|
||||||
if (handleCameraLaunchGesture(true /* useWakelock */)) {
|
if (handleCameraLaunchGesture(true /* useWakelock */,
|
||||||
|
StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE)) {
|
||||||
MetricsLogger.action(mContext, MetricsLogger.ACTION_WIGGLE_CAMERA_GESTURE);
|
MetricsLogger.action(mContext, MetricsLogger.ACTION_WIGGLE_CAMERA_GESTURE);
|
||||||
trackCameraLaunchEvent(event);
|
trackCameraLaunchEvent(event);
|
||||||
}
|
}
|
||||||
|
@ -28,5 +28,5 @@ public interface StatusBarManagerInternal {
|
|||||||
void showScreenPinningRequest();
|
void showScreenPinningRequest();
|
||||||
void showAssistDisclosure();
|
void showAssistDisclosure();
|
||||||
void startAssist(Bundle args);
|
void startAssist(Bundle args);
|
||||||
void onCameraLaunchGestureDetected();
|
void onCameraLaunchGestureDetected(int source);
|
||||||
}
|
}
|
||||||
|
@ -178,10 +178,10 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCameraLaunchGestureDetected() {
|
public void onCameraLaunchGestureDetected(int source) {
|
||||||
if (mBar != null) {
|
if (mBar != null) {
|
||||||
try {
|
try {
|
||||||
mBar.onCameraLaunchGestureDetected();
|
mBar.onCameraLaunchGestureDetected(source);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,5 +31,7 @@ public class CameraActivity extends Activity {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.camera_activity);
|
setContentView(R.layout.camera_activity);
|
||||||
Log.i(TAG, "Activity created");
|
Log.i(TAG, "Activity created");
|
||||||
|
Log.i(TAG, "Source: "
|
||||||
|
+ getIntent().getStringExtra("com.android.systemui.camera_launch_source"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package com.google.android.test.cameraprewarm;
|
package com.google.android.test.cameraprewarm;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.graphics.Camera;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
@ -31,5 +32,7 @@ public class SecureCameraActivity extends Activity {
|
|||||||
setContentView(R.layout.camera_activity);
|
setContentView(R.layout.camera_activity);
|
||||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
|
||||||
Log.i(CameraActivity.TAG, "Activity created");
|
Log.i(CameraActivity.TAG, "Activity created");
|
||||||
|
Log.i(CameraActivity.TAG, "Source: "
|
||||||
|
+ getIntent().getStringExtra("com.android.systemui.camera_launch_source"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user