Merge "Fix issue #28602068: Add count to job scheduler stats" into nyc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
d90be6cccc
82
core/java/com/android/internal/util/RingBufferIndices.java
Normal file
82
core/java/com/android/internal/util/RingBufferIndices.java
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.internal.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class for implementing a ring buffer. This supplies the indices, you supply
|
||||||
|
* the array(s).
|
||||||
|
*/
|
||||||
|
public class RingBufferIndices {
|
||||||
|
private final int mCapacity;
|
||||||
|
|
||||||
|
// The first valid element and the next open slot.
|
||||||
|
private int mStart;
|
||||||
|
private int mSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create ring buffer of the given capacity.
|
||||||
|
*/
|
||||||
|
public RingBufferIndices(int capacity) {
|
||||||
|
mCapacity = capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new item to the ring buffer. If the ring buffer is full, this
|
||||||
|
* replaces the oldest item.
|
||||||
|
* @return Returns the index at which the new item appears, for placing in your array.
|
||||||
|
*/
|
||||||
|
public int add() {
|
||||||
|
if (mSize < mCapacity) {
|
||||||
|
final int pos = mSize;
|
||||||
|
mSize++;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
int pos = mStart;
|
||||||
|
mStart++;
|
||||||
|
if (mStart == mCapacity) {
|
||||||
|
mStart = 0;
|
||||||
|
}
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the ring buffer.
|
||||||
|
*/
|
||||||
|
public void clear() {
|
||||||
|
mStart = 0;
|
||||||
|
mSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current size of the ring buffer.
|
||||||
|
*/
|
||||||
|
public int size() {
|
||||||
|
return mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a position in the ring buffer that is [0..size()] to an offset
|
||||||
|
* in the array(s) containing the ring buffer items.
|
||||||
|
*/
|
||||||
|
public int indexOf(int pos) {
|
||||||
|
int index = mStart + pos;
|
||||||
|
if (index >= mCapacity) {
|
||||||
|
index -= mCapacity;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,6 +23,7 @@ import android.text.format.DateFormat;
|
|||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.util.TimeUtils;
|
import android.util.TimeUtils;
|
||||||
|
import com.android.internal.util.RingBufferIndices;
|
||||||
import com.android.server.job.controllers.JobStatus;
|
import com.android.server.job.controllers.JobStatus;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
@@ -33,26 +34,24 @@ public final class JobPackageTracker {
|
|||||||
// Number of historical data sets we keep.
|
// Number of historical data sets we keep.
|
||||||
static final int NUM_HISTORY = 5;
|
static final int NUM_HISTORY = 5;
|
||||||
|
|
||||||
private static final int EVENT_BUFFER_SIZE = 50;
|
private static final int EVENT_BUFFER_SIZE = 100;
|
||||||
|
|
||||||
public static final int EVENT_NULL = 0;
|
public static final int EVENT_NULL = 0;
|
||||||
public static final int EVENT_START_JOB = 1;
|
public static final int EVENT_START_JOB = 1;
|
||||||
public static final int EVENT_STOP_JOB = 2;
|
public static final int EVENT_STOP_JOB = 2;
|
||||||
|
|
||||||
private int[] mEventCmds = new int[EVENT_BUFFER_SIZE];
|
private final RingBufferIndices mEventIndices = new RingBufferIndices(EVENT_BUFFER_SIZE);
|
||||||
private long[] mEventTimes = new long[EVENT_BUFFER_SIZE];
|
private final int[] mEventCmds = new int[EVENT_BUFFER_SIZE];
|
||||||
private int[] mEventUids = new int[EVENT_BUFFER_SIZE];
|
private final long[] mEventTimes = new long[EVENT_BUFFER_SIZE];
|
||||||
private String[] mEventTags = new String[EVENT_BUFFER_SIZE];
|
private final int[] mEventUids = new int[EVENT_BUFFER_SIZE];
|
||||||
|
private final String[] mEventTags = new String[EVENT_BUFFER_SIZE];
|
||||||
|
|
||||||
public void addEvent(int cmd, int uid, String tag) {
|
public void addEvent(int cmd, int uid, String tag) {
|
||||||
System.arraycopy(mEventCmds, 0, mEventCmds, 1, EVENT_BUFFER_SIZE - 1);
|
int index = mEventIndices.add();
|
||||||
System.arraycopy(mEventTimes, 0, mEventTimes, 1, EVENT_BUFFER_SIZE - 1);
|
mEventCmds[index] = cmd;
|
||||||
System.arraycopy(mEventUids, 0, mEventUids, 1, EVENT_BUFFER_SIZE - 1);
|
mEventTimes[index] = SystemClock.elapsedRealtime();
|
||||||
System.arraycopy(mEventTags, 0, mEventTags, 1, EVENT_BUFFER_SIZE - 1);
|
mEventUids[index] = uid;
|
||||||
mEventCmds[0] = cmd;
|
mEventTags[index] = tag;
|
||||||
mEventTimes[0] = SystemClock.elapsedRealtime();
|
|
||||||
mEventUids[0] = uid;
|
|
||||||
mEventTags[0] = tag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DataSet mCurDataSet = new DataSet();
|
DataSet mCurDataSet = new DataSet();
|
||||||
@@ -61,20 +60,23 @@ public final class JobPackageTracker {
|
|||||||
final static class PackageEntry {
|
final static class PackageEntry {
|
||||||
long pastActiveTime;
|
long pastActiveTime;
|
||||||
long activeStartTime;
|
long activeStartTime;
|
||||||
|
int activeNesting;
|
||||||
int activeCount;
|
int activeCount;
|
||||||
boolean hadActive;
|
boolean hadActive;
|
||||||
long pastActiveTopTime;
|
long pastActiveTopTime;
|
||||||
long activeTopStartTime;
|
long activeTopStartTime;
|
||||||
|
int activeTopNesting;
|
||||||
int activeTopCount;
|
int activeTopCount;
|
||||||
boolean hadActiveTop;
|
boolean hadActiveTop;
|
||||||
long pastPendingTime;
|
long pastPendingTime;
|
||||||
long pendingStartTime;
|
long pendingStartTime;
|
||||||
|
int pendingNesting;
|
||||||
int pendingCount;
|
int pendingCount;
|
||||||
boolean hadPending;
|
boolean hadPending;
|
||||||
|
|
||||||
public long getActiveTime(long now) {
|
public long getActiveTime(long now) {
|
||||||
long time = pastActiveTime;
|
long time = pastActiveTime;
|
||||||
if (activeCount > 0) {
|
if (activeNesting > 0) {
|
||||||
time += now - activeStartTime;
|
time += now - activeStartTime;
|
||||||
}
|
}
|
||||||
return time;
|
return time;
|
||||||
@@ -82,7 +84,7 @@ public final class JobPackageTracker {
|
|||||||
|
|
||||||
public long getActiveTopTime(long now) {
|
public long getActiveTopTime(long now) {
|
||||||
long time = pastActiveTopTime;
|
long time = pastActiveTopTime;
|
||||||
if (activeTopCount > 0) {
|
if (activeTopNesting > 0) {
|
||||||
time += now - activeTopStartTime;
|
time += now - activeTopStartTime;
|
||||||
}
|
}
|
||||||
return time;
|
return time;
|
||||||
@@ -90,7 +92,7 @@ public final class JobPackageTracker {
|
|||||||
|
|
||||||
public long getPendingTime(long now) {
|
public long getPendingTime(long now) {
|
||||||
long time = pastPendingTime;
|
long time = pastPendingTime;
|
||||||
if (pendingCount > 0) {
|
if (pendingNesting > 0) {
|
||||||
time += now - pendingStartTime;
|
time += now - pendingStartTime;
|
||||||
}
|
}
|
||||||
return time;
|
return time;
|
||||||
@@ -147,50 +149,53 @@ public final class JobPackageTracker {
|
|||||||
|
|
||||||
void incPending(int uid, String pkg, long now) {
|
void incPending(int uid, String pkg, long now) {
|
||||||
PackageEntry pe = getOrCreateEntry(uid, pkg);
|
PackageEntry pe = getOrCreateEntry(uid, pkg);
|
||||||
if (pe.pendingCount == 0) {
|
if (pe.pendingNesting == 0) {
|
||||||
pe.pendingStartTime = now;
|
pe.pendingStartTime = now;
|
||||||
}
|
|
||||||
pe.pendingCount++;
|
pe.pendingCount++;
|
||||||
}
|
}
|
||||||
|
pe.pendingNesting++;
|
||||||
|
}
|
||||||
|
|
||||||
void decPending(int uid, String pkg, long now) {
|
void decPending(int uid, String pkg, long now) {
|
||||||
PackageEntry pe = getOrCreateEntry(uid, pkg);
|
PackageEntry pe = getOrCreateEntry(uid, pkg);
|
||||||
if (pe.pendingCount == 1) {
|
if (pe.pendingNesting == 1) {
|
||||||
pe.pastPendingTime += now - pe.pendingStartTime;
|
pe.pastPendingTime += now - pe.pendingStartTime;
|
||||||
}
|
}
|
||||||
pe.pendingCount--;
|
pe.pendingNesting--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void incActive(int uid, String pkg, long now) {
|
void incActive(int uid, String pkg, long now) {
|
||||||
PackageEntry pe = getOrCreateEntry(uid, pkg);
|
PackageEntry pe = getOrCreateEntry(uid, pkg);
|
||||||
if (pe.activeCount == 0) {
|
if (pe.activeNesting == 0) {
|
||||||
pe.activeStartTime = now;
|
pe.activeStartTime = now;
|
||||||
}
|
|
||||||
pe.activeCount++;
|
pe.activeCount++;
|
||||||
}
|
}
|
||||||
|
pe.activeNesting++;
|
||||||
|
}
|
||||||
|
|
||||||
void decActive(int uid, String pkg, long now) {
|
void decActive(int uid, String pkg, long now) {
|
||||||
PackageEntry pe = getOrCreateEntry(uid, pkg);
|
PackageEntry pe = getOrCreateEntry(uid, pkg);
|
||||||
if (pe.activeCount == 1) {
|
if (pe.activeNesting == 1) {
|
||||||
pe.pastActiveTime += now - pe.activeStartTime;
|
pe.pastActiveTime += now - pe.activeStartTime;
|
||||||
}
|
}
|
||||||
pe.activeCount--;
|
pe.activeNesting--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void incActiveTop(int uid, String pkg, long now) {
|
void incActiveTop(int uid, String pkg, long now) {
|
||||||
PackageEntry pe = getOrCreateEntry(uid, pkg);
|
PackageEntry pe = getOrCreateEntry(uid, pkg);
|
||||||
if (pe.activeTopCount == 0) {
|
if (pe.activeTopNesting == 0) {
|
||||||
pe.activeTopStartTime = now;
|
pe.activeTopStartTime = now;
|
||||||
}
|
|
||||||
pe.activeTopCount++;
|
pe.activeTopCount++;
|
||||||
}
|
}
|
||||||
|
pe.activeTopNesting++;
|
||||||
|
}
|
||||||
|
|
||||||
void decActiveTop(int uid, String pkg, long now) {
|
void decActiveTop(int uid, String pkg, long now) {
|
||||||
PackageEntry pe = getOrCreateEntry(uid, pkg);
|
PackageEntry pe = getOrCreateEntry(uid, pkg);
|
||||||
if (pe.activeTopCount == 1) {
|
if (pe.activeTopNesting == 1) {
|
||||||
pe.pastActiveTopTime += now - pe.activeTopStartTime;
|
pe.pastActiveTopTime += now - pe.activeTopStartTime;
|
||||||
}
|
}
|
||||||
pe.activeTopCount--;
|
pe.activeTopNesting--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void finish(DataSet next, long now) {
|
void finish(DataSet next, long now) {
|
||||||
@@ -198,27 +203,27 @@ public final class JobPackageTracker {
|
|||||||
ArrayMap<String, PackageEntry> uidMap = mEntries.valueAt(i);
|
ArrayMap<String, PackageEntry> uidMap = mEntries.valueAt(i);
|
||||||
for (int j = uidMap.size() - 1; j >= 0; j--) {
|
for (int j = uidMap.size() - 1; j >= 0; j--) {
|
||||||
PackageEntry pe = uidMap.valueAt(j);
|
PackageEntry pe = uidMap.valueAt(j);
|
||||||
if (pe.activeCount > 0 || pe.activeTopCount > 0 || pe.pendingCount > 0) {
|
if (pe.activeNesting > 0 || pe.activeTopNesting > 0 || pe.pendingNesting > 0) {
|
||||||
// Propagate existing activity in to next data set.
|
// Propagate existing activity in to next data set.
|
||||||
PackageEntry nextPe = next.getOrCreateEntry(mEntries.keyAt(i), uidMap.keyAt(j));
|
PackageEntry nextPe = next.getOrCreateEntry(mEntries.keyAt(i), uidMap.keyAt(j));
|
||||||
nextPe.activeStartTime = now;
|
nextPe.activeStartTime = now;
|
||||||
nextPe.activeCount = pe.activeCount;
|
nextPe.activeNesting = pe.activeNesting;
|
||||||
nextPe.activeTopStartTime = now;
|
nextPe.activeTopStartTime = now;
|
||||||
nextPe.activeTopCount = pe.activeTopCount;
|
nextPe.activeTopNesting = pe.activeTopNesting;
|
||||||
nextPe.pendingStartTime = now;
|
nextPe.pendingStartTime = now;
|
||||||
nextPe.pendingCount = pe.pendingCount;
|
nextPe.pendingNesting = pe.pendingNesting;
|
||||||
// Finish it off.
|
// Finish it off.
|
||||||
if (pe.activeCount > 0) {
|
if (pe.activeNesting > 0) {
|
||||||
pe.pastActiveTime += now - pe.activeStartTime;
|
pe.pastActiveTime += now - pe.activeStartTime;
|
||||||
pe.activeCount = 0;
|
pe.activeNesting = 0;
|
||||||
}
|
}
|
||||||
if (pe.activeTopCount > 0) {
|
if (pe.activeTopNesting > 0) {
|
||||||
pe.pastActiveTopTime += now - pe.activeTopStartTime;
|
pe.pastActiveTopTime += now - pe.activeTopStartTime;
|
||||||
pe.activeTopCount = 0;
|
pe.activeTopNesting = 0;
|
||||||
}
|
}
|
||||||
if (pe.pendingCount > 0) {
|
if (pe.pendingNesting > 0) {
|
||||||
pe.pastPendingTime += now - pe.pendingStartTime;
|
pe.pastPendingTime += now - pe.pendingStartTime;
|
||||||
pe.pendingCount = 0;
|
pe.pendingNesting = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,17 +238,20 @@ public final class JobPackageTracker {
|
|||||||
PackageEntry pe = uidMap.valueAt(j);
|
PackageEntry pe = uidMap.valueAt(j);
|
||||||
PackageEntry outPe = out.getOrCreateEntry(mEntries.keyAt(i), uidMap.keyAt(j));
|
PackageEntry outPe = out.getOrCreateEntry(mEntries.keyAt(i), uidMap.keyAt(j));
|
||||||
outPe.pastActiveTime += pe.pastActiveTime;
|
outPe.pastActiveTime += pe.pastActiveTime;
|
||||||
|
outPe.activeCount += pe.activeCount;
|
||||||
outPe.pastActiveTopTime += pe.pastActiveTopTime;
|
outPe.pastActiveTopTime += pe.pastActiveTopTime;
|
||||||
|
outPe.activeTopCount += pe.activeTopCount;
|
||||||
outPe.pastPendingTime += pe.pastPendingTime;
|
outPe.pastPendingTime += pe.pastPendingTime;
|
||||||
if (pe.activeCount > 0) {
|
outPe.pendingCount += pe.pendingCount;
|
||||||
|
if (pe.activeNesting > 0) {
|
||||||
outPe.pastActiveTime += now - pe.activeStartTime;
|
outPe.pastActiveTime += now - pe.activeStartTime;
|
||||||
outPe.hadActive = true;
|
outPe.hadActive = true;
|
||||||
}
|
}
|
||||||
if (pe.activeTopCount > 0) {
|
if (pe.activeTopNesting > 0) {
|
||||||
outPe.pastActiveTopTime += now - pe.activeTopStartTime;
|
outPe.pastActiveTopTime += now - pe.activeTopStartTime;
|
||||||
outPe.hadActiveTop = true;
|
outPe.hadActiveTop = true;
|
||||||
}
|
}
|
||||||
if (pe.pendingCount > 0) {
|
if (pe.pendingNesting > 0) {
|
||||||
outPe.pastPendingTime += now - pe.pendingStartTime;
|
outPe.pastPendingTime += now - pe.pendingStartTime;
|
||||||
outPe.hadPending = true;
|
outPe.hadPending = true;
|
||||||
}
|
}
|
||||||
@@ -251,13 +259,20 @@ public final class JobPackageTracker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void printDuration(PrintWriter pw, long period, long duration, String suffix) {
|
void printDuration(PrintWriter pw, long period, long duration, int count, String suffix) {
|
||||||
float fraction = duration / (float) period;
|
float fraction = duration / (float) period;
|
||||||
int percent = (int) ((fraction * 100) + .5f);
|
int percent = (int) ((fraction * 100) + .5f);
|
||||||
if (percent > 0) {
|
if (percent > 0) {
|
||||||
pw.print(" ");
|
pw.print(" ");
|
||||||
pw.print(percent);
|
pw.print(percent);
|
||||||
pw.print("% ");
|
pw.print("% ");
|
||||||
|
pw.print(count);
|
||||||
|
pw.print("x ");
|
||||||
|
pw.print(suffix);
|
||||||
|
} else if (count > 0) {
|
||||||
|
pw.print(" ");
|
||||||
|
pw.print(count);
|
||||||
|
pw.print("x ");
|
||||||
pw.print(suffix);
|
pw.print(suffix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -286,16 +301,17 @@ public final class JobPackageTracker {
|
|||||||
UserHandle.formatUid(pw, uid);
|
UserHandle.formatUid(pw, uid);
|
||||||
pw.print(" / "); pw.print(uidMap.keyAt(j));
|
pw.print(" / "); pw.print(uidMap.keyAt(j));
|
||||||
pw.print(":");
|
pw.print(":");
|
||||||
printDuration(pw, period, pe.getPendingTime(now), "pending");
|
printDuration(pw, period, pe.getPendingTime(now), pe.pendingCount, "pending");
|
||||||
printDuration(pw, period, pe.getActiveTime(now), "active");
|
printDuration(pw, period, pe.getActiveTime(now), pe.activeCount, "active");
|
||||||
printDuration(pw, period, pe.getActiveTopTime(now), "active-top");
|
printDuration(pw, period, pe.getActiveTopTime(now), pe.activeTopCount,
|
||||||
if (pe.pendingCount > 0 || pe.hadPending) {
|
"active-top");
|
||||||
|
if (pe.pendingNesting > 0 || pe.hadPending) {
|
||||||
pw.print(" (pending)");
|
pw.print(" (pending)");
|
||||||
}
|
}
|
||||||
if (pe.activeCount > 0 || pe.hadActive) {
|
if (pe.activeNesting > 0 || pe.hadActive) {
|
||||||
pw.print(" (active)");
|
pw.print(" (active)");
|
||||||
}
|
}
|
||||||
if (pe.activeTopCount > 0 || pe.hadActiveTop) {
|
if (pe.activeTopNesting > 0 || pe.hadActiveTop) {
|
||||||
pw.print(" (active-top)");
|
pw.print(" (active-top)");
|
||||||
}
|
}
|
||||||
pw.println();
|
pw.println();
|
||||||
@@ -389,34 +405,36 @@ public final class JobPackageTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean dumpHistory(PrintWriter pw, String prefix, int filterUid) {
|
public boolean dumpHistory(PrintWriter pw, String prefix, int filterUid) {
|
||||||
if (mEventCmds[0] == EVENT_NULL) {
|
final int size = mEventIndices.size();
|
||||||
|
if (size <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pw.println(" Job history:");
|
pw.println(" Job history:");
|
||||||
long now = SystemClock.elapsedRealtime();
|
final long now = SystemClock.elapsedRealtime();
|
||||||
for (int i=EVENT_BUFFER_SIZE-1; i>=0; i--) {
|
for (int i=0; i<size; i++) {
|
||||||
int uid = mEventUids[i];
|
final int index = mEventIndices.indexOf(i);
|
||||||
|
final int uid = mEventUids[index];
|
||||||
if (filterUid != -1 && filterUid != UserHandle.getAppId(filterUid)) {
|
if (filterUid != -1 && filterUid != UserHandle.getAppId(filterUid)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int cmd = mEventCmds[i];
|
final int cmd = mEventCmds[index];
|
||||||
if (cmd == EVENT_NULL) {
|
if (cmd == EVENT_NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String label;
|
final String label;
|
||||||
switch (mEventCmds[i]) {
|
switch (mEventCmds[index]) {
|
||||||
case EVENT_START_JOB: label = "START"; break;
|
case EVENT_START_JOB: label = "START"; break;
|
||||||
case EVENT_STOP_JOB: label = " STOP"; break;
|
case EVENT_STOP_JOB: label = " STOP"; break;
|
||||||
default: label = " ??"; break;
|
default: label = " ??"; break;
|
||||||
}
|
}
|
||||||
pw.print(prefix);
|
pw.print(prefix);
|
||||||
TimeUtils.formatDuration(mEventTimes[i]-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
|
TimeUtils.formatDuration(mEventTimes[index]-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
|
||||||
pw.print(" ");
|
pw.print(" ");
|
||||||
pw.print(label);
|
pw.print(label);
|
||||||
pw.print(": ");
|
pw.print(": ");
|
||||||
UserHandle.formatUid(pw, uid);
|
UserHandle.formatUid(pw, uid);
|
||||||
pw.print(" ");
|
pw.print(" ");
|
||||||
pw.println(mEventTags[i]);
|
pw.println(mEventTags[index]);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user