Last active
January 4, 2016 16:19
-
-
Save xenon92/8646948 to your computer and use it in GitHub Desktop.
Patch frameworks/base rebased on Resurrection Remix Kitkat to fix vibration on Galaxy S2 Plus - credits to beastaki23 at XDA
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/services/java/com/android/server/VibratorService.java b/services/java/com/android/server/VibratorService.java | |
index 64fffb7..581af0c 100644 | |
--- a/services/java/com/android/server/VibratorService.java | |
+++ b/services/java/com/android/server/VibratorService.java | |
@@ -1,18 +1,18 @@ | |
/* | |
- * Copyright (C) 2008 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. | |
- */ | |
+* Copyright (C) 2008 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.server; | |
@@ -60,10 +60,12 @@ public class VibratorService extends IVibratorService.Stub | |
private final Handler mH = new Handler(); | |
private final Context mContext; | |
+ public static Context sContext; | |
private final PowerManager.WakeLock mWakeLock; | |
private final IAppOpsService mAppOpsService; | |
private final IBatteryStats mBatteryStatsService; | |
private InputManager mIm; | |
+ public static boolean booted = false; | |
volatile VibrateThread mThread; | |
@@ -81,12 +83,12 @@ public class VibratorService extends IVibratorService.Stub | |
private class Vibration implements IBinder.DeathRecipient { | |
private final IBinder mToken; | |
- private final long mTimeout; | |
- private final long mStartTime; | |
- private final long[] mPattern; | |
- private final int mRepeat; | |
- private final int mUid; | |
- private final String mPackageName; | |
+ private final long mTimeout; | |
+ private final long mStartTime; | |
+ private final long[] mPattern; | |
+ private final int mRepeat; | |
+ private final int mUid; | |
+ private final String mPackageName; | |
Vibration(IBinder token, long millis, int uid, String packageName) { | |
this(token, millis, null, 0, uid, packageName); | |
@@ -139,6 +141,7 @@ public class VibratorService extends IVibratorService.Stub | |
vibratorOff(); | |
mContext = context; | |
+ sContext = context; | |
PowerManager pm = (PowerManager)context.getSystemService( | |
Context.POWER_SERVICE); | |
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*"); | |
@@ -153,6 +156,8 @@ public class VibratorService extends IVibratorService.Stub | |
IntentFilter filter = new IntentFilter(); | |
filter.addAction(Intent.ACTION_SCREEN_OFF); | |
context.registerReceiver(mIntentReceiver, filter); | |
+ filter.addAction(Intent.ACTION_BOOT_COMPLETED); | |
+ context.registerReceiver(mIntentReceiver, filter); | |
} | |
public void systemReady() { | |
@@ -469,12 +474,12 @@ public class VibratorService extends IVibratorService.Stub | |
private boolean doVibratorExists() { | |
// For now, we choose to ignore the presence of input devices that have vibrators | |
- // when reporting whether the device has a vibrator. Applications often use this | |
+ // when reporting whether the device has a vibrator. Applications often use this | |
// information to decide whether to enable certain features so they expect the | |
- // result of hasVibrator() to be constant. For now, just report whether | |
+ // result of hasVibrator() to be constant. For now, just report whether | |
// the device has a built-in vibrator. | |
//synchronized (mInputDeviceVibrators) { | |
- // return !mInputDeviceVibrators.isEmpty() || vibratorExists(); | |
+ // return !mInputDeviceVibrators.isEmpty() || vibratorExists(); | |
//} | |
return vibratorExists(); | |
} | |
@@ -492,11 +497,37 @@ public class VibratorService extends IVibratorService.Stub | |
mInputDeviceVibrators.get(i).vibrate(millis); | |
} | |
} else { | |
+ s2plusVibrateON(millis,uid); | |
vibratorOn(millis); | |
} | |
} | |
} | |
+ public static void s2plusVibrateON(long millis, int uid) { | |
+ // Function for s2plus to vibrate from other service untill bug is fixed | |
+ if (booted){ | |
+ String CUSTOM_INTENT = "vibrator.intent.for.broadcast"; | |
+ Intent myI = new Intent(); | |
+ myI.setAction(CUSTOM_INTENT); | |
+ myI.putExtra("millis", millis); | |
+ myI.putExtra("uid", uid); | |
+ sContext.sendBroadcast(myI); | |
+ } | |
+ } | |
+ | |
+ public static void s2plusVibrateOFF() { | |
+ // Function for s2plus to stop vibrating from other service untill bug is fixed | |
+ if (booted){ | |
+ String CUSTOM_INTENT = "vibrator.intent.off.broadcast"; | |
+ Intent myI = new Intent(); | |
+ myI.setAction(CUSTOM_INTENT); | |
+ Long lint = (long) 0; | |
+ myI.putExtra("millis", lint); | |
+ myI.putExtra("uid", 0); | |
+ sContext.sendBroadcast(myI); | |
+ } | |
+ } | |
+ | |
private void doVibratorOff() { | |
synchronized (mInputDeviceVibrators) { | |
if (mCurVibUid >= 0) { | |
@@ -512,6 +543,7 @@ public class VibratorService extends IVibratorService.Stub | |
mInputDeviceVibrators.get(i).cancel(); | |
} | |
} else { | |
+ s2plusVibrateOFF(); | |
vibratorOff(); | |
} | |
} | |
@@ -613,7 +645,7 @@ public class VibratorService extends IVibratorService.Stub | |
mVibrations.clear(); | |
} | |
- } | |
+ }else if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) booted = true; | |
} | |
}; | |
-} | |
+} | |
\ No newline at end of file | |
diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java | |
index d2d312c..6f62121 100644 | |
--- a/services/java/com/android/server/input/InputManagerService.java | |
+++ b/services/java/com/android/server/input/InputManagerService.java | |
@@ -76,6 +76,9 @@ import android.view.ViewConfiguration; | |
import android.view.WindowManagerPolicy; | |
import android.widget.Toast; | |
+import com.android.server.power.PowerManagerService; | |
+import com.android.server.VibratorService; | |
+ | |
import java.io.File; | |
import java.io.FileDescriptor; | |
import java.io.FileNotFoundException; | |
@@ -1421,6 +1424,10 @@ public class InputManagerService extends IInputManager.Stub | |
// Native callback. | |
private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) { | |
+ if ((event.getScanCode() == 139 || event.getScanCode() == 158) && event.getAction() == 0) { | |
+ VibratorService.s2plusVibrateON((long) 0 , -10); | |
+ PowerManagerService.ButtonsLightON(); | |
+ } | |
return mWindowManagerCallbacks.interceptKeyBeforeQueueing( | |
event, policyFlags, isScreenOn); | |
} | |
@@ -1433,12 +1440,14 @@ public class InputManagerService extends IInputManager.Stub | |
// Native callback. | |
private long interceptKeyBeforeDispatching(InputWindowHandle focus, | |
KeyEvent event, int policyFlags) { | |
+ //Slog.v(TAG, "2 KeyEvent " + event); | |
return mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags); | |
} | |
// Native callback. | |
private KeyEvent dispatchUnhandledKey(InputWindowHandle focus, | |
KeyEvent event, int policyFlags) { | |
+ //Slog.v(TAG, "3 KeyEvent " + event); | |
return mWindowManagerCallbacks.dispatchUnhandledKey(focus, event, policyFlags); | |
} | |
diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java | |
index c1a9849..93c6632 100644 | |
--- a/services/java/com/android/server/power/PowerManagerService.java | |
+++ b/services/java/com/android/server/power/PowerManagerService.java | |
@@ -77,7 +77,9 @@ import libcore.util.Objects; | |
public final class PowerManagerService extends IPowerManager.Stub | |
implements Watchdog.Monitor { | |
private static final String TAG = "PowerManagerService"; | |
- | |
+ private static long buttonNextTimeout = -1; | |
+ private static int buttonBrightness = 0; | |
+ private static boolean buttonleds = false; | |
private static final boolean DEBUG = false; | |
private static final boolean DEBUG_SPEW = DEBUG && true; | |
@@ -173,7 +175,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
// Max time (microseconds) to allow a CPU boost for | |
private static final int MAX_CPU_BOOST_TIME = 5000000; | |
- private Context mContext; | |
+ private static Context mContext; | |
private LightsService mLightsService; | |
private BatteryService mBatteryService; | |
private DisplayManagerService mDisplayManagerService; | |
@@ -189,13 +191,13 @@ public final class PowerManagerService extends IPowerManager.Stub | |
private DreamManagerService mDreamManager; | |
private AutoBrightnessHandler mAutoBrightnessHandler; | |
private LightsService.Light mAttentionLight; | |
- private LightsService.Light mButtonsLight; | |
+ private static LightsService.Light mButtonsLight; | |
private LightsService.Light mKeyboardLight; | |
private LightsService.Light mCapsLight; | |
private LightsService.Light mFnLight; | |
- private int mButtonTimeout; | |
- private int mButtonBrightness; | |
+ static private int mButtonTimeout; | |
+ static private int mButtonBrightness; | |
private int mButtonBrightnessSettingDefault; | |
private int mKeyboardBrightness; | |
private int mKeyboardBrightnessSettingDefault; | |
@@ -723,7 +725,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
return; | |
} | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "acquireWakeLockInternal: lock=" + Objects.hashCode(lock) | |
+ Slog.v(TAG, "acquireWakeLockInternal: lock=" + Objects.hashCode(lock) | |
+ ", flags=0x" + Integer.toHexString(flags) | |
+ ", tag=\"" + tag + "\", ws=" + ws + ", uid=" + uid + ", pid=" + pid); | |
} | |
@@ -794,7 +796,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
int index = findWakeLockIndexLocked(lock); | |
if (index < 0) { | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "releaseWakeLockInternal: lock=" + Objects.hashCode(lock) | |
+ Slog.v(TAG, "releaseWakeLockInternal: lock=" + Objects.hashCode(lock) | |
+ " [not found], flags=0x" + Integer.toHexString(flags)); | |
} | |
return; | |
@@ -802,7 +804,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
WakeLock wakeLock = mWakeLocks.get(index); | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "releaseWakeLockInternal: lock=" + Objects.hashCode(lock) | |
+ Slog.v(TAG, "releaseWakeLockInternal: lock=" + Objects.hashCode(lock) | |
+ " [" + wakeLock.mTag + "], flags=0x" + Integer.toHexString(flags)); | |
} | |
@@ -823,7 +825,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
private void handleWakeLockDeath(WakeLock wakeLock) { | |
synchronized (mLock) { | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "handleWakeLockDeath: lock=" + Objects.hashCode(wakeLock.mLock) | |
+ Slog.v(TAG, "handleWakeLockDeath: lock=" + Objects.hashCode(wakeLock.mLock) | |
+ " [" + wakeLock.mTag + "]"); | |
} | |
@@ -895,7 +897,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
boolean isNsrmEnabled = (value == 4 || value == 5 || value == 6); | |
if (index < 0) { | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "updateWakeLockWorkSourceInternal: lock=" + Objects.hashCode(lock) | |
+ Slog.v(TAG, "updateWakeLockWorkSourceInternal: lock=" + Objects.hashCode(lock) | |
+ " [not found], ws=" + ws); | |
} | |
if (!isNsrmEnabled) { | |
@@ -907,7 +909,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
WakeLock wakeLock = mWakeLocks.get(index); | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "updateWakeLockWorkSourceInternal: lock=" + Objects.hashCode(lock) | |
+ Slog.v(TAG, "updateWakeLockWorkSourceInternal: lock=" + Objects.hashCode(lock) | |
+ " [" + wakeLock.mTag + "], ws=" + ws); | |
} | |
@@ -1071,11 +1073,10 @@ public final class PowerManagerService extends IPowerManager.Stub | |
private boolean userActivityNoUpdateLocked(long eventTime, int event, int flags, int uid) { | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "userActivityNoUpdateLocked: eventTime=" + eventTime | |
+ Slog.v(TAG, "userActivityNoUpdateLocked: eventTime=" + eventTime | |
+ ", event=" + event + ", flags=0x" + Integer.toHexString(flags) | |
+ ", uid=" + uid); | |
} | |
- | |
if (eventTime < mLastSleepTime || eventTime < mLastWakeTime | |
|| mWakefulness == WAKEFULNESS_ASLEEP || !mBootCompleted || !mSystemReady) { | |
return false; | |
@@ -1104,7 +1105,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
public void setKeyboardVisibility(boolean visible) { | |
synchronized (mLock) { | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "setKeyboardVisibility: " + visible); | |
+ Slog.v(TAG, "setKeyboardVisibility: " + visible); | |
} | |
if (mKeyboardVisible != visible) { | |
mKeyboardVisible = visible; | |
@@ -1167,7 +1168,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
private boolean wakeUpNoUpdateLocked(long eventTime) { | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime); | |
+ Slog.v(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime); | |
} | |
if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE | |
@@ -1231,7 +1232,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
@SuppressWarnings("deprecation") | |
private boolean goToSleepNoUpdateLocked(long eventTime, int reason) { | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime + ", reason=" + reason); | |
+ Slog.v(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime + ", reason=" + reason); | |
} | |
if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP | |
@@ -1303,7 +1304,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
private boolean napNoUpdateLocked(long eventTime) { | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "napNoUpdateLocked: eventTime=" + eventTime); | |
+ Slog.v(TAG, "napNoUpdateLocked: eventTime=" + eventTime); | |
} | |
if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE | |
@@ -1391,7 +1392,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
mBatteryLevel = mBatteryService.getBatteryLevel(); | |
if (DEBUG) { | |
- Slog.d(TAG, "updateIsPoweredLocked: wasPowered=" + wasPowered | |
+ Slog.v(TAG, "updateIsPoweredLocked: wasPowered=" + wasPowered | |
+ ", mIsPowered=" + mIsPowered | |
+ ", oldPlugType=" + oldPlugType | |
+ ", mPlugType=" + mPlugType | |
@@ -1532,7 +1533,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
} | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness=" | |
+ Slog.v(TAG, "updateWakeLockSummaryLocked: mWakefulness=" | |
+ wakefulnessToString(mWakefulness) | |
+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)); | |
} | |
@@ -1561,7 +1562,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
nextTimeout = mLastUserActivityTime | |
+ screenOffTimeout - screenDimDuration; | |
if (now < nextTimeout) { | |
- int buttonBrightness, keyboardBrightness; | |
+ int keyboardBrightness; | |
if (mButtonBrightnessOverrideFromWindowManager >= 0) { | |
buttonBrightness = mButtonBrightnessOverrideFromWindowManager; | |
keyboardBrightness = mButtonBrightnessOverrideFromWindowManager; | |
@@ -1574,7 +1575,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
if (mButtonTimeout != 0 && now > mLastUserActivityTime + mButtonTimeout) { | |
mButtonsLight.setBrightness(0); | |
} else { | |
- mButtonsLight.setBrightness(buttonBrightness); | |
+ if (now > buttonNextTimeout) mButtonsLight.setBrightness(0); | |
if (buttonBrightness != 0 && mButtonTimeout != 0) { | |
nextTimeout = now + mButtonTimeout; | |
} | |
@@ -1610,7 +1611,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
} | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "updateUserActivitySummaryLocked: mWakefulness=" | |
+ Slog.v(TAG, "updateUserActivitySummaryLocked: mWakefulness=" | |
+ wakefulnessToString(mWakefulness) | |
+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary) | |
+ ", nextTimeout=" + TimeUtils.formatUptime(nextTimeout)); | |
@@ -1618,6 +1619,12 @@ public final class PowerManagerService extends IPowerManager.Stub | |
} | |
} | |
+ static public void ButtonsLightON(){ | |
+ long timing = SystemClock.uptimeMillis(); | |
+ mButtonsLight.setBrightness(buttonBrightness); | |
+ buttonNextTimeout = timing + mButtonTimeout; | |
+ } | |
+ | |
/** | |
* Called when a user activity timeout has occurred. | |
* Simply indicates that something about user activity has changed so that the new | |
@@ -1629,7 +1636,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
private void handleUserActivityTimeout() { // runs on handler thread | |
synchronized (mLock) { | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "handleUserActivityTimeout"); | |
+ Slog.v(TAG, "handleUserActivityTimeout"); | |
} | |
mDirty |= DIRTY_USER_ACTIVITY; | |
@@ -1669,7 +1676,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
| DIRTY_DOCK_STATE)) != 0) { | |
if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) { | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "updateWakefulnessLocked: Bed time..."); | |
+ Slog.v(TAG, "updateWakefulnessLocked: Bed time..."); | |
} | |
final long time = SystemClock.uptimeMillis(); | |
if (shouldNapAtBedTimeLocked()) { | |
@@ -1758,7 +1765,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
mSandmanScheduled = false; | |
boolean canDream = canDreamLocked(); | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "handleSandman: canDream=" + canDream | |
+ Slog.v(TAG, "handleSandman: canDream=" + canDream | |
+ ", mWakefulness=" + wakefulnessToString(mWakefulness)); | |
} | |
@@ -1927,7 +1934,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
mRequestWaitForNegativeProximity = false; | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "updateScreenStateLocked: mDisplayReady=" + mDisplayReady | |
+ Slog.v(TAG, "updateScreenStateLocked: mDisplayReady=" + mDisplayReady | |
+ ", newScreenState=" + newScreenState | |
+ ", mWakefulness=" + mWakefulness | |
+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary) | |
@@ -2074,7 +2081,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
private void checkIfBootAnimationFinished() { | |
if (DEBUG) { | |
- Slog.d(TAG, "Check if boot animation finished..."); | |
+ Slog.v(TAG, "Check if boot animation finished..."); | |
} | |
if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) { | |
@@ -2875,7 +2882,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
mReferenceCount += 1; | |
if (mReferenceCount == 1) { | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "Acquiring suspend blocker \"" + mName + "\"."); | |
+ Slog.v(TAG, "Acquiring suspend blocker \"" + mName + "\"."); | |
} | |
nativeAcquireSuspendBlocker(mName); | |
} | |
@@ -2888,7 +2895,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
mReferenceCount -= 1; | |
if (mReferenceCount == 0) { | |
if (DEBUG_SPEW) { | |
- Slog.d(TAG, "Releasing suspend blocker \"" + mName + "\"."); | |
+ Slog.v(TAG, "Releasing suspend blocker \"" + mName + "\"."); | |
} | |
nativeReleaseSuspendBlocker(mName); | |
} else if (mReferenceCount < 0) { | |
@@ -2921,7 +2928,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
synchronized (this) { | |
mNestCount += 1; | |
if (DEBUG) { | |
- Slog.d(TAG, "Screen on blocked: mNestCount=" + mNestCount); | |
+ Slog.v(TAG, "Screen on blocked: mNestCount=" + mNestCount); | |
} | |
} | |
} | |
@@ -2939,7 +2946,7 @@ public final class PowerManagerService extends IPowerManager.Stub | |
mHandler.sendEmptyMessage(MSG_SCREEN_ON_BLOCKER_RELEASED); | |
} | |
if (DEBUG) { | |
- Slog.d(TAG, "Screen on unblocked: mNestCount=" + mNestCount); | |
+ Slog.v(TAG, "Screen on unblocked: mNestCount=" + mNestCount); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment