Merge "WorkSource can now track package names."
This commit is contained in:
committed by
Android (Google) Code Review
commit
0d31c74b2e
@@ -1,6 +1,6 @@
|
|||||||
package android.os;
|
package android.os;
|
||||||
|
|
||||||
import com.android.internal.util.ArrayUtils;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
@@ -10,8 +10,12 @@ import java.util.Arrays;
|
|||||||
* defined; this is an opaque container.
|
* defined; this is an opaque container.
|
||||||
*/
|
*/
|
||||||
public class WorkSource implements Parcelable {
|
public class WorkSource implements Parcelable {
|
||||||
|
static final String TAG = "WorkSource";
|
||||||
|
static final boolean DEBUG = true;
|
||||||
|
|
||||||
int mNum;
|
int mNum;
|
||||||
int[] mUids;
|
int[] mUids;
|
||||||
|
String[] mNames;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal statics to avoid object allocations in some operations.
|
* Internal statics to avoid object allocations in some operations.
|
||||||
@@ -47,8 +51,10 @@ public class WorkSource implements Parcelable {
|
|||||||
mNum = orig.mNum;
|
mNum = orig.mNum;
|
||||||
if (orig.mUids != null) {
|
if (orig.mUids != null) {
|
||||||
mUids = orig.mUids.clone();
|
mUids = orig.mUids.clone();
|
||||||
|
mNames = orig.mNames != null ? orig.mNames.clone() : null;
|
||||||
} else {
|
} else {
|
||||||
mUids = null;
|
mUids = null;
|
||||||
|
mNames = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,11 +62,23 @@ public class WorkSource implements Parcelable {
|
|||||||
public WorkSource(int uid) {
|
public WorkSource(int uid) {
|
||||||
mNum = 1;
|
mNum = 1;
|
||||||
mUids = new int[] { uid, 0 };
|
mUids = new int[] { uid, 0 };
|
||||||
|
mNames = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public WorkSource(int uid, String name) {
|
||||||
|
if (name == null) {
|
||||||
|
throw new NullPointerException("Name can't be null");
|
||||||
|
}
|
||||||
|
mNum = 1;
|
||||||
|
mUids = new int[] { uid, 0 };
|
||||||
|
mNames = new String[] { name, null };
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkSource(Parcel in) {
|
WorkSource(Parcel in) {
|
||||||
mNum = in.readInt();
|
mNum = in.readInt();
|
||||||
mUids = in.createIntArray();
|
mUids = in.createIntArray();
|
||||||
|
mNames = in.createStringArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@@ -73,6 +91,11 @@ public class WorkSource implements Parcelable {
|
|||||||
return mUids[index];
|
return mUids[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public String getName(int index) {
|
||||||
|
return mNames != null ? mNames[index] : null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear this WorkSource to be empty.
|
* Clear this WorkSource to be empty.
|
||||||
*/
|
*/
|
||||||
@@ -91,6 +114,11 @@ public class WorkSource implements Parcelable {
|
|||||||
for (int i = 0; i < mNum; i++) {
|
for (int i = 0; i < mNum; i++) {
|
||||||
result = ((result << 4) | (result >>> 28)) ^ mUids[i];
|
result = ((result << 4) | (result >>> 28)) ^ mUids[i];
|
||||||
}
|
}
|
||||||
|
if (mNames != null) {
|
||||||
|
for (int i = 0; i < mNum; i++) {
|
||||||
|
result = ((result << 4) | (result >>> 28)) ^ mNames[i].hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,10 +134,15 @@ public class WorkSource implements Parcelable {
|
|||||||
}
|
}
|
||||||
final int[] uids1 = mUids;
|
final int[] uids1 = mUids;
|
||||||
final int[] uids2 = other.mUids;
|
final int[] uids2 = other.mUids;
|
||||||
|
final String[] names1 = mNames;
|
||||||
|
final String[] names2 = other.mNames;
|
||||||
for (int i=0; i<N; i++) {
|
for (int i=0; i<N; i++) {
|
||||||
if (uids1[i] != uids2[i]) {
|
if (uids1[i] != uids2[i]) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (names1 != null && names2 != null && !names1[i].equals(names2[i])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -131,8 +164,18 @@ public class WorkSource implements Parcelable {
|
|||||||
} else {
|
} else {
|
||||||
mUids = other.mUids.clone();
|
mUids = other.mUids.clone();
|
||||||
}
|
}
|
||||||
|
if (other.mNames != null) {
|
||||||
|
if (mNames != null && mNames.length >= mNum) {
|
||||||
|
System.arraycopy(other.mNames, 0, mNames, 0, mNum);
|
||||||
|
} else {
|
||||||
|
mNames = other.mNames.clone();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mNames = null;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
mUids = null;
|
mUids = null;
|
||||||
|
mNames = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,6 +184,22 @@ public class WorkSource implements Parcelable {
|
|||||||
mNum = 1;
|
mNum = 1;
|
||||||
if (mUids == null) mUids = new int[2];
|
if (mUids == null) mUids = new int[2];
|
||||||
mUids[0] = uid;
|
mUids[0] = uid;
|
||||||
|
mNames = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public void set(int uid, String name) {
|
||||||
|
if (name == null) {
|
||||||
|
throw new NullPointerException("Name can't be null");
|
||||||
|
}
|
||||||
|
mNum = 1;
|
||||||
|
if (mUids == null) {
|
||||||
|
mUids = new int[2];
|
||||||
|
mNames = new String[2];
|
||||||
|
}
|
||||||
|
mUids[0] = uid;
|
||||||
|
mNames[0] = name;
|
||||||
|
mNames = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@@ -182,10 +241,49 @@ public class WorkSource implements Parcelable {
|
|||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public boolean add(int uid) {
|
public boolean add(int uid) {
|
||||||
synchronized (sTmpWorkSource) {
|
if (mNum <= 0) {
|
||||||
sTmpWorkSource.mUids[0] = uid;
|
mNames = null;
|
||||||
return updateLocked(sTmpWorkSource, false, false);
|
insert(0, uid);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
if (mNames != null) {
|
||||||
|
throw new IllegalArgumentException("Adding without name to named " + this);
|
||||||
|
}
|
||||||
|
int i = Arrays.binarySearch(mUids, 0, mNum, uid);
|
||||||
|
if (DEBUG) Log.d(TAG, "Adding uid " + uid + " to " + this + ": binsearch res = " + i);
|
||||||
|
if (i >= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
insert(-i-1, uid);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public boolean add(int uid, String name) {
|
||||||
|
if (mNum <= 0) {
|
||||||
|
insert(0, uid, name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (mNames == null) {
|
||||||
|
throw new IllegalArgumentException("Adding name to unnamed " + this);
|
||||||
|
}
|
||||||
|
int i;
|
||||||
|
for (i=0; i<mNum; i++) {
|
||||||
|
if (mUids[i] > uid) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (mUids[i] == uid) {
|
||||||
|
int diff = mNames[i].compareTo(name);
|
||||||
|
if (diff > 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (diff == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
insert(i, uid, name);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@@ -199,19 +297,102 @@ public class WorkSource implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean remove(WorkSource other) {
|
public boolean remove(WorkSource other) {
|
||||||
|
if (mNum <= 0 || other.mNum <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (mNames == null && other.mNames == null) {
|
||||||
|
return removeUids(other);
|
||||||
|
} else {
|
||||||
|
if (mNames == null) {
|
||||||
|
throw new IllegalArgumentException("Other " + other + " has names, but target "
|
||||||
|
+ this + " does not");
|
||||||
|
}
|
||||||
|
if (other.mNames == null) {
|
||||||
|
throw new IllegalArgumentException("Target " + this + " has names, but other "
|
||||||
|
+ other + " does not");
|
||||||
|
}
|
||||||
|
return removeUidsAndNames(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public WorkSource stripNames() {
|
||||||
|
if (mNum <= 0) {
|
||||||
|
return new WorkSource();
|
||||||
|
}
|
||||||
|
WorkSource result = new WorkSource();
|
||||||
|
int lastUid = -1;
|
||||||
|
for (int i=0; i<mNum; i++) {
|
||||||
|
int uid = mUids[i];
|
||||||
|
if (i == 0 || lastUid != uid) {
|
||||||
|
result.add(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean removeUids(WorkSource other) {
|
||||||
int N1 = mNum;
|
int N1 = mNum;
|
||||||
final int[] uids1 = mUids;
|
final int[] uids1 = mUids;
|
||||||
final int N2 = other.mNum;
|
final int N2 = other.mNum;
|
||||||
final int[] uids2 = other.mUids;
|
final int[] uids2 = other.mUids;
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
int i1 = 0;
|
int i1 = 0, i2 = 0;
|
||||||
for (int i2=0; i2<N2 && i1<N1; i2++) {
|
if (DEBUG) Log.d(TAG, "Remove " + other + " from " + this);
|
||||||
|
while (i1 < N1 && i2 < N2) {
|
||||||
|
if (DEBUG) Log.d(TAG, "Step: target @ " + i1 + " of " + N1 + ", other @ " + i2
|
||||||
|
+ " of " + N2);
|
||||||
if (uids2[i2] == uids1[i1]) {
|
if (uids2[i2] == uids1[i1]) {
|
||||||
|
if (DEBUG) Log.d(TAG, "i1=" + i1 + " i2=" + i2 + " N1=" + N1
|
||||||
|
+ ": remove " + uids1[i1]);
|
||||||
N1--;
|
N1--;
|
||||||
|
changed = true;
|
||||||
if (i1 < N1) System.arraycopy(uids1, i1+1, uids1, i1, N1-i1);
|
if (i1 < N1) System.arraycopy(uids1, i1+1, uids1, i1, N1-i1);
|
||||||
}
|
i2++;
|
||||||
while (i1 < N1 && uids2[i2] > uids1[i1]) {
|
} else if (uids2[i2] > uids1[i1]) {
|
||||||
|
if (DEBUG) Log.d(TAG, "i1=" + i1 + " i2=" + i2 + " N1=" + N1 + ": skip i1");
|
||||||
i1++;
|
i1++;
|
||||||
|
} else {
|
||||||
|
if (DEBUG) Log.d(TAG, "i1=" + i1 + " i2=" + i2 + " N1=" + N1 + ": skip i2");
|
||||||
|
i2++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mNum = N1;
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean removeUidsAndNames(WorkSource other) {
|
||||||
|
int N1 = mNum;
|
||||||
|
final int[] uids1 = mUids;
|
||||||
|
final String[] names1 = mNames;
|
||||||
|
final int N2 = other.mNum;
|
||||||
|
final int[] uids2 = other.mUids;
|
||||||
|
final String[] names2 = other.mNames;
|
||||||
|
boolean changed = false;
|
||||||
|
int i1 = 0, i2 = 0;
|
||||||
|
if (DEBUG) Log.d(TAG, "Remove " + other + " from " + this);
|
||||||
|
while (i1 < N1 && i2 < N2) {
|
||||||
|
if (DEBUG) Log.d(TAG, "Step: target @ " + i1 + " of " + N1 + ", other @ " + i2
|
||||||
|
+ " of " + N2 + ": " + uids1[i1] + " " + names1[i1]);
|
||||||
|
if (uids2[i2] == uids1[i1] && names2[i2].equals(names1[i1])) {
|
||||||
|
if (DEBUG) Log.d(TAG, "i1=" + i1 + " i2=" + i2 + " N1=" + N1
|
||||||
|
+ ": remove " + uids1[i1] + " " + names1[i1]);
|
||||||
|
N1--;
|
||||||
|
changed = true;
|
||||||
|
if (i1 < N1) {
|
||||||
|
System.arraycopy(uids1, i1+1, uids1, i1, N1-i1);
|
||||||
|
System.arraycopy(names1, i1+1, names1, i1, N1-i1);
|
||||||
|
}
|
||||||
|
i2++;
|
||||||
|
} else if (uids2[i2] > uids1[i1]
|
||||||
|
|| (uids2[i2] == uids1[i1] && names2[i2].compareTo(names1[i1]) > 0)) {
|
||||||
|
if (DEBUG) Log.d(TAG, "i1=" + i1 + " i2=" + i2 + " N1=" + N1 + ": skip i1");
|
||||||
|
i1++;
|
||||||
|
} else {
|
||||||
|
if (DEBUG) Log.d(TAG, "i1=" + i1 + " i2=" + i2 + " N1=" + N1 + ": skip i2");
|
||||||
|
i2++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,20 +402,50 @@ public class WorkSource implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean updateLocked(WorkSource other, boolean set, boolean returnNewbs) {
|
private boolean updateLocked(WorkSource other, boolean set, boolean returnNewbs) {
|
||||||
|
if (mNames == null && other.mNames == null) {
|
||||||
|
return updateUidsLocked(other, set, returnNewbs);
|
||||||
|
} else {
|
||||||
|
if (mNum > 0 && mNames == null) {
|
||||||
|
throw new IllegalArgumentException("Other " + other + " has names, but target "
|
||||||
|
+ this + " does not");
|
||||||
|
}
|
||||||
|
if (other.mNum > 0 && other.mNames == null) {
|
||||||
|
throw new IllegalArgumentException("Target " + this + " has names, but other "
|
||||||
|
+ other + " does not");
|
||||||
|
}
|
||||||
|
return updateUidsAndNamesLocked(other, set, returnNewbs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WorkSource addWork(WorkSource cur, int newUid) {
|
||||||
|
if (cur == null) {
|
||||||
|
return new WorkSource(newUid);
|
||||||
|
}
|
||||||
|
cur.insert(cur.mNum, newUid);
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean updateUidsLocked(WorkSource other, boolean set, boolean returnNewbs) {
|
||||||
int N1 = mNum;
|
int N1 = mNum;
|
||||||
int[] uids1 = mUids;
|
int[] uids1 = mUids;
|
||||||
final int N2 = other.mNum;
|
final int N2 = other.mNum;
|
||||||
final int[] uids2 = other.mUids;
|
final int[] uids2 = other.mUids;
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
int i1 = 0;
|
int i1 = 0, i2 = 0;
|
||||||
for (int i2=0; i2<N2; i2++) {
|
if (DEBUG) Log.d(TAG, "Update " + this + " with " + other + " set=" + set
|
||||||
if (i1 >= N1 || uids2[i2] < uids1[i1]) {
|
+ " returnNewbs=" + returnNewbs);
|
||||||
|
while (i1 < N1 || i2 < N2) {
|
||||||
|
if (DEBUG) Log.d(TAG, "Step: target @ " + i1 + " of " + N1 + ", other @ " + i2
|
||||||
|
+ " of " + N2);
|
||||||
|
if (i1 >= N1 || (i2 < N2 && uids2[i2] < uids1[i1])) {
|
||||||
// Need to insert a new uid.
|
// Need to insert a new uid.
|
||||||
|
if (DEBUG) Log.d(TAG, "i1=" + i1 + " i2=" + i2 + " N1=" + N1
|
||||||
|
+ ": insert " + uids2[i2]);
|
||||||
changed = true;
|
changed = true;
|
||||||
if (uids1 == null) {
|
if (uids1 == null) {
|
||||||
uids1 = new int[4];
|
uids1 = new int[4];
|
||||||
uids1[0] = uids2[i2];
|
uids1[0] = uids2[i2];
|
||||||
} else if (i1 >= uids1.length) {
|
} else if (N1 >= uids1.length) {
|
||||||
int[] newuids = new int[(uids1.length*3)/2];
|
int[] newuids = new int[(uids1.length*3)/2];
|
||||||
if (i1 > 0) System.arraycopy(uids1, 0, newuids, 0, i1);
|
if (i1 > 0) System.arraycopy(uids1, 0, newuids, 0, i1);
|
||||||
if (i1 < N1) System.arraycopy(uids1, i1, newuids, i1+1, N1-i1);
|
if (i1 < N1) System.arraycopy(uids1, i1, newuids, i1+1, N1-i1);
|
||||||
@@ -245,39 +456,37 @@ public class WorkSource implements Parcelable {
|
|||||||
uids1[i1] = uids2[i2];
|
uids1[i1] = uids2[i2];
|
||||||
}
|
}
|
||||||
if (returnNewbs) {
|
if (returnNewbs) {
|
||||||
if (sNewbWork == null) {
|
sNewbWork = addWork(sNewbWork, uids2[i2]);
|
||||||
sNewbWork = new WorkSource(uids2[i2]);
|
|
||||||
} else {
|
|
||||||
sNewbWork.addLocked(uids2[i2]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
N1++;
|
N1++;
|
||||||
i1++;
|
i1++;
|
||||||
|
i2++;
|
||||||
} else {
|
} else {
|
||||||
if (!set) {
|
if (!set) {
|
||||||
// Skip uids that already exist or are not in 'other'.
|
// Skip uids that already exist or are not in 'other'.
|
||||||
do {
|
if (DEBUG) Log.d(TAG, "i1=" + i1 + " i2=" + i2 + " N1=" + N1 + ": skip");
|
||||||
i1++;
|
if (i2 < N2 && uids2[i2] == uids1[i1]) {
|
||||||
} while (i1 < N1 && uids2[i2] >= uids1[i1]);
|
i2++;
|
||||||
|
}
|
||||||
|
i1++;
|
||||||
} else {
|
} else {
|
||||||
// Remove any uids that don't exist in 'other'.
|
// Remove any uids that don't exist in 'other'.
|
||||||
int start = i1;
|
int start = i1;
|
||||||
while (i1 < N1 && uids2[i2] > uids1[i1]) {
|
while (i1 < N1 && (i2 >= N2 || uids2[i2] > uids1[i1])) {
|
||||||
if (sGoneWork == null) {
|
if (DEBUG) Log.d(TAG, "i1=" + i1 + " i2=" + i2 + ": remove " + uids1[i1]);
|
||||||
sGoneWork = new WorkSource(uids1[i1]);
|
sGoneWork = addWork(sGoneWork, uids1[i1]);
|
||||||
} else {
|
|
||||||
sGoneWork.addLocked(uids1[i1]);
|
|
||||||
}
|
|
||||||
i1++;
|
i1++;
|
||||||
}
|
}
|
||||||
if (start < i1) {
|
if (start < i1) {
|
||||||
System.arraycopy(uids1, i1, uids1, start, i1-start);
|
System.arraycopy(uids1, i1, uids1, start, N1-i1);
|
||||||
N1 -= i1-start;
|
N1 -= i1-start;
|
||||||
i1 = start;
|
i1 = start;
|
||||||
}
|
}
|
||||||
// If there is a matching uid, skip it.
|
// If there is a matching uid, skip it.
|
||||||
if (i1 < N1 && uids2[i1] == uids1[i1]) {
|
if (i1 < N1 && i2 < N2 && uids2[i2] == uids1[i1]) {
|
||||||
|
if (DEBUG) Log.d(TAG, "i1=" + i1 + " i2=" + i2 + " N1=" + N1 + ": skip");
|
||||||
i1++;
|
i1++;
|
||||||
|
i2++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -289,21 +498,145 @@ public class WorkSource implements Parcelable {
|
|||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addLocked(int uid) {
|
/**
|
||||||
|
* Returns 0 if equal, negative if 'this' is before 'other', positive if 'this' is after 'other'.
|
||||||
|
*/
|
||||||
|
private int compare(WorkSource other, int i1, int i2) {
|
||||||
|
final int diff = mUids[i1] - other.mUids[i2];
|
||||||
|
if (diff != 0) {
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
return mNames[i1].compareTo(other.mNames[i2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WorkSource addWork(WorkSource cur, int newUid, String newName) {
|
||||||
|
if (cur == null) {
|
||||||
|
return new WorkSource(newUid, newName);
|
||||||
|
}
|
||||||
|
cur.insert(cur.mNum, newUid, newName);
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean updateUidsAndNamesLocked(WorkSource other, boolean set, boolean returnNewbs) {
|
||||||
|
final int N2 = other.mNum;
|
||||||
|
final int[] uids2 = other.mUids;
|
||||||
|
String[] names2 = other.mNames;
|
||||||
|
boolean changed = false;
|
||||||
|
int i1 = 0, i2 = 0;
|
||||||
|
if (DEBUG) Log.d(TAG, "Update " + this + " with " + other + " set=" + set
|
||||||
|
+ " returnNewbs=" + returnNewbs);
|
||||||
|
while (i1 < mNum || i2 < N2) {
|
||||||
|
if (DEBUG) Log.d(TAG, "Step: target @ " + i1 + " of " + mNum + ", other @ " + i2
|
||||||
|
+ " of " + N2);
|
||||||
|
int diff = -1;
|
||||||
|
if (i1 >= mNum || (i2 < N2 && (diff=compare(other, i1, i2)) > 0)) {
|
||||||
|
// Need to insert a new uid.
|
||||||
|
changed = true;
|
||||||
|
if (DEBUG) Log.d(TAG, "i1=" + i1 + " i2=" + i2 + " N1=" + mNum
|
||||||
|
+ ": insert " + uids2[i2] + " " + names2[i2]);
|
||||||
|
insert(i1, uids2[i2], names2[i2]);
|
||||||
|
if (returnNewbs) {
|
||||||
|
sNewbWork = addWork(sNewbWork, uids2[i2], names2[i2]);
|
||||||
|
}
|
||||||
|
i1++;
|
||||||
|
i2++;
|
||||||
|
} else {
|
||||||
|
if (!set) {
|
||||||
|
if (DEBUG) Log.d(TAG, "i1=" + i1 + " i2=" + i2 + " N1=" + mNum + ": skip");
|
||||||
|
if (i2 < N2 && diff == 0) {
|
||||||
|
i2++;
|
||||||
|
}
|
||||||
|
i1++;
|
||||||
|
} else {
|
||||||
|
// Remove any uids that don't exist in 'other'.
|
||||||
|
int start = i1;
|
||||||
|
while (diff < 0) {
|
||||||
|
if (DEBUG) Log.d(TAG, "i1=" + i1 + " i2=" + i2 + ": remove " + mUids[i1]
|
||||||
|
+ " " + mNames[i1]);
|
||||||
|
sGoneWork = addWork(sGoneWork, mUids[i1], mNames[i1]);
|
||||||
|
i1++;
|
||||||
|
if (i1 >= mNum) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
diff = i2 < N2 ? compare(other, i1, i2) : -1;
|
||||||
|
}
|
||||||
|
if (start < i1) {
|
||||||
|
System.arraycopy(mUids, i1, mUids, start, mNum-i1);
|
||||||
|
System.arraycopy(mNames, i1, mNames, start, mNum-i1);
|
||||||
|
mNum -= i1-start;
|
||||||
|
i1 = start;
|
||||||
|
}
|
||||||
|
// If there is a matching uid, skip it.
|
||||||
|
if (i1 < mNum && diff == 0) {
|
||||||
|
if (DEBUG) Log.d(TAG, "i1=" + i1 + " i2=" + i2 + " N1=" + mNum + ": skip");
|
||||||
|
i1++;
|
||||||
|
i2++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insert(int index, int uid) {
|
||||||
|
if (DEBUG) Log.d(TAG, "Insert in " + this + " @ " + index + " uid " + uid);
|
||||||
if (mUids == null) {
|
if (mUids == null) {
|
||||||
mUids = new int[4];
|
mUids = new int[4];
|
||||||
mUids[0] = uid;
|
mUids[0] = uid;
|
||||||
mNum = 1;
|
mNum = 1;
|
||||||
return;
|
} else if (mNum >= mUids.length) {
|
||||||
}
|
|
||||||
if (mNum >= mUids.length) {
|
|
||||||
int[] newuids = new int[(mNum*3)/2];
|
int[] newuids = new int[(mNum*3)/2];
|
||||||
System.arraycopy(mUids, 0, newuids, 0, mNum);
|
if (index > 0) {
|
||||||
|
System.arraycopy(mUids, 0, newuids, 0, index);
|
||||||
|
}
|
||||||
|
if (index < mNum) {
|
||||||
|
System.arraycopy(mUids, index, newuids, index+1, mNum-index);
|
||||||
|
}
|
||||||
mUids = newuids;
|
mUids = newuids;
|
||||||
|
mUids[index] = uid;
|
||||||
|
mNum++;
|
||||||
|
} else {
|
||||||
|
if (index < mNum) {
|
||||||
|
System.arraycopy(mUids, index, mUids, index+1, mNum-index);
|
||||||
|
}
|
||||||
|
mUids[index] = uid;
|
||||||
|
mNum++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mUids[mNum] = uid;
|
private void insert(int index, int uid, String name) {
|
||||||
mNum++;
|
if (mUids == null) {
|
||||||
|
mUids = new int[4];
|
||||||
|
mUids[0] = uid;
|
||||||
|
mNames = new String[4];
|
||||||
|
mNames[0] = name;
|
||||||
|
mNum = 1;
|
||||||
|
} else if (mNum >= mUids.length) {
|
||||||
|
int[] newuids = new int[(mNum*3)/2];
|
||||||
|
String[] newnames = new String[(mNum*3)/2];
|
||||||
|
if (index > 0) {
|
||||||
|
System.arraycopy(mUids, 0, newuids, 0, index);
|
||||||
|
System.arraycopy(mNames, 0, newnames, 0, index);
|
||||||
|
}
|
||||||
|
if (index < mNum) {
|
||||||
|
System.arraycopy(mUids, index, newuids, index+1, mNum-index);
|
||||||
|
System.arraycopy(mNames, index, newnames, index+1, mNum-index);
|
||||||
|
}
|
||||||
|
mUids = newuids;
|
||||||
|
mNames = newnames;
|
||||||
|
mUids[index] = uid;
|
||||||
|
mNames[index] = name;
|
||||||
|
mNum++;
|
||||||
|
} else {
|
||||||
|
if (index < mNum) {
|
||||||
|
System.arraycopy(mUids, index, mUids, index+1, mNum-index);
|
||||||
|
System.arraycopy(mNames, index, mNames, index+1, mNum-index);
|
||||||
|
}
|
||||||
|
mUids[index] = uid;
|
||||||
|
mNames[index] = name;
|
||||||
|
mNum++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -315,19 +648,24 @@ public class WorkSource implements Parcelable {
|
|||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
dest.writeInt(mNum);
|
dest.writeInt(mNum);
|
||||||
dest.writeIntArray(mUids);
|
dest.writeIntArray(mUids);
|
||||||
|
dest.writeStringArray(mNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder result = new StringBuilder();
|
StringBuilder result = new StringBuilder();
|
||||||
result.append("{WorkSource: uids=[");
|
result.append("WorkSource{");
|
||||||
for (int i = 0; i < mNum; i++) {
|
for (int i = 0; i < mNum; i++) {
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
result.append(", ");
|
result.append(", ");
|
||||||
}
|
}
|
||||||
result.append(mUids[i]);
|
result.append(mUids[i]);
|
||||||
|
if (mNames != null) {
|
||||||
|
result.append(" ");
|
||||||
|
result.append(mNames[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
result.append("]}");
|
result.append("}");
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -189,27 +189,23 @@ public class AppOpsService extends IAppOpsService.Stub {
|
|||||||
if (ops == null) {
|
if (ops == null) {
|
||||||
// This is the first time we have seen this package name under this uid,
|
// This is the first time we have seen this package name under this uid,
|
||||||
// so let's make sure it is valid.
|
// so let's make sure it is valid.
|
||||||
// XXX for now we always allow null through until we can fix everything
|
final long ident = Binder.clearCallingIdentity();
|
||||||
// to provide the name.
|
try {
|
||||||
if (packageName != null) {
|
int pkgUid = -1;
|
||||||
final long ident = Binder.clearCallingIdentity();
|
|
||||||
try {
|
try {
|
||||||
int pkgUid = -1;
|
pkgUid = mContext.getPackageManager().getPackageUid(packageName,
|
||||||
try {
|
UserHandle.getUserId(uid));
|
||||||
pkgUid = mContext.getPackageManager().getPackageUid(packageName,
|
} catch (NameNotFoundException e) {
|
||||||
UserHandle.getUserId(uid));
|
|
||||||
} catch (NameNotFoundException e) {
|
|
||||||
}
|
|
||||||
if (pkgUid != uid) {
|
|
||||||
// Oops! The package name is not valid for the uid they are calling
|
|
||||||
// under. Abort.
|
|
||||||
Slog.w(TAG, "Bad call: specified package " + packageName
|
|
||||||
+ " under uid " + uid + " but it is really " + pkgUid);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
Binder.restoreCallingIdentity(ident);
|
|
||||||
}
|
}
|
||||||
|
if (pkgUid != uid) {
|
||||||
|
// Oops! The package name is not valid for the uid they are calling
|
||||||
|
// under. Abort.
|
||||||
|
Slog.w(TAG, "Bad call: specified package " + packageName
|
||||||
|
+ " under uid " + uid + " but it is really " + pkgUid);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(ident);
|
||||||
}
|
}
|
||||||
ops = new Ops(packageName);
|
ops = new Ops(packageName);
|
||||||
pkgOps.put(packageName, ops);
|
pkgOps.put(packageName, ops);
|
||||||
|
|||||||
@@ -1010,7 +1010,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
|||||||
if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
|
if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
|
||||||
LocationRequest locationRequest = record.mRequest;
|
LocationRequest locationRequest = record.mRequest;
|
||||||
if (locationRequest.getInterval() <= thresholdInterval) {
|
if (locationRequest.getInterval() <= thresholdInterval) {
|
||||||
worksource.add(record.mReceiver.mUid);
|
worksource.add(record.mReceiver.mUid, record.mReceiver.mPackageName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
|||||||
private final IBatteryStats mBatteryStats;
|
private final IBatteryStats mBatteryStats;
|
||||||
|
|
||||||
// only modified on handler thread
|
// only modified on handler thread
|
||||||
private int[] mClientUids = new int[0];
|
private WorkSource mClientSource = new WorkSource();
|
||||||
|
|
||||||
private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
|
private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
|
||||||
@Override
|
@Override
|
||||||
@@ -805,11 +805,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
|||||||
|
|
||||||
if (request.reportLocation) {
|
if (request.reportLocation) {
|
||||||
// update client uids
|
// update client uids
|
||||||
int[] uids = new int[source.size()];
|
updateClientUids(source);
|
||||||
for (int i=0; i < source.size(); i++) {
|
|
||||||
uids[i] = source.get(i);
|
|
||||||
}
|
|
||||||
updateClientUids(uids);
|
|
||||||
|
|
||||||
mFixInterval = (int) request.interval;
|
mFixInterval = (int) request.interval;
|
||||||
|
|
||||||
@@ -831,7 +827,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
|||||||
startNavigating();
|
startNavigating();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
updateClientUids(new int[0]);
|
updateClientUids(new WorkSource());
|
||||||
|
|
||||||
stopNavigating();
|
stopNavigating();
|
||||||
mAlarmManager.cancel(mWakeupIntent);
|
mAlarmManager.cancel(mWakeupIntent);
|
||||||
@@ -859,47 +855,45 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateClientUids(int[] uids) {
|
private void updateClientUids(WorkSource source) {
|
||||||
// Find uid's that were not previously tracked
|
// Update work source.
|
||||||
for (int uid1 : uids) {
|
WorkSource[] changes = mClientSource.setReturningDiffs(source);
|
||||||
boolean newUid = true;
|
WorkSource newWork = changes[0];
|
||||||
for (int uid2 : mClientUids) {
|
WorkSource goneWork = changes[1];
|
||||||
if (uid1 == uid2) {
|
|
||||||
newUid = false;
|
// Update sources that were not previously tracked.
|
||||||
break;
|
if (newWork != null) {
|
||||||
}
|
int lastuid = -1;
|
||||||
}
|
for (int i=0; i<newWork.size(); i++) {
|
||||||
if (newUid) {
|
|
||||||
try {
|
try {
|
||||||
mAppOpsService.startOperation(AppOpsManager.OP_GPS, uid1, null);
|
int uid = newWork.get(i);
|
||||||
mBatteryStats.noteStartGps(uid1);
|
mAppOpsService.startOperation(AppOpsManager.OP_GPS, uid, newWork.getName(i));
|
||||||
|
if (uid != lastuid) {
|
||||||
|
lastuid = uid;
|
||||||
|
mBatteryStats.noteStartGps(uid);
|
||||||
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.w(TAG, "RemoteException", e);
|
Log.w(TAG, "RemoteException", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find uid'd that were tracked but have now disappeared
|
// Update sources that are no longer tracked.
|
||||||
for (int uid1 : mClientUids) {
|
if (goneWork != null) {
|
||||||
boolean oldUid = true;
|
int lastuid = -1;
|
||||||
for (int uid2 : uids) {
|
for (int i=0; i<goneWork.size(); i++) {
|
||||||
if (uid1 == uid2) {
|
|
||||||
oldUid = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldUid) {
|
|
||||||
try {
|
try {
|
||||||
mBatteryStats.noteStopGps(uid1);
|
int uid = goneWork.get(i);
|
||||||
mAppOpsService.finishOperation(AppOpsManager.OP_GPS, uid1, null);
|
mAppOpsService.finishOperation(AppOpsManager.OP_GPS, uid, goneWork.getName(i));
|
||||||
|
if (uid != lastuid) {
|
||||||
|
lastuid = uid;
|
||||||
|
mBatteryStats.noteStopGps(uid);
|
||||||
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.w(TAG, "RemoteException", e);
|
Log.w(TAG, "RemoteException", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// save current uids
|
|
||||||
mClientUids = uids;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user