summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/ActivityManager.java113
-rw-r--r--core/java/android/app/ActivityManagerNative.java31
-rw-r--r--core/java/android/app/ActivityThread.java107
-rw-r--r--core/java/android/app/ApplicationThreadNative.java12
-rw-r--r--core/java/android/app/IActivityManager.java13
-rw-r--r--core/java/android/app/IApplicationThread.java4
-rw-r--r--core/java/android/app/LoaderManager.java4
-rw-r--r--core/java/android/app/PendingIntent.java18
-rw-r--r--core/java/android/bluetooth/BluetoothGatt.java6
-rw-r--r--core/java/android/content/pm/RegisteredServicesCache.java2
-rw-r--r--core/java/android/content/res/Configuration.java8
-rw-r--r--core/java/android/content/res/Resources.java6
-rw-r--r--core/java/android/database/DatabaseUtils.java12
-rw-r--r--core/java/android/os/Debug.java49
-rw-r--r--core/java/android/os/Trace.java2
-rw-r--r--core/java/android/preference/Preference.java3
-rw-r--r--core/java/android/service/notification/StatusBarNotification.java8
-rw-r--r--core/java/android/util/ArrayMap.java615
-rw-r--r--core/java/android/util/LongSparseArray.java16
-rw-r--r--core/java/android/util/LongSparseLongArray.java16
-rw-r--r--core/java/android/util/MapCollections.java496
-rw-r--r--core/java/android/util/SparseArray.java62
-rw-r--r--core/java/android/util/SparseBooleanArray.java46
-rw-r--r--core/java/android/util/SparseIntArray.java45
-rw-r--r--core/java/android/util/SparseLongArray.java45
-rw-r--r--core/java/android/view/View.java4
-rw-r--r--core/java/android/view/ViewGroup.java2
-rw-r--r--core/java/android/widget/AbsListView.java4
-rw-r--r--core/java/android/widget/CalendarView.java2
-rw-r--r--core/java/android/widget/Toast.java72
30 files changed, 1558 insertions, 265 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 1f6f421..63ac42e 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1238,6 +1238,97 @@ public class ActivityManager {
}
}
+ /**
+ * Information you can retrieve about the WindowManager StackBox hierarchy.
+ * @hide
+ */
+ public static class StackBoxInfo implements Parcelable {
+ public int stackBoxId;
+ public float weight;
+ public boolean vertical;
+ public Rect bounds;
+ public StackBoxInfo[] children;
+ public int stackId;
+ public StackInfo stack;
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(stackBoxId);
+ dest.writeFloat(weight);
+ dest.writeInt(vertical ? 1 : 0);
+ bounds.writeToParcel(dest, flags);
+ dest.writeInt(stackId);
+ if (children != null) {
+ children[0].writeToParcel(dest, flags);
+ children[1].writeToParcel(dest, flags);
+ } else {
+ stack.writeToParcel(dest, flags);
+ }
+ }
+
+ public void readFromParcel(Parcel source) {
+ stackBoxId = source.readInt();
+ weight = source.readFloat();
+ vertical = source.readInt() == 1;
+ bounds = Rect.CREATOR.createFromParcel(source);
+ stackId = source.readInt();
+ if (stackId == -1) {
+ children = new StackBoxInfo[2];
+ children[0] = StackBoxInfo.CREATOR.createFromParcel(source);
+ children[1] = StackBoxInfo.CREATOR.createFromParcel(source);
+ } else {
+ stack = StackInfo.CREATOR.createFromParcel(source);
+ }
+ }
+
+ public static final Creator<StackBoxInfo> CREATOR =
+ new Creator<ActivityManager.StackBoxInfo>() {
+
+ @Override
+ public StackBoxInfo createFromParcel(Parcel source) {
+ return new StackBoxInfo(source);
+ }
+
+ @Override
+ public StackBoxInfo[] newArray(int size) {
+ return new StackBoxInfo[size];
+ }
+ };
+
+ public StackBoxInfo() {
+ }
+
+ public StackBoxInfo(Parcel source) {
+ readFromParcel(source);
+ }
+
+ public String toString(String prefix) {
+ StringBuilder sb = new StringBuilder(256);
+ sb.append(prefix); sb.append("Box id=" + stackBoxId); sb.append(" weight=" + weight);
+ sb.append(" vertical=" + vertical); sb.append(" bounds=" + bounds.toShortString());
+ sb.append("\n");
+ if (children != null) {
+ sb.append(prefix); sb.append("First child=\n");
+ sb.append(children[0].toString(prefix + " "));
+ sb.append(prefix); sb.append("Second child=\n");
+ sb.append(children[1].toString(prefix + " "));
+ } else {
+ sb.append(prefix); sb.append("Stack=\n");
+ sb.append(stack.toString(prefix + " "));
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public String toString() {
+ return toString("");
+ }
+ }
/**
* Information you can retrieve about an ActivityStack in the system.
@@ -1249,9 +1340,6 @@ public class ActivityManager {
public int[] taskIds;
public String[] taskNames;
- public StackInfo() {
- }
-
@Override
public int describeContents() {
return 0;
@@ -1287,22 +1375,29 @@ public class ActivityManager {
}
};
+ public StackInfo() {
+ }
+
private StackInfo(Parcel source) {
readFromParcel(source);
}
- @Override
- public String toString() {
+ public String toString(String prefix) {
StringBuilder sb = new StringBuilder(256);
- sb.append("Stack id="); sb.append(stackId);
+ sb.append(prefix); sb.append("Stack id="); sb.append(stackId);
sb.append(" bounds="); sb.append(bounds.toShortString()); sb.append("\n");
- final String prefix = " ";
+ prefix = prefix + " ";
for (int i = 0; i < taskIds.length; ++i) {
sb.append(prefix); sb.append("taskId="); sb.append(taskIds[i]);
sb.append(": "); sb.append(taskNames[i]); sb.append("\n");
}
return sb.toString();
}
+
+ @Override
+ public String toString() {
+ return toString("");
+ }
}
/**
@@ -1378,10 +1473,12 @@ public class ActivityManager {
public ProcessErrorStateInfo() {
}
+ @Override
public int describeContents() {
return 0;
}
+ @Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(condition);
dest.writeString(processName);
@@ -1392,7 +1489,7 @@ public class ActivityManager {
dest.writeString(longMsg);
dest.writeString(stackTrace);
}
-
+
public void readFromParcel(Parcel source) {
condition = source.readInt();
processName = source.readString();
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index b197f90..27e20b9 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -16,6 +16,7 @@
package android.app;
+import android.app.ActivityManager.StackBoxInfo;
import android.content.ComponentName;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
@@ -632,16 +633,16 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
case RESIZE_STACK_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
- int stackId = data.readInt();
+ int stackBoxId = data.readInt();
float weight = data.readFloat();
- resizeStack(stackId, weight);
+ resizeStackBox(stackBoxId, weight);
reply.writeNoException();
return true;
}
- case GET_STACKS_TRANSACTION: {
+ case GET_STACK_BOXES_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
- List<ActivityManager.StackInfo> list = getStacks();
+ List<StackBoxInfo> list = getStackBoxes();
reply.writeNoException();
reply.writeTypedList(list);
return true;
@@ -1409,7 +1410,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
data.enforceInterface(IActivityManager.descriptor);
String pkg = data.readString();
int appid = data.readInt();
- killApplicationWithAppId(pkg, appid);
+ String reason = data.readString();
+ killApplicationWithAppId(pkg, appid, reason);
reply.writeNoException();
return true;
}
@@ -2612,14 +2614,14 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
@Override
- public int createStack(int taskId, int relativeStackId, int position, float weight)
+ public int createStack(int taskId, int relativeStackBoxId, int position, float weight)
throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(taskId);
- data.writeInt(relativeStackId);
+ data.writeInt(relativeStackBoxId);
data.writeInt(position);
data.writeFloat(weight);
mRemote.transact(CREATE_STACK_TRANSACTION, data, reply, 0);
@@ -2644,12 +2646,12 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
@Override
- public void resizeStack(int stackId, float weight) throws RemoteException
+ public void resizeStackBox(int stackBoxId, float weight) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeInt(stackId);
+ data.writeInt(stackBoxId);
data.writeFloat(weight);
mRemote.transact(RESIZE_STACK_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
reply.readException();
@@ -2657,15 +2659,14 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
@Override
- public List<ActivityManager.StackInfo> getStacks() throws RemoteException
+ public List<StackBoxInfo> getStackBoxes() throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(GET_STACKS_TRANSACTION, data, reply, 0);
+ mRemote.transact(GET_STACK_BOXES_TRANSACTION, data, reply, 0);
reply.readException();
- ArrayList<ActivityManager.StackInfo> list
- = reply.createTypedArrayList(ActivityManager.StackInfo.CREATOR);
+ ArrayList<StackBoxInfo> list = reply.createTypedArrayList(StackBoxInfo.CREATOR);
data.recycle();
reply.recycle();
return list;
@@ -3692,12 +3693,14 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
}
- public void killApplicationWithAppId(String pkg, int appid) throws RemoteException {
+ public void killApplicationWithAppId(String pkg, int appid, String reason)
+ throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeString(pkg);
data.writeInt(appid);
+ data.writeString(reason);
mRemote.transact(KILL_APPLICATION_WITH_APPID_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d1bf0af..4a41896 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -895,17 +895,18 @@ public final class ActivityThread {
@Override
public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, boolean checkin,
- boolean all, String[] args) {
+ boolean dumpInfo, boolean dumpDalvik, String[] args) {
FileOutputStream fout = new FileOutputStream(fd);
PrintWriter pw = new PrintWriter(fout);
try {
- return dumpMemInfo(pw, checkin, all);
+ return dumpMemInfo(pw, checkin, dumpInfo, dumpDalvik);
} finally {
pw.flush();
}
}
- private Debug.MemoryInfo dumpMemInfo(PrintWriter pw, boolean checkin, boolean all) {
+ private Debug.MemoryInfo dumpMemInfo(PrintWriter pw, boolean checkin, boolean dumpInfo,
+ boolean dumpDalvik) {
long nativeMax = Debug.getNativeHeapSize() / 1024;
long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
@@ -913,7 +914,7 @@ public final class ActivityThread {
Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
Debug.getMemoryInfo(memInfo);
- if (!all) {
+ if (!dumpInfo) {
return memInfo;
}
@@ -1040,16 +1041,20 @@ public final class ActivityThread {
}
// otherwise, show human-readable format
- printRow(pw, HEAP_COLUMN, "", "", "Swapable","Shared", "Private", "Shared", "Private", "Heap", "Heap", "Heap");
- printRow(pw, HEAP_COLUMN, "", "Pss", "Pss", "Dirty", "Dirty", "Clean", "Clean", "Size", "Alloc", "Free");
- printRow(pw, HEAP_COLUMN, "", "------", "------", "------", "------", "------", "------", "------", "------",
- "------");
- printRow(pw, HEAP_COLUMN, "Native", memInfo.nativePss, memInfo.nativeSwappablePss, memInfo.nativeSharedDirty,
- memInfo.nativePrivateDirty, memInfo.nativeSharedClean, memInfo.nativePrivateClean,nativeMax,
- nativeAllocated, nativeFree);
- printRow(pw, HEAP_COLUMN, "Dalvik", memInfo.dalvikPss, memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty,
- memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean, memInfo.dalvikPrivateClean, dalvikMax, dalvikAllocated,
- dalvikFree);
+ printRow(pw, HEAP_COLUMN, "", "Pss", "Pss","Shared", "Private", "Shared", "Private",
+ "Heap", "Heap", "Heap");
+ printRow(pw, HEAP_COLUMN, "", "Total", "Clean", "Dirty", "Dirty", "Clean", "Clean",
+ "Size", "Alloc", "Free");
+ printRow(pw, HEAP_COLUMN, "", "------", "------", "------", "------", "------",
+ "------", "------", "------", "------");
+ printRow(pw, HEAP_COLUMN, "Native Heap", memInfo.nativePss, memInfo.nativeSwappablePss,
+ memInfo.nativeSharedDirty,
+ memInfo.nativePrivateDirty, memInfo.nativeSharedClean,
+ memInfo.nativePrivateClean, nativeMax, nativeAllocated, nativeFree);
+ printRow(pw, HEAP_COLUMN, "Dalvik Heap", memInfo.dalvikPss, memInfo.dalvikSwappablePss,
+ memInfo.dalvikSharedDirty,
+ memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean,
+ memInfo.dalvikPrivateClean, dalvikMax, dalvikAllocated, dalvikFree);
int otherPss = memInfo.otherPss;
int otherSwappablePss = memInfo.otherSwappablePss;
@@ -1059,42 +1064,56 @@ public final class ActivityThread {
int otherPrivateClean = memInfo.otherPrivateClean;
for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
- printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
- memInfo.getOtherPss(i), memInfo.getOtherSwappablePss(i), memInfo.getOtherSharedDirty(i),
- memInfo.getOtherPrivateDirty(i), memInfo.getOtherSharedClean(i), memInfo.getOtherPrivateClean(i),
- "", "", "");
- otherPss -= memInfo.getOtherPss(i);
- otherSwappablePss -= memInfo.getOtherSwappablePss(i);
- otherSharedDirty -= memInfo.getOtherSharedDirty(i);
- otherPrivateDirty -= memInfo.getOtherPrivateDirty(i);
- otherSharedClean -= memInfo.getOtherSharedClean(i);
- otherPrivateClean -= memInfo.getOtherPrivateClean(i);
+ final int myPss = memInfo.getOtherPss(i);
+ final int mySwappablePss = memInfo.getOtherSwappablePss(i);
+ final int mySharedDirty = memInfo.getOtherSharedDirty(i);
+ final int myPrivateDirty = memInfo.getOtherPrivateDirty(i);
+ final int mySharedClean = memInfo.getOtherSharedClean(i);
+ final int myPrivateClean = memInfo.getOtherPrivateClean(i);
+ if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
+ || mySharedClean != 0 || myPrivateClean != 0) {
+ printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
+ myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
+ mySharedClean, myPrivateClean, "", "", "");
+ otherPss -= myPss;
+ otherSwappablePss -= mySwappablePss;
+ otherSharedDirty -= mySharedDirty;
+ otherPrivateDirty -= myPrivateDirty;
+ otherSharedClean -= mySharedClean;
+ otherPrivateClean -= myPrivateClean;
+ }
}
printRow(pw, HEAP_COLUMN, "Unknown", otherPss, otherSwappablePss, otherSharedDirty,
otherPrivateDirty, otherSharedClean, otherPrivateClean,"", "", "");
- printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(), memInfo.getTotalSwappablePss(),
- memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
- memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(), nativeMax+dalvikMax,
- nativeAllocated+dalvikAllocated, nativeFree+dalvikFree);
-
- pw.println(" ");
- pw.println(" Dalvik");
-
- for (int i=Debug.MemoryInfo.NUM_OTHER_STATS;
- i<Debug.MemoryInfo.NUM_OTHER_STATS + Debug.MemoryInfo.NUM_DVK_STATS; i++) {
- printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
- memInfo.getOtherPss(i), memInfo.getOtherSwappablePss(i), memInfo.getOtherSharedDirty(i),
- memInfo.getOtherPrivateDirty(i), memInfo.getOtherSharedClean(i),
- memInfo.getOtherPrivateClean(i), "", "", "");
- otherPss -= memInfo.getOtherPss(i);
- otherSwappablePss -= memInfo.getOtherSwappablePss(i);
- otherSharedDirty -= memInfo.getOtherSharedDirty(i);
- otherPrivateDirty -= memInfo.getOtherPrivateDirty(i);
- otherSharedClean -= memInfo.getOtherSharedClean(i);
- otherPrivateClean -= memInfo.getOtherPrivateClean(i);
+ printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(),
+ memInfo.getTotalSwappablePss(),
+ memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
+ memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(),
+ nativeMax+dalvikMax,
+ nativeAllocated+dalvikAllocated, nativeFree+dalvikFree);
+
+ if (dumpDalvik) {
+ pw.println(" ");
+ pw.println(" Dalvik Details");
+
+ for (int i=Debug.MemoryInfo.NUM_OTHER_STATS;
+ i<Debug.MemoryInfo.NUM_OTHER_STATS + Debug.MemoryInfo.NUM_DVK_STATS; i++) {
+ final int myPss = memInfo.getOtherPss(i);
+ final int mySwappablePss = memInfo.getOtherSwappablePss(i);
+ final int mySharedDirty = memInfo.getOtherSharedDirty(i);
+ final int myPrivateDirty = memInfo.getOtherPrivateDirty(i);
+ final int mySharedClean = memInfo.getOtherSharedClean(i);
+ final int myPrivateClean = memInfo.getOtherPrivateClean(i);
+ if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
+ || mySharedClean != 0 || myPrivateClean != 0) {
+ printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
+ myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
+ mySharedClean, myPrivateClean, "", "", "");
+ }
+ }
}
pw.println(" ");
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index b1c58f2..e903447 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -524,12 +524,13 @@ public abstract class ApplicationThreadNative extends Binder
data.enforceInterface(IApplicationThread.descriptor);
ParcelFileDescriptor fd = data.readFileDescriptor();
boolean checkin = data.readInt() != 0;
- boolean all = data.readInt() != 0;
+ boolean dumpInfo = data.readInt() != 0;
+ boolean dumpDalvik = data.readInt() != 0;
String[] args = data.readStringArray();
Debug.MemoryInfo mi = null;
if (fd != null) {
try {
- mi = dumpMemInfo(fd.getFileDescriptor(), checkin, all, args);
+ mi = dumpMemInfo(fd.getFileDescriptor(), checkin, dumpInfo, dumpDalvik, args);
} finally {
try {
fd.close();
@@ -1159,14 +1160,15 @@ class ApplicationThreadProxy implements IApplicationThread {
IBinder.FLAG_ONEWAY);
}
- public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, boolean checkin, boolean all,
- String[] args) throws RemoteException {
+ public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, boolean checkin, boolean dumpInfo,
+ boolean dumpDalvik, String[] args) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeFileDescriptor(fd);
data.writeInt(checkin ? 1 : 0);
- data.writeInt(all ? 1 : 0);
+ data.writeInt(dumpInfo ? 1 : 0);
+ data.writeInt(dumpDalvik ? 1 : 0);
data.writeStringArray(args);
mRemote.transact(DUMP_MEM_INFO_TRANSACTION, data, reply, 0);
reply.readException();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 334a304..b48eed2 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -18,7 +18,7 @@ package android.app;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.RunningServiceInfo;
-import android.app.ActivityManager.StackInfo;
+import android.app.ActivityManager.StackBoxInfo;
import android.content.ComponentName;
import android.content.ContentProviderNative;
import android.content.IContentProvider;
@@ -115,11 +115,11 @@ public interface IActivityManager extends IInterface {
public void moveTaskToBack(int task) throws RemoteException;
public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) throws RemoteException;
public void moveTaskBackwards(int task) throws RemoteException;
- public int createStack(int taskId, int relativeStackId, int position, float weight)
+ public int createStack(int taskId, int relativeStackBoxId, int position, float weight)
throws RemoteException;
public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException;
- public void resizeStack(int stackId, float weight) throws RemoteException;
- public List<StackInfo> getStacks() throws RemoteException;
+ public void resizeStackBox(int stackBoxId, float weight) throws RemoteException;
+ public List<StackBoxInfo> getStackBoxes() throws RemoteException;
public void setFocusedStack(int stackId) throws RemoteException;
public int getTaskForActivity(IBinder token, boolean onlyRoot) throws RemoteException;
/* oneway */
@@ -283,7 +283,8 @@ public interface IActivityManager extends IInterface {
public void stopAppSwitches() throws RemoteException;
public void resumeAppSwitches() throws RemoteException;
- public void killApplicationWithAppId(String pkg, int appid) throws RemoteException;
+ public void killApplicationWithAppId(String pkg, int appid, String reason)
+ throws RemoteException;
public void closeSystemDialogs(String reason) throws RemoteException;
@@ -661,6 +662,6 @@ public interface IActivityManager extends IInterface {
int CREATE_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+167;
int MOVE_TASK_TO_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+168;
int RESIZE_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+169;
- int GET_STACKS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+170;
+ int GET_STACK_BOXES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+170;
int SET_FOCUSED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+171;
}
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 3189b31..a009bd3 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -126,8 +126,8 @@ public interface IApplicationThread extends IInterface {
void setCoreSettings(Bundle coreSettings) throws RemoteException;
void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) throws RemoteException;
void scheduleTrimMemory(int level) throws RemoteException;
- Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, boolean checkin, boolean all,
- String[] args) throws RemoteException;
+ Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, boolean checkin, boolean dumpInfo,
+ boolean dumpDalvik, String[] args) throws RemoteException;
void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException;
void dumpDbInfo(FileDescriptor fd, String[] args) throws RemoteException;
void unstableProviderDied(IBinder provider) throws RemoteException;
diff --git a/core/java/android/app/LoaderManager.java b/core/java/android/app/LoaderManager.java
index 267555a..b13b24a 100644
--- a/core/java/android/app/LoaderManager.java
+++ b/core/java/android/app/LoaderManager.java
@@ -204,13 +204,13 @@ class LoaderManagerImpl extends LoaderManager {
// These are the currently active loaders. A loader is here
// from the time its load is started until it has been explicitly
// stopped or restarted by the application.
- final SparseArray<LoaderInfo> mLoaders = new SparseArray<LoaderInfo>();
+ final SparseArray<LoaderInfo> mLoaders = new SparseArray<LoaderInfo>(0);
// These are previously run loaders. This list is maintained internally
// to avoid destroying a loader while an application is still using it.
// It allows an application to restart a loader, but continue using its
// previously run loader until the new loader's data is available.
- final SparseArray<LoaderInfo> mInactiveLoaders = new SparseArray<LoaderInfo>();
+ final SparseArray<LoaderInfo> mInactiveLoaders = new SparseArray<LoaderInfo>(0);
final String mWho;
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 25c790f..bdd0adb 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -207,8 +207,7 @@ public final class PendingIntent implements Parcelable {
*
* @param context The Context in which this PendingIntent should start
* the activity.
- * @param requestCode Private request code for the sender (currently
- * not used).
+ * @param requestCode Private request code for the sender
* @param intent Intent of the activity to be launched.
* @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
* {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
@@ -239,8 +238,7 @@ public final class PendingIntent implements Parcelable {
*
* @param context The Context in which this PendingIntent should start
* the activity.
- * @param requestCode Private request code for the sender (currently
- * not used).
+ * @param requestCode Private request code for the sender
* @param intent Intent of the activity to be launched.
* @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
* {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
@@ -332,8 +330,7 @@ public final class PendingIntent implements Parcelable {
*
* @param context The Context in which this PendingIntent should start
* the activity.
- * @param requestCode Private request code for the sender (currently
- * not used).
+ * @param requestCode Private request code for the sender
* @param intents Array of Intents of the activities to be launched.
* @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
* {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
@@ -383,8 +380,7 @@ public final class PendingIntent implements Parcelable {
*
* @param context The Context in which this PendingIntent should start
* the activity.
- * @param requestCode Private request code for the sender (currently
- * not used).
+ * @param requestCode Private request code for the sender
* @param intents Array of Intents of the activities to be launched.
* @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
* {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
@@ -454,8 +450,7 @@ public final class PendingIntent implements Parcelable {
*
* @param context The Context in which this PendingIntent should perform
* the broadcast.
- * @param requestCode Private request code for the sender (currently
- * not used).
+ * @param requestCode Private request code for the sender
* @param intent The Intent to be broadcast.
* @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
* {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
@@ -509,8 +504,7 @@ public final class PendingIntent implements Parcelable {
*
* @param context The Context in which this PendingIntent should start
* the service.
- * @param requestCode Private request code for the sender (currently
- * not used).
+ * @param requestCode Private request code for the sender
* @param intent An Intent describing the service to be started.
* @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
* {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 4df6e7c..77e5f84 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -70,9 +70,6 @@ public final class BluetoothGatt implements BluetoothProfile {
private List<BluetoothGattService> mServices;
- /** A GATT operation failed */
- public static final int GATT_FAILURE = 0;
-
/** A GATT operation completed successfully */
public static final int GATT_SUCCESS = 0;
@@ -97,6 +94,9 @@ public final class BluetoothGatt implements BluetoothProfile {
/** A write operation exceeds the maximum length of the attribute */
public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 0xd;
+ /** A GATT operation failed, errors other than the above */
+ public static final int GATT_FAILURE = 0x101;
+
/**
* No authentication required.
* @hide
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index 288d55f..875e8de 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -82,7 +82,7 @@ public abstract class RegisteredServicesCache<V> {
@GuardedBy("mServicesLock")
private boolean mPersistentServicesFileDidNotExist;
@GuardedBy("mServicesLock")
- private final SparseArray<UserServices<V>> mUserServices = new SparseArray<UserServices<V>>();
+ private final SparseArray<UserServices<V>> mUserServices = new SparseArray<UserServices<V>>(2);
private static class UserServices<V> {
@GuardedBy("mServicesLock")
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 905ae0d..68db33a 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -853,11 +853,13 @@ public final class Configuration implements Parcelable, Comparable<Configuration
changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
screenHeightDp = delta.screenHeightDp;
}
- if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
- changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
+ if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
+ && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
+ changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
smallestScreenWidthDp = delta.smallestScreenWidthDp;
}
- if (delta.densityDpi != DENSITY_DPI_UNDEFINED) {
+ if (delta.densityDpi != DENSITY_DPI_UNDEFINED &&
+ densityDpi != delta.densityDpi) {
changed |= ActivityInfo.CONFIG_DENSITY;
densityDpi = delta.densityDpi;
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index c7976c3..cff974d 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -99,11 +99,11 @@ public class Resources {
/*package*/ final Configuration mTmpConfig = new Configuration();
/*package*/ TypedValue mTmpValue = new TypedValue();
/*package*/ final LongSparseArray<WeakReference<Drawable.ConstantState> > mDrawableCache
- = new LongSparseArray<WeakReference<Drawable.ConstantState> >();
+ = new LongSparseArray<WeakReference<Drawable.ConstantState> >(0);
/*package*/ final LongSparseArray<WeakReference<ColorStateList> > mColorStateListCache
- = new LongSparseArray<WeakReference<ColorStateList> >();
+ = new LongSparseArray<WeakReference<ColorStateList> >(0);
/*package*/ final LongSparseArray<WeakReference<Drawable.ConstantState> > mColorDrawableCache
- = new LongSparseArray<WeakReference<Drawable.ConstantState> >();
+ = new LongSparseArray<WeakReference<Drawable.ConstantState> >(0);
/*package*/ boolean mPreloading;
/*package*/ TypedArray mCachedStyledAttributes = null;
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 1fc1226..e2d9724 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -792,6 +792,18 @@ public class DatabaseUtils {
}
/**
+ * Query the table to check whether a table is empty or not
+ * @param db the database the table is in
+ * @param table the name of the table to query
+ * @return True if the table is empty
+ * @hide
+ */
+ public static boolean queryIsEmpty(SQLiteDatabase db, String table) {
+ long isEmpty = longForQuery(db, "select exists(select 1 from " + table + ")", null);
+ return isEmpty == 0;
+ }
+
+ /**
* Utility method to run the query on the db and return the value in the
* first column of the first row.
*/
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index d8e30e2..362ae29 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -108,19 +108,19 @@ public final class Debug
* process. The returns info broken down by dalvik, native, and other. All results are in kB.
*/
public static class MemoryInfo implements Parcelable {
- /** The proportional set size for dalvik. */
+ /** The proportional set size for dalvik heap. (Doesn't include other Dalvik overhead.) */
public int dalvikPss;
- /** The proportional set size that is swappable for dalvik. */
+ /** The proportional set size that is swappable for dalvik heap. */
/** @hide We may want to expose this, eventually. */
public int dalvikSwappablePss;
- /** The private dirty pages used by dalvik. */
+ /** The private dirty pages used by dalvik heap. */
public int dalvikPrivateDirty;
- /** The shared dirty pages used by dalvik. */
+ /** The shared dirty pages used by dalvik heap. */
public int dalvikSharedDirty;
- /** The private clean pages used by dalvik. */
+ /** The private clean pages used by dalvik heap. */
/** @hide We may want to expose this, eventually. */
public int dalvikPrivateClean;
- /** The shared clean pages used by dalvik. */
+ /** The shared clean pages used by dalvik heap. */
/** @hide We may want to expose this, eventually. */
public int dalvikSharedClean;
@@ -157,7 +157,7 @@ public final class Debug
public int otherSharedClean;
/** @hide */
- public static final int NUM_OTHER_STATS = 12;
+ public static final int NUM_OTHER_STATS = 13;
/** @hide */
public static final int NUM_DVK_STATS = 5;
@@ -263,23 +263,24 @@ public final class Debug
/* @hide */
public static String getOtherLabel(int which) {
switch (which) {
- case 0: return "Stack";
- case 1: return "Cursor";
- case 2: return "Ashmem";
- case 3: return "Other dev";
- case 4: return ".so mmap";
- case 5: return ".jar mmap";
- case 6: return ".apk mmap";
- case 7: return ".ttf mmap";
- case 8: return ".dex mmap";
- case 9: return "code mmap";
- case 10: return "image mmap";
- case 11: return "Other mmap";
- case 12: return ".Heap";
- case 13: return ".LOS";
- case 14: return ".LinearAlloc";
- case 15: return ".GC";
- case 16: return ".JITCache";
+ case 0: return "Dalvik Other";
+ case 1: return "Stack";
+ case 2: return "Cursor";
+ case 3: return "Ashmem";
+ case 4: return "Other dev";
+ case 5: return ".so mmap";
+ case 6: return ".jar mmap";
+ case 7: return ".apk mmap";
+ case 8: return ".ttf mmap";
+ case 9: return ".dex mmap";
+ case 10: return "code mmap";
+ case 11: return "image mmap";
+ case 12: return "Other mmap";
+ case 13: return ".Heap";
+ case 14: return ".LOS";
+ case 15: return ".LinearAlloc";
+ case 16: return ".GC";
+ case 17: return ".JITCache";
default: return "????";
}
}
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index e53cb5e..bb3d296 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -67,6 +67,8 @@ public final class Trace {
public static final long TRACE_TAG_RESOURCES = 1L << 13;
/** @hide */
public static final long TRACE_TAG_DALVIK = 1L << 14;
+ /** @hide */
+ public static final long TRACE_TAG_RS = 1L << 15;
private static final long TRACE_TAG_NOT_READY = 1L << 63;
private static final int MAX_SECTION_NAME_LEN = 127;
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index e343e83..6c02965 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -1072,6 +1072,9 @@ public class Preference implements Comparable<Preference>, OnDependencyChangeLis
|| (mOrder == DEFAULT_ORDER && another.mOrder != DEFAULT_ORDER)) {
// Do order comparison
return mOrder - another.mOrder;
+ } else if (mTitle == another.mTitle) {
+ // If titles are null or share same object comparison
+ return 0;
} else if (mTitle == null) {
return 1;
} else if (another.mTitle == null) {
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index e8cc24b..19f8678 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -190,13 +190,13 @@ public class StatusBarNotification implements Parcelable {
return pkg;
}
- /** The id supplied to {@link android.app.NotificationManager#notify}. */
+ /** The id supplied to {@link android.app.NotificationManager#notify(int,Notification)}. */
public int getId() {
return id;
}
- /** The tag supplied to {@link android.app.NotificationManager#notify}, or null if no tag
- * was specified. */
+ /** The tag supplied to {@link android.app.NotificationManager#notify(int,Notification)},
+ * or null if no tag was specified. */
public String getTag() {
return tag;
}
@@ -217,7 +217,7 @@ public class StatusBarNotification implements Parcelable {
}
/** The {@link android.app.Notification} supplied to
- * {@link android.app.NotificationManager#notify}. */
+ * {@link android.app.NotificationManager#notify(int,Notification)}. */
public Notification getNotification() {
return notification;
}
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
new file mode 100644
index 0000000..70f7d2e
--- /dev/null
+++ b/core/java/android/util/ArrayMap.java
@@ -0,0 +1,615 @@
+/*
+ * Copyright (C) 2013 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 android.util;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * ArrayMap is a generic key->value mapping data structure that is
+ * designed to be more memory efficient than a traditional {@link java.util.HashMap}.
+ * It keeps its mappings in an array data structure -- an integer array of hash
+ * codes for each item, and an Object array of the key/value pairs. This allows it to
+ * avoid having to create an extra object for every entry put in to the map, and it
+ * also tries to control the growth of the size of these arrays more aggressively
+ * (since growing them only requires copying the entries in the array, not rebuilding
+ * a hash map).
+ *
+ * <p>Note that this implementation is not intended to be appropriate for data structures
+ * that may contain large numbers of items. It is generally slower than a traditional
+ * HashMap, since lookups require a binary search and adds and removes require inserting
+ * and deleting entries in the array. For containers holding up to hundreds of items,
+ * the performance difference is not significant, less than 50%. For larger numbers of items
+ * this data structure should be avoided.</p>
+ *
+ * <p><b>Note:</b> unlike {@link java.util.HashMap}, this container does not support
+ * null keys.</p>
+ *
+ * <p>Because this container is intended to better balance memory use, unlike most other
+ * standard Java containers it will shrink its array as items are removed from it. Currently
+ * you have no control over this shrinking -- if you set a capacity and then remove an
+ * item, it may reduce the capacity to better match the current size. In the future an
+ * explicitly call to set the capacity should turn off this aggressive shrinking behavior.</p>
+ *
+ * @hide
+ */
+public final class ArrayMap<K, V> implements Map<K, V> {
+ private static final boolean DEBUG = false;
+ private static final String TAG = "ArrayMap";
+
+ /**
+ * The minimum amount by which the capacity of a ArrayMap will increase.
+ * This is tuned to be relatively space-efficient.
+ */
+ private static final int BASE_SIZE = 4;
+
+ /**
+ * Maximum number of entries to have in array caches.
+ */
+ private static final int CACHE_SIZE = 10;
+
+ /**
+ * Caches of small array objects to avoid spamming garbage. The cache
+ * Object[] variable is a pointer to a linked list of array objects.
+ * The first entry in the array is a pointer to the next array in the
+ * list; the second entry is a pointer to the int[] hash code array for it.
+ */
+ static Object[] mBaseCache;
+ static int mBaseCacheSize;
+ static Object[] mTwiceBaseCache;
+ static int mTwiceBaseCacheSize;
+
+ int[] mHashes;
+ Object[] mArray;
+ int mSize;
+ MapCollections<K, V> mCollections;
+
+ private int indexOf(Object key, int hash) {
+ final int N = mSize;
+
+ // Important fast case: if nothing is in here, nothing to look for.
+ if (N == 0) {
+ return ~0;
+ }
+
+ int index = SparseArray.binarySearch(mHashes, N, hash);
+
+ // If the hash code wasn't found, then we have no entry for this key.
+ if (index < 0) {
+ return index;
+ }
+
+ // If the key at the returned index matches, that's what we want.
+ if (mArray[index<<1].equals(key)) {
+ return index;
+ }
+
+ // Search for a matching key after the index.
+ int end;
+ for (end = index + 1; end < N && mHashes[end] == hash; end++) {
+ if (mArray[end << 1].equals(key)) return end;
+ }
+
+ // Search for a matching key before the index.
+ for (int i = index - 1; i >= 0 && mHashes[i] == hash; i--) {
+ if (mArray[i << 1].equals(key)) return i;
+ }
+
+ // Key not found -- return negative value indicating where a
+ // new entry for this key should go. We use the end of the
+ // hash chain to reduce the number of array entries that will
+ // need to be copied when inserting.
+ return ~end;
+ }
+
+ private void allocArrays(final int size) {
+ if (size == (BASE_SIZE*2)) {
+ synchronized (ArrayMap.class) {
+ if (mTwiceBaseCache != null) {
+ final Object[] array = mTwiceBaseCache;
+ mArray = array;
+ mTwiceBaseCache = (Object[])array[0];
+ mHashes = (int[])array[1];
+ array[0] = array[1] = null;
+ mTwiceBaseCacheSize--;
+ if (DEBUG) Log.d(TAG, "Retrieving 2x cache " + mHashes
+ + " now have " + mTwiceBaseCacheSize + " entries");
+ return;
+ }
+ }
+ } else if (size == BASE_SIZE) {
+ synchronized (ArrayMap.class) {
+ if (mBaseCache != null) {
+ final Object[] array = mBaseCache;
+ mArray = array;
+ mBaseCache = (Object[])array[0];
+ mHashes = (int[])array[1];
+ array[0] = array[1] = null;
+ mBaseCacheSize--;
+ if (DEBUG) Log.d(TAG, "Retrieving 1x cache " + mHashes
+ + " now have " + mBaseCacheSize + " entries");
+ return;
+ }
+ }
+ }
+
+ mHashes = new int[size];
+ mArray = new Object[size<<1];
+ }
+
+ private static void freeArrays(final int[] hashes, final Object[] array, final int size) {
+ if (hashes.length == (BASE_SIZE*2)) {
+ synchronized (ArrayMap.class) {
+ if (mTwiceBaseCacheSize < CACHE_SIZE) {
+ array[0] = mTwiceBaseCache;
+ array[1] = hashes;
+ for (int i=(size<<1)-1; i>=2; i--) {
+ array[i] = null;
+ }
+ mTwiceBaseCache = array;
+ mTwiceBaseCacheSize++;
+ if (DEBUG) Log.d(TAG, "Storing 2x cache " + array
+ + " now have " + mTwiceBaseCacheSize + " entries");
+ }
+ }
+ } else if (hashes.length == BASE_SIZE) {
+ synchronized (ArrayMap.class) {
+ if (mBaseCacheSize < CACHE_SIZE) {
+ array[0] = mBaseCache;
+ array[1] = hashes;
+ for (int i=(size<<1)-1; i>=2; i--) {
+ array[i] = null;
+ }
+ mBaseCache = array;
+ mBaseCacheSize++;
+ if (DEBUG) Log.d(TAG, "Storing 1x cache " + array
+ + " now have " + mBaseCacheSize + " entries");
+ }
+ }
+ }
+ }
+
+ /**
+ * Create a new empty ArrayMap. The default capacity of an array map is 0, and
+ * will grow once items are added to it.
+ */
+ public ArrayMap() {
+ mHashes = SparseArray.EMPTY_INTS;
+ mArray = SparseArray.EMPTY_OBJECTS;
+ mSize = 0;
+ }
+
+ /**
+ * Create a new ArrayMap with a given initial capacity.
+ */
+ public ArrayMap(int capacity) {
+ if (capacity == 0) {
+ mHashes = SparseArray.EMPTY_INTS;
+ mArray = SparseArray.EMPTY_OBJECTS;
+ } else {
+ allocArrays(capacity);
+ }
+ mSize = 0;
+ }
+
+ /**
+ * Make the array map empty. All storage is released.
+ */
+ @Override
+ public void clear() {
+ freeArrays(mHashes, mArray, mSize);
+ mHashes = SparseArray.EMPTY_INTS;
+ mArray = SparseArray.EMPTY_OBJECTS;
+ mSize = 0;
+ }
+
+ /**
+ * Ensure the array map can hold at least <var>minimumCapacity</var>
+ * items.
+ */
+ public void ensureCapacity(int minimumCapacity) {
+ if (mHashes.length < minimumCapacity) {
+ int[] ohashes = mHashes;
+ Object[] oarray = mArray;
+ allocArrays(minimumCapacity);
+ if (mHashes.length > 0) {
+ System.arraycopy(ohashes, 0, mHashes, 0, mHashes.length);
+ System.arraycopy(oarray, 0, mArray, 0, mArray.length);
+ }
+ freeArrays(ohashes, oarray, mSize);
+ }
+ }
+
+ /**
+ * Check whether a key exists in the array.
+ *
+ * @param key The key to search for.
+ * @return Returns true if the key exists, else false.
+ */
+ @Override
+ public boolean containsKey(Object key) {
+ return indexOf(key, key.hashCode()) >= 0;
+ }
+
+ private int indexOfValue(Object value) {
+ final int N = mSize*2;
+ final Object[] array = mArray;
+ if (value == null) {
+ for (int i=1; i<N; i+=2) {
+ if (array[i] == null) {
+ return i>>1;
+ }
+ }
+ } else {
+ for (int i=1; i<N; i+=2) {
+ if (value.equals(array[i])) {
+ return i>>1;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Check whether a value exists in the array. This requires a linear search
+ * through the entire array.
+ *
+ * @param value The value to search for.
+ * @return Returns true if the value exists, else false.
+ */
+ @Override
+ public boolean containsValue(Object value) {
+ return indexOfValue(value) >= 0;
+ }
+
+ /**
+ * Retrieve a value from the array.
+ * @param key The key of the value to retrieve.
+ * @return Returns the value associated with the given key,
+ * or null if there is no such key.
+ */
+ @Override
+ public V get(Object key) {
+ final int index = indexOf(key, key.hashCode());
+ return index >= 0 ? (V)mArray[(index<<1)+1] : null;
+ }
+
+ /**
+ * Return the key at the given index in the array.
+ * @param index The desired index, must be between 0 and {@link #size()}-1.
+ * @return Returns the key stored at the given index.
+ */
+ public K keyAt(int index) {
+ return (K)mArray[index << 1];
+ }
+
+ /**
+ * Return the value at the given index in the array.
+ * @param index The desired index, must be between 0 and {@link #size()}-1.
+ * @return Returns the value stored at the given index.
+ */
+ public V valueAt(int index) {
+ return (V)mArray[(index << 1) + 1];
+ }
+
+ /**
+ * Set the value at a given index in the array.
+ * @param index The desired index, must be between 0 and {@link #size()}-1.
+ * @param value The new value to store at this index.
+ * @return Returns the previous value at the given index.
+ */
+ public V setValueAt(int index, V value) {
+ index = (index << 1) + 1;
+ V old = (V)mArray[index];
+ mArray[index] = value;
+ return old;
+ }
+
+ /**
+ * Return true if the array map contains no items.
+ */
+ @Override
+ public boolean isEmpty() {
+ return mSize <= 0;
+ }
+
+ /**
+ * Add a new value to the array map.
+ * @param key The key under which to store the value. <b>Must not be null.</b> If
+ * this key already exists in the array, its value will be replaced.
+ * @param value The value to store for the given key.
+ * @return Returns the old value that was stored for the given key, or null if there
+ * was no such key.
+ */
+ @Override
+ public V put(K key, V value) {
+ final int hash = key.hashCode();
+ int index = indexOf(key, hash);
+ if (index >= 0) {
+ index = (index<<1) + 1;
+ final V old = (V)mArray[index];
+ mArray[index] = value;
+ return old;
+ }
+
+ index = ~index;
+ if (mSize >= mHashes.length) {
+ final int n = mSize >= (BASE_SIZE*2) ? (mSize+(mSize>>1))
+ : (mSize >= BASE_SIZE ? (BASE_SIZE*2) : BASE_SIZE);
+
+ if (DEBUG) Log.d(TAG, "put: grow from " + mHashes.length + " to " + n);
+
+ final int[] ohashes = mHashes;
+ final Object[] oarray = mArray;
+ allocArrays(n);
+
+ if (mHashes.length > 0) {
+ if (DEBUG) Log.d(TAG, "put: copy 0-" + mSize + " to 0");
+ System.arraycopy(ohashes, 0, mHashes, 0, ohashes.length);
+ System.arraycopy(oarray, 0, mArray, 0, oarray.length);
+ }
+
+ freeArrays(ohashes, oarray, mSize);
+ }
+
+ if (index < mSize) {
+ if (DEBUG) Log.d(TAG, "put: move " + index + "-" + (mSize-index)
+ + " to " + (index+1));
+ System.arraycopy(mHashes, index, mHashes, index + 1, mSize - index);
+ System.arraycopy(mArray, index << 1, mArray, (index + 1) << 1, (mSize - index) << 1);
+ }
+
+ mHashes[index] = hash;
+ mArray[index<<1] = key;
+ mArray[(index<<1)+1] = value;
+ mSize++;
+ return null;
+ }
+
+ /**
+ * Perform a {@link #put(Object, Object)} of all key/value pairs in <var>array</var>
+ * @param array The array whose contents are to be retrieved.
+ */
+ public void putAll(ArrayMap<? extends K, ? extends V> array) {
+ final int N = array.mSize;
+ ensureCapacity(mSize + N);
+ for (int i=0; i<N; i++) {
+ put(array.keyAt(i), array.valueAt(i));
+ }
+ }
+
+ /**
+ * Remove an existing key from the array map.
+ * @param key The key of the mapping to remove.
+ * @return Returns the value that was stored under the key, or null if there
+ * was no such key.
+ */
+ @Override
+ public V remove(Object key) {
+ int index = indexOf(key, key.hashCode());
+ if (index >= 0) {
+ return removeAt(index);
+ }
+
+ return null;
+ }
+
+ /**
+ * Remove the key/value mapping at the given index.
+ * @param index The desired index, must be between 0 and {@link #size()}-1.
+ * @return Returns the value that was stored at this index.
+ */
+ public V removeAt(int index) {
+ final V old = (V)mArray[(index << 1) + 1];
+ if (mSize <= 1) {
+ // Now empty.
+ if (DEBUG) Log.d(TAG, "remove: shrink from " + mHashes.length + " to 0");
+ freeArrays(mHashes, mArray, mSize);
+ mHashes = SparseArray.EMPTY_INTS;
+ mArray = SparseArray.EMPTY_OBJECTS;
+ mSize = 0;
+ } else {
+ if (mHashes.length > (BASE_SIZE*2) && mSize < mHashes.length/3) {
+ // Shrunk enough to reduce size of arrays. We don't allow it to
+ // shrink smaller than (BASE_SIZE*2) to avoid flapping between
+ // that and BASE_SIZE.
+ final int n = mSize > (BASE_SIZE*2) ? (mSize + (mSize>>1)) : (BASE_SIZE*2);
+
+ if (DEBUG) Log.d(TAG, "remove: shrink from " + mHashes.length + " to " + n);
+
+ final int[] ohashes = mHashes;
+ final Object[] oarray = mArray;
+ allocArrays(n);
+
+ mSize--;
+ if (index > 0) {
+ if (DEBUG) Log.d(TAG, "remove: copy from 0-" + index + " to 0");
+ System.arraycopy(ohashes, 0, mHashes, 0, index);
+ System.arraycopy(oarray, 0, mArray, 0, index << 1);
+ }
+ if (index < mSize) {
+ if (DEBUG) Log.d(TAG, "remove: copy from " + (index+1) + "-" + mSize
+ + " to " + index);
+ System.arraycopy(ohashes, index + 1, mHashes, index, mSize - index);
+ System.arraycopy(oarray, (index + 1) << 1, mArray, index << 1,
+ (mSize - index) << 1);
+ }
+ } else {
+ mSize--;
+ if (index < mSize) {
+ if (DEBUG) Log.d(TAG, "remove: move " + (index+1) + "-" + mSize
+ + " to " + index);
+ System.arraycopy(mHashes, index + 1, mHashes, index, mSize - index);
+ System.arraycopy(mArray, (index + 1) << 1, mArray, index << 1,
+ (mSize - index) << 1);
+ }
+ mArray[mSize << 1] = null;
+ mArray[(mSize << 1) + 1] = null;
+ }
+ }
+ return old;
+ }
+
+ /**
+ * Return the number of items in this array map.
+ */
+ @Override
+ public int size() {
+ return mSize;
+ }
+
+ // ------------------------------------------------------------------------
+ // Interop with traditional Java containers. Not as efficient as using
+ // specialized collection APIs.
+ // ------------------------------------------------------------------------
+
+ private MapCollections<K, V> getCollection() {
+ if (mCollections == null) {
+ mCollections = new MapCollections<K, V>() {
+ @Override
+ protected int colGetSize() {
+ return mSize;
+ }
+
+ @Override
+ protected Object colGetEntry(int index, int offset) {
+ return mArray[(index<<1) + offset];
+ }
+
+ @Override
+ protected int colIndexOfKey(Object key) {
+ return indexOf(key, key.hashCode());
+ }
+
+ @Override
+ protected int colIndexOfValue(Object value) {
+ return indexOfValue(value);
+ }
+
+ @Override
+ protected Map<K, V> colGetMap() {
+ return ArrayMap.this;
+ }
+
+ @Override
+ protected void colPut(K key, V value) {
+ put(key, value);
+ }
+
+ @Override
+ protected V colSetValue(int index, V value) {
+ return setValueAt(index, value);
+ }
+
+ @Override
+ protected void colRemoveAt(int index) {
+ removeAt(index);
+ }
+
+ @Override
+ protected void colClear() {
+ clear();
+ }
+ };
+ }
+ return mCollections;
+ }
+
+ /**
+ * Determine if the array map contains all of the keys in the given collection.
+ * @param collection The collection whose contents are to be checked against.
+ * @return Returns true if this array map contains a key for every entry
+ * in <var>collection</var>, else returns false.
+ */
+ public boolean containsAll(Collection<?> collection) {
+ return MapCollections.containsAllHelper(this, collection);
+ }
+
+ /**
+ * Perform a {@link #put(Object, Object)} of all key/value pairs in <var>map</var>
+ * @param map The map whose contents are to be retrieved.
+ */
+ @Override
+ public void putAll(Map<? extends K, ? extends V> map) {
+ ensureCapacity(mSize + map.size());
+ for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
+ put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ /**
+ * Remove all keys in the array map that exist in the given collection.
+ * @param collection The collection whose contents are to be used to remove keys.
+ * @return Returns true if any keys were removed from the array map, else false.
+ */
+ public boolean removeAll(Collection<?> collection) {
+ return MapCollections.removeAllHelper(this, collection);
+ }
+
+ /**
+ * Remove all keys in the array map that do <b>not</b> exist in the given collection.
+ * @param collection The collection whose contents are to be used to determine which
+ * keys to keep.
+ * @return Returns true if any keys were removed from the array map, else false.
+ */
+ public boolean retainAll(Collection<?> collection) {
+ return MapCollections.retainAllHelper(this, collection);
+ }
+
+ /**
+ * Return a {@link java.util.Set} for iterating over and interacting with all mappings
+ * in the array map.
+ *
+ * <p><b>Note:</b> this is a very inefficient way to access the array contents, it
+ * requires generating a number of temporary objects.</p>
+ *
+ * <p><b>Note:</b></p> the semantics of this
+ * Set are subtly different than that of a {@link java.util.HashMap}: most important,
+ * the {@link java.util.Map.Entry Map.Entry} object returned by its iterator is a single
+ * object that exists for the entire iterator, so you can <b>not</b> hold on to it
+ * after calling {@link java.util.Iterator#next() Iterator.next}.</p>
+ */
+ @Override
+ public Set<Map.Entry<K, V>> entrySet() {
+ return getCollection().getEntrySet();
+ }
+
+ /**
+ * Return a {@link java.util.Set} for iterating over and interacting with all keys
+ * in the array map.
+ *
+ * <p><b>Note:</b> this is a fair inefficient way to access the array contents, it
+ * requires generating a number of temporary objects.</p>
+ */
+ @Override
+ public Set<K> keySet() {
+ return getCollection().getKeySet();
+ }
+
+ /**
+ * Return a {@link java.util.Collection} for iterating over and interacting with all values
+ * in the array map.
+ *
+ * <p><b>Note:</b> this is a fair inefficient way to access the array contents, it
+ * requires generating a number of temporary objects.</p>
+ */
+ @Override
+ public Collection<V> values() {
+ return getCollection().getValues();
+ }
+}
diff --git a/core/java/android/util/LongSparseArray.java b/core/java/android/util/LongSparseArray.java
index 630e5f3..660b743 100644
--- a/core/java/android/util/LongSparseArray.java
+++ b/core/java/android/util/LongSparseArray.java
@@ -41,13 +41,19 @@ public class LongSparseArray<E> implements Cloneable {
/**
* Creates a new LongSparseArray containing no mappings that will not
* require any additional memory allocation to store the specified
- * number of mappings.
+ * number of mappings. If you supply an initial capacity of 0, the
+ * sparse array will be initialized with a light-weight representation
+ * not requiring any additional array allocations.
*/
public LongSparseArray(int initialCapacity) {
- initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity);
-
- mKeys = new long[initialCapacity];
- mValues = new Object[initialCapacity];
+ if (initialCapacity == 0) {
+ mKeys = SparseLongArray.EMPTY_LONGS;
+ mValues = SparseArray.EMPTY_OBJECTS;
+ } else {
+ initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity);
+ mKeys = new long[initialCapacity];
+ mValues = new Object[initialCapacity];
+ }
mSize = 0;
}
diff --git a/core/java/android/util/LongSparseLongArray.java b/core/java/android/util/LongSparseLongArray.java
index 34b6126..503295c 100644
--- a/core/java/android/util/LongSparseLongArray.java
+++ b/core/java/android/util/LongSparseLongArray.java
@@ -42,13 +42,19 @@ public class LongSparseLongArray implements Cloneable {
/**
* Creates a new SparseLongArray containing no mappings that will not
* require any additional memory allocation to store the specified
- * number of mappings.
+ * number of mappings. If you supply an initial capacity of 0, the
+ * sparse array will be initialized with a light-weight representation
+ * not requiring any additional array allocations.
*/
public LongSparseLongArray(int initialCapacity) {
- initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity);
-
- mKeys = new long[initialCapacity];
- mValues = new long[initialCapacity];
+ if (initialCapacity == 0) {
+ mKeys = SparseLongArray.EMPTY_LONGS;
+ mValues = SparseLongArray.EMPTY_LONGS;
+ } else {
+ initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity);
+ mKeys = new long[initialCapacity];
+ mValues = new long[initialCapacity];
+ }
mSize = 0;
}
diff --git a/core/java/android/util/MapCollections.java b/core/java/android/util/MapCollections.java
new file mode 100644
index 0000000..f29fb65
--- /dev/null
+++ b/core/java/android/util/MapCollections.java
@@ -0,0 +1,496 @@
+/*
+ * Copyright (C) 2013 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 android.util;
+
+import libcore.util.Objects;
+
+import java.lang.reflect.Array;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Helper for writing standard Java collection interfaces to a data
+ * structure like {@link ArrayMap}.
+ * @hide
+ */
+abstract class MapCollections<K, V> {
+ EntrySet mEntrySet;
+ KeySet mKeySet;
+ ValuesCollection mValues;
+
+ final class ArrayIterator<T> implements Iterator<T> {
+ final int mOffset;
+ int mSize;
+ int mIndex;
+ boolean mCanRemove = false;
+
+ ArrayIterator(int offset) {
+ mOffset = offset;
+ mSize = colGetSize();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return mIndex < mSize;
+ }
+
+ @Override
+ public T next() {
+ Object res = colGetEntry(mIndex, mOffset);
+ mIndex++;
+ mCanRemove = true;
+ return (T)res;
+ }
+
+ @Override
+ public void remove() {
+ if (!mCanRemove) {
+ throw new IllegalStateException();
+ }
+ mIndex--;
+ mSize--;
+ mCanRemove = false;
+ colRemoveAt(mIndex);
+ }
+ }
+
+ final class MapIterator implements Iterator<Map.Entry<K, V>>, Map.Entry<K, V> {
+ int mEnd;
+ int mIndex;
+ boolean mEntryValid = false;
+
+ MapIterator() {
+ mEnd = colGetSize() - 1;
+ mIndex = -1;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return mIndex < mEnd;
+ }
+
+ @Override
+ public Map.Entry<K, V> next() {
+ mIndex++;
+ mEntryValid = true;
+ return this;
+ }
+
+ @Override
+ public void remove() {
+ if (!mEntryValid) {
+ throw new IllegalStateException();
+ }
+ mIndex--;
+ mEnd--;
+ mEntryValid = false;
+ colRemoveAt(mIndex);
+ }
+
+ @Override
+ public K getKey() {
+ if (!mEntryValid) {
+ throw new IllegalStateException(
+ "This container does not support retaining Map.Entry objects");
+ }
+ return (K)colGetEntry(mIndex, 0);
+ }
+
+ @Override
+ public V getValue() {
+ if (!mEntryValid) {
+ throw new IllegalStateException(
+ "This container does not support retaining Map.Entry objects");
+ }
+ return (V)colGetEntry(mIndex, 1);
+ }
+
+ @Override
+ public V setValue(V object) {
+ if (!mEntryValid) {
+ throw new IllegalStateException(
+ "This container does not support retaining Map.Entry objects");
+ }
+ return colSetValue(mIndex, object);
+ }
+
+ @Override
+ public final boolean equals(Object o) {
+ if (!mEntryValid) {
+ throw new IllegalStateException(
+ "This container does not support retaining Map.Entry objects");
+ }
+ if (!(o instanceof Map.Entry)) {
+ return false;
+ }
+ Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
+ return Objects.equal(e.getKey(), colGetEntry(mIndex, 0))
+ && Objects.equal(e.getValue(), colGetEntry(mIndex, 1));
+ }
+
+ @Override
+ public final int hashCode() {
+ if (!mEntryValid) {
+ throw new IllegalStateException(
+ "This container does not support retaining Map.Entry objects");
+ }
+ final Object key = colGetEntry(mIndex, 0);
+ final Object value = colGetEntry(mIndex, 1);
+ return (key == null ? 0 : key.hashCode()) ^
+ (value == null ? 0 : value.hashCode());
+ }
+
+ @Override
+ public final String toString() {
+ return getKey() + "=" + getValue();
+ }
+ }
+
+ final class EntrySet implements Set<Map.Entry<K, V>> {
+ @Override
+ public boolean add(Map.Entry<K, V> object) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends Map.Entry<K, V>> collection) {
+ int oldSize = colGetSize();
+ for (Map.Entry<K, V> entry : collection) {
+ colPut(entry.getKey(), entry.getValue());
+ }
+ return oldSize != colGetSize();
+ }
+
+ @Override
+ public void clear() {
+ colClear();
+ }
+
+ @Override
+ public boolean contains(Object object) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> collection) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return colGetSize() == 0;
+ }
+
+ @Override
+ public Iterator<Map.Entry<K, V>> iterator() {
+ return new MapIterator();
+ }
+
+ @Override
+ public boolean remove(Object object) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> collection) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> collection) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int size() {
+ return colGetSize();
+ }
+
+ @Override
+ public Object[] toArray() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public <T> T[] toArray(T[] array) {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ final class KeySet implements Set<K> {
+
+ @Override
+ public boolean add(K object) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends K> collection) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void clear() {
+ colClear();
+ }
+
+ @Override
+ public boolean contains(Object object) {
+ return colIndexOfKey(object) >= 0;
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> collection) {
+ return removeAllHelper(colGetMap(), collection);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return colGetSize() == 0;
+ }
+
+ @Override
+ public Iterator<K> iterator() {
+ return new ArrayIterator<K>(0);
+ }
+
+ @Override
+ public boolean remove(Object object) {
+ int index = colIndexOfKey(object);
+ if (index >= 0) {
+ colRemoveAt(index);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> collection) {
+ return removeAllHelper(colGetMap(), collection);
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> collection) {
+ return retainAllHelper(colGetMap(), collection);
+ }
+
+ @Override
+ public int size() {
+ return colGetSize();
+ }
+
+ @Override
+ public Object[] toArray() {
+ return toArrayHelper(1);
+ }
+
+ @Override
+ public <T> T[] toArray(T[] array) {
+ return toArrayHelper(array, 1);
+ }
+ };
+
+ final class ValuesCollection implements Collection<V> {
+
+ @Override
+ public boolean add(V object) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends V> collection) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void clear() {
+ colClear();
+ }
+
+ @Override
+ public boolean contains(Object object) {
+ return colIndexOfValue(object) >= 0;
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> collection) {
+ Iterator<?> it = collection.iterator();
+ while (it.hasNext()) {
+ if (!contains(it.next())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return colGetSize() == 0;
+ }
+
+ @Override
+ public Iterator<V> iterator() {
+ return new ArrayIterator<V>(1);
+ }
+
+ @Override
+ public boolean remove(Object object) {
+ int index = colIndexOfValue(object);
+ if (index >= 0) {
+ colRemoveAt(index);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> collection) {
+ int N = colGetSize();
+ boolean changed = false;
+ for (int i=0; i<N; i++) {
+ Object cur = colGetEntry(i, 1);
+ if (collection.contains(cur)) {
+ colRemoveAt(i);
+ i--;
+ N--;
+ changed = true;
+ }
+ }
+ return changed;
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> collection) {
+ int N = colGetSize();
+ boolean changed = false;
+ for (int i=0; i<N; i++) {
+ Object cur = colGetEntry(i, 1);
+ if (!collection.contains(cur)) {
+ colRemoveAt(i);
+ i--;
+ N--;
+ changed = true;
+ }
+ }
+ return changed;
+ }
+
+ @Override
+ public int size() {
+ return colGetSize();
+ }
+
+ @Override
+ public Object[] toArray() {
+ return toArrayHelper(1);
+ }
+
+ @Override
+ public <T> T[] toArray(T[] array) {
+ return toArrayHelper(array, 1);
+ }
+ };
+
+ public static <K, V> boolean containsAllHelper(Map<K, V> map, Collection<?> collection) {
+ Iterator<?> it = collection.iterator();
+ while (it.hasNext()) {
+ if (!map.containsKey(it.next())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static <K, V> boolean removeAllHelper(Map<K, V> map, Collection<?> collection) {
+ int oldSize = map.size();
+ Iterator<?> it = collection.iterator();
+ while (it.hasNext()) {
+ map.remove(it.next());
+ }
+ return oldSize != map.size();
+ }
+
+ public static <K, V> boolean retainAllHelper(Map<K, V> map, Collection<?> collection) {
+ int oldSize = map.size();
+ Iterator<K> it = map.keySet().iterator();
+ while (it.hasNext()) {
+ if (!collection.contains(it.next())) {
+ it.remove();
+ }
+ }
+ return oldSize != map.size();
+ }
+
+
+ public Object[] toArrayHelper(int offset) {
+ final int N = colGetSize();
+ Object[] result = new Object[N];
+ for (int i=0; i<N; i++) {
+ result[i] = colGetEntry(i, offset);
+ }
+ return result;
+ }
+
+ public <T> T[] toArrayHelper(T[] array, int offset) {
+ final int N = colGetSize();
+ if (array.length < N) {
+ @SuppressWarnings("unchecked") T[] newArray
+ = (T[]) Array.newInstance(array.getClass().getComponentType(), N);
+ array = newArray;
+ }
+ for (int i=0; i<N; i++) {
+ array[i] = (T)colGetEntry(i, offset);
+ }
+ if (array.length > N) {
+ array[N] = null;
+ }
+ return array;
+ }
+
+ public Set<Map.Entry<K, V>> getEntrySet() {
+ if (mEntrySet == null) {
+ mEntrySet = new EntrySet();
+ }
+ return mEntrySet;
+ }
+
+ public Set<K> getKeySet() {
+ if (mKeySet == null) {
+ mKeySet = new KeySet();
+ }
+ return mKeySet;
+ }
+
+ public Collection<V> getValues() {
+ if (mValues == null) {
+ mValues = new ValuesCollection();
+ }
+ return mValues;
+ }
+
+ protected abstract int colGetSize();
+ protected abstract Object colGetEntry(int index, int offset);
+ protected abstract int colIndexOfKey(Object key);
+ protected abstract int colIndexOfValue(Object key);
+ protected abstract Map<K, V> colGetMap();
+ protected abstract void colPut(K key, V value);
+ protected abstract V colSetValue(int index, V value);
+ protected abstract void colRemoveAt(int index);
+ protected abstract void colClear();
+}
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index 7e8fee5..001fc5b 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -25,6 +25,8 @@ import com.android.internal.util.ArrayUtils;
*/
public class SparseArray<E> implements Cloneable {
private static final Object DELETED = new Object();
+ static final int[] EMPTY_INTS = new int[0];
+ static final Object[] EMPTY_OBJECTS = new Object[0];
private boolean mGarbage = false;
private int[] mKeys;
@@ -41,13 +43,19 @@ public class SparseArray<E> implements Cloneable {
/**
* Creates a new SparseArray containing no mappings that will not
* require any additional memory allocation to store the specified
- * number of mappings.
+ * number of mappings. If you supply an initial capacity of 0, the
+ * sparse array will be initialized with a light-weight representation
+ * not requiring any additional array allocations.
*/
public SparseArray(int initialCapacity) {
- initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
-
- mKeys = new int[initialCapacity];
- mValues = new Object[initialCapacity];
+ if (initialCapacity == 0) {
+ mKeys = EMPTY_INTS;
+ mValues = EMPTY_OBJECTS;
+ } else {
+ initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
+ mKeys = new int[initialCapacity];
+ mValues = new Object[initialCapacity];
+ }
mSize = 0;
}
@@ -79,7 +87,7 @@ public class SparseArray<E> implements Cloneable {
*/
@SuppressWarnings("unchecked")
public E get(int key, E valueIfKeyNotFound) {
- int i = binarySearch(mKeys, 0, mSize, key);
+ int i = binarySearch(mKeys, mSize, key);
if (i < 0 || mValues[i] == DELETED) {
return valueIfKeyNotFound;
@@ -92,7 +100,7 @@ public class SparseArray<E> implements Cloneable {
* Removes the mapping from the specified key, if there was any.
*/
public void delete(int key) {
- int i = binarySearch(mKeys, 0, mSize, key);
+ int i = binarySearch(mKeys, mSize, key);
if (i >= 0) {
if (mValues[i] != DELETED) {
@@ -153,7 +161,7 @@ public class SparseArray<E> implements Cloneable {
* was one.
*/
public void put(int key, E value) {
- int i = binarySearch(mKeys, 0, mSize, key);
+ int i = binarySearch(mKeys, mSize, key);
if (i >= 0) {
mValues[i] = value;
@@ -170,7 +178,7 @@ public class SparseArray<E> implements Cloneable {
gc();
// Search again because indices may have changed.
- i = ~binarySearch(mKeys, 0, mSize, key);
+ i = ~binarySearch(mKeys, mSize, key);
}
if (mSize >= mKeys.length) {
@@ -261,7 +269,7 @@ public class SparseArray<E> implements Cloneable {
gc();
}
- return binarySearch(mKeys, 0, mSize, key);
+ return binarySearch(mKeys, mSize, key);
}
/**
@@ -335,23 +343,23 @@ public class SparseArray<E> implements Cloneable {
mSize = pos + 1;
}
- private static int binarySearch(int[] a, int start, int len, int key) {
- int high = start + len, low = start - 1, guess;
-
- while (high - low > 1) {
- guess = (high + low) / 2;
-
- if (a[guess] < key)
- low = guess;
- else
- high = guess;
+ // This is Arrays.binarySearch(), but doesn't do any argument validation.
+ static int binarySearch(int[] array, int size, int value) {
+ int lo = 0;
+ int hi = size - 1;
+
+ while (lo <= hi) {
+ int mid = (lo + hi) >>> 1;
+ int midVal = array[mid];
+
+ if (midVal < value) {
+ lo = mid + 1;
+ } else if (midVal > value) {
+ hi = mid - 1;
+ } else {
+ return mid; // value found
+ }
}
-
- if (high == start + len)
- return ~(start + len);
- else if (a[high] == key)
- return high;
- else
- return ~high;
+ return ~lo; // value not present
}
}
diff --git a/core/java/android/util/SparseBooleanArray.java b/core/java/android/util/SparseBooleanArray.java
index 76c47c6..73e3629 100644
--- a/core/java/android/util/SparseBooleanArray.java
+++ b/core/java/android/util/SparseBooleanArray.java
@@ -25,6 +25,8 @@ import com.android.internal.util.ArrayUtils;
* than using a HashMap to map Integers to Booleans.
*/
public class SparseBooleanArray implements Cloneable {
+ static final boolean[] EMPTY_BOOLEANS = new boolean[0];
+
/**
* Creates a new SparseBooleanArray containing no mappings.
*/
@@ -35,13 +37,19 @@ public class SparseBooleanArray implements Cloneable {
/**
* Creates a new SparseBooleanArray containing no mappings that will not
* require any additional memory allocation to store the specified
- * number of mappings.
+ * number of mappings. If you supply an initial capacity of 0, the
+ * sparse array will be initialized with a light-weight representation
+ * not requiring any additional array allocations.
*/
public SparseBooleanArray(int initialCapacity) {
- initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
-
- mKeys = new int[initialCapacity];
- mValues = new boolean[initialCapacity];
+ if (initialCapacity == 0) {
+ mKeys = SparseArray.EMPTY_INTS;
+ mValues = EMPTY_BOOLEANS;
+ } else {
+ initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
+ mKeys = new int[initialCapacity];
+ mValues = new boolean[initialCapacity];
+ }
mSize = 0;
}
@@ -71,7 +79,7 @@ public class SparseBooleanArray implements Cloneable {
* if no such mapping has been made.
*/
public boolean get(int key, boolean valueIfKeyNotFound) {
- int i = binarySearch(mKeys, 0, mSize, key);
+ int i = SparseArray.binarySearch(mKeys, mSize, key);
if (i < 0) {
return valueIfKeyNotFound;
@@ -84,7 +92,7 @@ public class SparseBooleanArray implements Cloneable {
* Removes the mapping from the specified key, if there was any.
*/
public void delete(int key) {
- int i = binarySearch(mKeys, 0, mSize, key);
+ int i = SparseArray.binarySearch(mKeys, mSize, key);
if (i >= 0) {
System.arraycopy(mKeys, i + 1, mKeys, i, mSize - (i + 1));
@@ -99,7 +107,7 @@ public class SparseBooleanArray implements Cloneable {
* was one.
*/
public void put(int key, boolean value) {
- int i = binarySearch(mKeys, 0, mSize, key);
+ int i = SparseArray.binarySearch(mKeys, mSize, key);
if (i >= 0) {
mValues[i] = value;
@@ -164,7 +172,7 @@ public class SparseBooleanArray implements Cloneable {
* key is not mapped.
*/
public int indexOfKey(int key) {
- return binarySearch(mKeys, 0, mSize, key);
+ return SparseArray.binarySearch(mKeys, mSize, key);
}
/**
@@ -220,26 +228,6 @@ public class SparseBooleanArray implements Cloneable {
mSize = pos + 1;
}
- private static int binarySearch(int[] a, int start, int len, int key) {
- int high = start + len, low = start - 1, guess;
-
- while (high - low > 1) {
- guess = (high + low) / 2;
-
- if (a[guess] < key)
- low = guess;
- else
- high = guess;
- }
-
- if (high == start + len)
- return ~(start + len);
- else if (a[high] == key)
- return high;
- else
- return ~high;
- }
-
private int[] mKeys;
private boolean[] mValues;
private int mSize;
diff --git a/core/java/android/util/SparseIntArray.java b/core/java/android/util/SparseIntArray.java
index 8d11177..122f7f5 100644
--- a/core/java/android/util/SparseIntArray.java
+++ b/core/java/android/util/SparseIntArray.java
@@ -24,7 +24,6 @@ import com.android.internal.util.ArrayUtils;
* than using a HashMap to map Integers to Integers.
*/
public class SparseIntArray implements Cloneable {
-
private int[] mKeys;
private int[] mValues;
private int mSize;
@@ -39,13 +38,19 @@ public class SparseIntArray implements Cloneable {
/**
* Creates a new SparseIntArray containing no mappings that will not
* require any additional memory allocation to store the specified
- * number of mappings.
+ * number of mappings. If you supply an initial capacity of 0, the
+ * sparse array will be initialized with a light-weight representation
+ * not requiring any additional array allocations.
*/
public SparseIntArray(int initialCapacity) {
- initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
-
- mKeys = new int[initialCapacity];
- mValues = new int[initialCapacity];
+ if (initialCapacity == 0) {
+ mKeys = SparseArray.EMPTY_INTS;
+ mValues = SparseArray.EMPTY_INTS;
+ } else {
+ initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
+ mKeys = new int[initialCapacity];
+ mValues = new int[initialCapacity];
+ }
mSize = 0;
}
@@ -75,7 +80,7 @@ public class SparseIntArray implements Cloneable {
* if no such mapping has been made.
*/
public int get(int key, int valueIfKeyNotFound) {
- int i = binarySearch(mKeys, 0, mSize, key);
+ int i = SparseArray.binarySearch(mKeys, mSize, key);
if (i < 0) {
return valueIfKeyNotFound;
@@ -88,7 +93,7 @@ public class SparseIntArray implements Cloneable {
* Removes the mapping from the specified key, if there was any.
*/
public void delete(int key) {
- int i = binarySearch(mKeys, 0, mSize, key);
+ int i = SparseArray.binarySearch(mKeys, mSize, key);
if (i >= 0) {
removeAt(i);
@@ -110,7 +115,7 @@ public class SparseIntArray implements Cloneable {
* was one.
*/
public void put(int key, int value) {
- int i = binarySearch(mKeys, 0, mSize, key);
+ int i = SparseArray.binarySearch(mKeys, mSize, key);
if (i >= 0) {
mValues[i] = value;
@@ -175,7 +180,7 @@ public class SparseIntArray implements Cloneable {
* key is not mapped.
*/
public int indexOfKey(int key) {
- return binarySearch(mKeys, 0, mSize, key);
+ return SparseArray.binarySearch(mKeys, mSize, key);
}
/**
@@ -230,24 +235,4 @@ public class SparseIntArray implements Cloneable {
mValues[pos] = value;
mSize = pos + 1;
}
-
- private static int binarySearch(int[] a, int start, int len, int key) {
- int high = start + len, low = start - 1, guess;
-
- while (high - low > 1) {
- guess = (high + low) / 2;
-
- if (a[guess] < key)
- low = guess;
- else
- high = guess;
- }
-
- if (high == start + len)
- return ~(start + len);
- else if (a[high] == key)
- return high;
- else
- return ~high;
- }
}
diff --git a/core/java/android/util/SparseLongArray.java b/core/java/android/util/SparseLongArray.java
index 2f7a6fe..c608996 100644
--- a/core/java/android/util/SparseLongArray.java
+++ b/core/java/android/util/SparseLongArray.java
@@ -24,6 +24,7 @@ import com.android.internal.util.ArrayUtils;
* than using a HashMap to map Integers to Longs.
*/
public class SparseLongArray implements Cloneable {
+ static final long[] EMPTY_LONGS = new long[0];
private int[] mKeys;
private long[] mValues;
@@ -39,13 +40,19 @@ public class SparseLongArray implements Cloneable {
/**
* Creates a new SparseLongArray containing no mappings that will not
* require any additional memory allocation to store the specified
- * number of mappings.
+ * number of mappings. If you supply an initial capacity of 0, the
+ * sparse array will be initialized with a light-weight representation
+ * not requiring any additional array allocations.
*/
public SparseLongArray(int initialCapacity) {
- initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity);
-
- mKeys = new int[initialCapacity];
- mValues = new long[initialCapacity];
+ if (initialCapacity == 0) {
+ mKeys = SparseArray.EMPTY_INTS;
+ mValues = EMPTY_LONGS;
+ } else {
+ initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity);
+ mKeys = new int[initialCapacity];
+ mValues = new long[initialCapacity];
+ }
mSize = 0;
}
@@ -75,7 +82,7 @@ public class SparseLongArray implements Cloneable {
* if no such mapping has been made.
*/
public long get(int key, long valueIfKeyNotFound) {
- int i = binarySearch(mKeys, 0, mSize, key);
+ int i = SparseArray.binarySearch(mKeys, mSize, key);
if (i < 0) {
return valueIfKeyNotFound;
@@ -88,7 +95,7 @@ public class SparseLongArray implements Cloneable {
* Removes the mapping from the specified key, if there was any.
*/
public void delete(int key) {
- int i = binarySearch(mKeys, 0, mSize, key);
+ int i = SparseArray.binarySearch(mKeys, mSize, key);
if (i >= 0) {
removeAt(i);
@@ -110,7 +117,7 @@ public class SparseLongArray implements Cloneable {
* was one.
*/
public void put(int key, long value) {
- int i = binarySearch(mKeys, 0, mSize, key);
+ int i = SparseArray.binarySearch(mKeys, mSize, key);
if (i >= 0) {
mValues[i] = value;
@@ -164,7 +171,7 @@ public class SparseLongArray implements Cloneable {
* key is not mapped.
*/
public int indexOfKey(int key) {
- return binarySearch(mKeys, 0, mSize, key);
+ return SparseArray.binarySearch(mKeys, mSize, key);
}
/**
@@ -222,24 +229,4 @@ public class SparseLongArray implements Cloneable {
mKeys = nkeys;
mValues = nvalues;
}
-
- private static int binarySearch(int[] a, int start, int len, long key) {
- int high = start + len, low = start - 1, guess;
-
- while (high - low > 1) {
- guess = (high + low) / 2;
-
- if (a[guess] < key)
- low = guess;
- else
- high = guess;
- }
-
- if (high == start + len)
- return ~(start + len);
- else if (a[high] == key)
- return high;
- else
- return ~high;
- }
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index babccf6..d1fa455 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -15688,7 +15688,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
private void setKeyedTag(int key, Object tag) {
if (mKeyedTags == null) {
- mKeyedTags = new SparseArray<Object>();
+ mKeyedTags = new SparseArray<Object>(2);
}
mKeyedTags.put(key, tag);
@@ -15966,7 +15966,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
+ * <p>This method must be called by {@link #onMeasure(int, int)} to store the
* measured width and measured height. Failing to do so will trigger an
* exception at measurement time.</p>
*
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 077cb6f..b0fbe84 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1517,9 +1517,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (lastHoverTarget != null) {
lastHoverTarget.next = hoverTarget;
} else {
- lastHoverTarget = hoverTarget;
mFirstHoverTarget = hoverTarget;
}
+ lastHoverTarget = hoverTarget;
// Dispatch the event to the child.
if (action == MotionEvent.ACTION_HOVER_ENTER) {
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 5de7399..4c0ccca 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1151,10 +1151,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
if (mChoiceMode != CHOICE_MODE_NONE) {
if (mCheckStates == null) {
- mCheckStates = new SparseBooleanArray();
+ mCheckStates = new SparseBooleanArray(0);
}
if (mCheckedIdStates == null && mAdapter != null && mAdapter.hasStableIds()) {
- mCheckedIdStates = new LongSparseArray<Integer>();
+ mCheckedIdStates = new LongSparseArray<Integer>(0);
}
// Modal multi-choice mode only has choices when the mode is active. Clear them.
if (mChoiceMode == CHOICE_MODE_MULTIPLE_MODAL) {
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index 361eca4..a19c6a8 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -247,7 +247,7 @@ public class CalendarView extends FrameLayout {
/**
* Which month should be displayed/highlighted [0-11].
*/
- private int mCurrentMonthDisplayed;
+ private int mCurrentMonthDisplayed = -1;
/**
* Used for tracking during a scroll.
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 1d85126..aaa1adaa 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -29,6 +29,7 @@ import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -74,6 +75,9 @@ public class Toast {
*/
public static final int LENGTH_LONG = 1;
+ /** @hide */
+ public static final int LENGTH_INFINITE = 2;
+
final Context mContext;
final TN mTN;
int mDuration;
@@ -288,6 +292,61 @@ public class Toast {
tv.setText(s);
}
+ /** @hide */
+ public static Toast makeBar(Context context, int resId, int duration) {
+ return makeBar(context, context.getResources().getText(resId), duration);
+ }
+
+ /** @hide */
+ public static Toast makeBar(Context context, CharSequence text, int duration) {
+ Toast result = new Toast(context);
+
+ LayoutInflater inflate = (LayoutInflater)
+ context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ View v = inflate.inflate(com.android.internal.R.layout.toast_bar, null);
+ ((TextView)v.findViewById(android.R.id.message)).setText(text);
+ v.findViewById(android.R.id.button1).setVisibility(View.GONE);
+
+ result.mNextView = v;
+ result.mDuration = duration;
+ result.mTN.mParams.alpha = 0.9f;
+ result.mTN.mParams.windowAnimations = com.android.internal.R.style.Animation_ToastBar;
+
+ return result;
+ }
+
+ /** @hide */
+ public Toast setAction(int resId, Runnable action) {
+ return setAction(mContext.getResources().getText(resId), action);
+ }
+
+ /** @hide */
+ public Toast setAction(CharSequence actionText, final Runnable action) {
+ if (mNextView != null) {
+ TextView text1 = (TextView)mNextView.findViewById(android.R.id.text1);
+ View button1 = mNextView.findViewById(android.R.id.button1);
+ if (text1 != null && button1 != null) {
+ text1.setText(actionText);
+ button1.setVisibility(View.VISIBLE);
+ button1.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (action != null) {
+ action.run();
+ }
+ }});
+ return setInteractive(true);
+ }
+ }
+ throw new RuntimeException("This Toast was not created with Toast.makeBar()");
+ }
+
+ /** @hide */
+ public Toast setInteractive(boolean interactive) {
+ mTN.setInteractive(interactive);
+ return this;
+ }
+
// =======================================================================================
// All the gunk below is the interaction with the Notification Service, which handles
// the proper ordering of these system-wide.
@@ -340,13 +399,20 @@ public class Toast {
final WindowManager.LayoutParams params = mParams;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
- params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
- | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
params.format = PixelFormat.TRANSLUCENT;
params.windowAnimations = com.android.internal.R.style.Animation_Toast;
params.type = WindowManager.LayoutParams.TYPE_TOAST;
params.setTitle("Toast");
+ setInteractive(false);
+ }
+
+ private void setInteractive(boolean interactive) {
+ mParams.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | (interactive
+ ? (WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH)
+ : WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
}
/**