Merge "Add a unique input device descriptor."
diff --git a/Android.mk b/Android.mk
index d27dbab..9c51fc6 100644
--- a/Android.mk
+++ b/Android.mk
@@ -118,6 +118,7 @@
core/java/android/net/INetworkPolicyListener.aidl \
core/java/android/net/INetworkPolicyManager.aidl \
core/java/android/net/INetworkStatsService.aidl \
+ core/java/android/net/INetworkStatsSession.aidl \
core/java/android/net/nsd/INsdManager.aidl \
core/java/android/nfc/INdefPushCallback.aidl \
core/java/android/nfc/INfcAdapter.aidl \
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 000abc5..a3fdf3e 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -867,6 +867,16 @@
return true;
}
+ case GET_UID_FOR_INTENT_SENDER_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IIntentSender r = IIntentSender.Stub.asInterface(
+ data.readStrongBinder());
+ int res = getUidForIntentSender(r);
+ reply.writeNoException();
+ reply.writeInt(res);
+ return true;
+ }
+
case SET_PROCESS_LIMIT_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
int max = data.readInt();
@@ -2714,6 +2724,18 @@
reply.recycle();
return res;
}
+ public int getUidForIntentSender(IIntentSender sender) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(sender.asBinder());
+ mRemote.transact(GET_UID_FOR_INTENT_SENDER_TRANSACTION, data, reply, 0);
+ reply.readException();
+ int res = reply.readInt();
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
public void setProcessLimit(int max) throws RemoteException
{
Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 0f287c1..c71b186 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -175,6 +175,7 @@
public boolean clearApplicationUserData(final String packageName,
final IPackageDataObserver observer, int userId) throws RemoteException;
public String getPackageForIntentSender(IIntentSender sender) throws RemoteException;
+ public int getUidForIntentSender(IIntentSender sender) throws RemoteException;
public void setProcessLimit(int max) throws RemoteException;
public int getProcessLimit() throws RemoteException;
@@ -531,6 +532,7 @@
int START_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+89;
int BACKUP_AGENT_CREATED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+90;
int UNBIND_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+91;
+ int GET_UID_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+92;
int START_ACTIVITY_IN_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 2a9f1af..736dd24 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2034,6 +2034,38 @@
"android.intent.action.HDMI_AUDIO_PLUG";
/**
+ * Broadcast Action: A USB audio device was plugged in or unplugged.
+ *
+ * <p>The intent will have the following extra values:
+ * <ul>
+ * <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
+ * <li><em>card</em> - ALSA card number (integer) </li>
+ * <li><em>device</em> - ALSA device number (integer) </li>
+ * </ul>
+ * </ul>
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_USB_AUDIO_DEVICE_PLUG =
+ "android.intent.action.USB_AUDIO_DEVICE_PLUG";
+
+ /**
+ * Broadcast Action: A USB audio accessory was plugged in or unplugged.
+ *
+ * <p>The intent will have the following extra values:
+ * <ul>
+ * <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
+ * <li><em>card</em> - ALSA card number (integer) </li>
+ * <li><em>device</em> - ALSA device number (integer) </li>
+ * </ul>
+ * </ul>
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_USB_AUDIO_ACCESSORY_PLUG =
+ "android.intent.action.USB_AUDIO_ACCESSORY_PLUG";
+
+ /**
* <p>Broadcast Action: The user has switched on advanced settings in the settings app:</p>
* <ul>
* <li><em>state</em> - A boolean value indicating whether the settings is on or off.</li>
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 15ccda3..7571993 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -94,10 +94,12 @@
public static class SplitPermissionInfo {
public final String rootPerm;
public final String[] newPerms;
+ public final int targetSdk;
- public SplitPermissionInfo(String rootPerm, String[] newPerms) {
+ public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
this.rootPerm = rootPerm;
this.newPerms = newPerms;
+ this.targetSdk = targetSdk;
}
}
@@ -126,7 +128,14 @@
public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
new PackageParser.SplitPermissionInfo[] {
new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
- new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE })
+ new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
+ android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
+ new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
+ new String[] { android.Manifest.permission.READ_CALL_LOG },
+ android.os.Build.VERSION_CODES.JELLY_BEAN),
+ new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
+ new String[] { android.Manifest.permission.WRITE_CALL_LOG },
+ android.os.Build.VERSION_CODES.JELLY_BEAN)
};
private String mArchiveSourcePath;
@@ -1293,8 +1302,9 @@
for (int is=0; is<NS; is++) {
final PackageParser.SplitPermissionInfo spi
= PackageParser.SPLIT_PERMISSIONS[is];
- if (!pkg.requestedPermissions.contains(spi.rootPerm)) {
- break;
+ if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
+ || !pkg.requestedPermissions.contains(spi.rootPerm)) {
+ continue;
}
for (int in=0; in<spi.newPerms.length; in++) {
final String perm = spi.newPerms[in];
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 93f93c7..c40504a7 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -66,6 +66,8 @@
* PTP function is enabled
* <li> {@link #USB_FUNCTION_PTP} boolean extra indicating whether the
* accessory function is enabled
+ * <li> {@link #USB_FUNCTION_AUDIO_SOURCE} boolean extra indicating whether the
+ * audio source function is enabled
* </ul>
*
* {@hide}
@@ -178,6 +180,14 @@
public static final String USB_FUNCTION_PTP = "ptp";
/**
+ * Name of the audio source USB function.
+ * Used in extras for the {@link #ACTION_USB_STATE} broadcast
+ *
+ * {@hide}
+ */
+ public static final String USB_FUNCTION_AUDIO_SOURCE = "audio_source";
+
+ /**
* Name of the Accessory USB function.
* Used in extras for the {@link #ACTION_USB_STATE} broadcast
*
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index 0e883cf..b4f6367 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -16,6 +16,7 @@
package android.net;
+import android.net.INetworkStatsSession;
import android.net.NetworkStats;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
@@ -23,15 +24,11 @@
/** {@hide} */
interface INetworkStatsService {
- /** Return historical network layer stats for traffic that matches template. */
- NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields);
- /** Return historical network layer stats for specific UID traffic that matches template. */
- NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int set, int tag, int fields);
+ /** Start a statistics query session. */
+ INetworkStatsSession openSession();
- /** Return network layer usage summary for traffic that matches template. */
- NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end);
- /** Return network layer usage summary per UID for traffic that matches template. */
- NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags);
+ /** Return network layer usage total for traffic that matches template. */
+ long getNetworkTotalBytes(in NetworkTemplate template, long start, long end);
/** Return data layer snapshot of UID network usage. */
NetworkStats getDataLayerSnapshotForUid(int uid);
diff --git a/core/java/android/net/INetworkStatsSession.aidl b/core/java/android/net/INetworkStatsSession.aidl
new file mode 100644
index 0000000..1596fa2
--- /dev/null
+++ b/core/java/android/net/INetworkStatsSession.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 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.net;
+
+import android.net.NetworkStats;
+import android.net.NetworkStatsHistory;
+import android.net.NetworkTemplate;
+
+/** {@hide} */
+interface INetworkStatsSession {
+
+ /** Return network layer usage summary for traffic that matches template. */
+ NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end);
+ /** Return historical network layer stats for traffic that matches template. */
+ NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields);
+
+ /** Return network layer usage summary per UID for traffic that matches template. */
+ NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags);
+ /** Return historical network layer stats for specific UID traffic that matches template. */
+ NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int set, int tag, int fields);
+
+ void close();
+
+}
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 973fac1..ee3e165 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -238,6 +238,19 @@
}
}
+ /** {@hide} */
+ public static void closeQuietly(INetworkStatsSession session) {
+ // TODO: move to NetworkStatsService once it exists
+ if (session != null) {
+ try {
+ session.close();
+ } catch (RuntimeException rethrown) {
+ throw rethrown;
+ } catch (Exception ignored) {
+ }
+ }
+ }
+
/**
* Get the total number of packets transmitted through the mobile interface.
*
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 371e2a1..2aaf548 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -37,6 +37,7 @@
import android.os.BatteryManager;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
@@ -2260,6 +2261,7 @@
private static ILockSettings sLockSettings = null;
+ private static boolean sIsSystemProcess;
private static final HashSet<String> MOVED_TO_LOCK_SETTINGS;
static {
MOVED_TO_LOCK_SETTINGS = new HashSet<String>(3);
@@ -2283,8 +2285,10 @@
if (sLockSettings == null) {
sLockSettings = ILockSettings.Stub.asInterface(
(IBinder) ServiceManager.getService("lock_settings"));
+ sIsSystemProcess = Process.myUid() == Process.SYSTEM_UID;
}
- if (sLockSettings != null && MOVED_TO_LOCK_SETTINGS.contains(name)) {
+ if (sLockSettings != null && !sIsSystemProcess
+ && MOVED_TO_LOCK_SETTINGS.contains(name)) {
try {
return sLockSettings.getString(name, "0", UserId.getCallingUserId());
} catch (RemoteException re) {
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index bb4b282..f7a7eb8 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -50,8 +50,6 @@
public SpannableStringBuilder(CharSequence text, int start, int end) {
int srclen = end - start;
- if (srclen < 0) throw new StringIndexOutOfBoundsException();
-
int len = ArrayUtils.idealCharArraySize(srclen + 1);
mText = new char[len];
mGapStart = srclen;
@@ -155,7 +153,7 @@
if (where == mGapStart)
return;
- boolean atEnd = (where == length());
+ boolean atend = (where == length());
if (where < mGapStart) {
int overlap = mGapStart - where;
@@ -181,7 +179,7 @@
else if (start == where) {
int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT;
- if (flag == POINT || (atEnd && flag == PARAGRAPH))
+ if (flag == POINT || (atend && flag == PARAGRAPH))
start += mGapLength;
}
@@ -192,7 +190,7 @@
else if (end == where) {
int flag = (mSpanFlags[i] & END_MASK);
- if (flag == POINT || (atEnd && flag == PARAGRAPH))
+ if (flag == POINT || (atend && flag == PARAGRAPH))
end += mGapLength;
}
@@ -399,7 +397,7 @@
// Documentation from interface
public SpannableStringBuilder replace(final int start, final int end,
- CharSequence tb, int tbstart, int tbend) {
+ CharSequence tb, int tbstart, int tbend) {
int filtercount = mFilters.length;
for (int i = 0; i < filtercount; i++) {
CharSequence repl = mFilters[i].filter(tb, tbstart, tbend, this, start, end);
@@ -421,26 +419,53 @@
TextWatcher[] textWatchers = getSpans(start, start + origLen, TextWatcher.class);
sendBeforeTextChanged(textWatchers, start, origLen, newLen);
- // Try to keep the cursor / selection at the same relative position during
- // a text replacement. If replaced or replacement text length is zero, this
- // is already taken care of.
- boolean adjustSelection = origLen != 0 && newLen != 0;
- int selstart = 0;
- int selend = 0;
- if (adjustSelection) {
- selstart = Selection.getSelectionStart(this);
- selend = Selection.getSelectionEnd(this);
- }
+ if (origLen == 0 || newLen == 0) {
+ change(start, end, tb, tbstart, tbend);
+ } else {
+ int selstart = Selection.getSelectionStart(this);
+ int selend = Selection.getSelectionEnd(this);
- checkRange("replace", start, end);
+ // XXX just make the span fixups in change() do the right thing
+ // instead of this madness!
- change(start, end, tb, tbstart, tbend);
+ checkRange("replace", start, end);
+ moveGapTo(end);
- if (adjustSelection) {
+ if (mGapLength < 2)
+ resizeFor(length() + 1);
+
+ for (int i = mSpanCount - 1; i >= 0; i--) {
+ if (mSpanStarts[i] == mGapStart)
+ mSpanStarts[i]++;
+
+ if (mSpanEnds[i] == mGapStart)
+ mSpanEnds[i]++;
+ }
+
+ mText[mGapStart] = ' ';
+ mGapStart++;
+ mGapLength--;
+
+ if (mGapLength < 1) {
+ new Exception("mGapLength < 1").printStackTrace();
+ }
+
+ change(start + 1, start + 1, tb, tbstart, tbend);
+ change(start, start + 1, "", 0, 0);
+ change(start + newLen, start + newLen + origLen, "", 0, 0);
+
+ /*
+ * Special case to keep the cursor in the same position
+ * if it was somewhere in the middle of the replaced region.
+ * If it was at the start or the end or crossing the whole
+ * replacement, it should already be where it belongs.
+ * TODO: Is there some more general mechanism that could
+ * accomplish this?
+ */
if (selstart > start && selstart < end) {
long off = selstart - start;
- off = off * newLen / origLen;
+ off = off * newLen / (end - start);
selstart = (int) off + start;
setSpan(false, Selection.SELECTION_START, selstart, selstart,
@@ -449,7 +474,7 @@
if (selend > start && selend < end) {
long off = selend - start;
- off = off * newLen / origLen;
+ off = off * newLen / (end - start);
selend = (int) off + start;
setSpan(false, Selection.SELECTION_END, selend, selend, Spanned.SPAN_POINT_POINT);
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index d1af397..b0399fd 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -526,7 +526,7 @@
static final int SURFACE_STATE_SUCCESS = 1;
static final int SURFACE_STATE_UPDATED = 2;
- static final int FUNCTOR_PROCESS_DELAY = 2;
+ static final int FUNCTOR_PROCESS_DELAY = 4;
static EGL10 sEgl;
static EGLDisplay sEglDisplay;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 39d2e39..2a908ab 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -260,7 +260,7 @@
Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom);
dirty.unionWith(localDirty);
- if (result == DrawGlInfo::kStatusInvoke) {
+ if (result & DrawGlInfo::kStatusInvoke) {
mFunctors.push(f);
}
}
@@ -300,7 +300,7 @@
Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom);
dirty.unionWith(localDirty);
- if (result == DrawGlInfo::kStatusInvoke) {
+ if (result & DrawGlInfo::kStatusInvoke) {
mFunctors.push(functor);
}
}
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 66cea9d4..410383d 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -45,10 +45,16 @@
public int mFlags;
};
+ // The follow flag constants MUST stay in sync with their equivalents
+ // in MediaCodec.h !
public static int FLAG_SYNCFRAME = 1;
public static int FLAG_CODECCONFIG = 2;
public static int FLAG_EOS = 4;
- public static int FLAG_ENCRYPTED = 8;
+
+ // The following mode constants MUST stay in sync with their equivalents
+ // in media/hardware/CryptoAPI.h !
+ public static int MODE_UNENCRYPTED = 0;
+ public static int MODE_AES_CTR = 1;
/** Instantiate a codec component by mime type. For decoder components
this is the mime type of media that this decoder should be able to
@@ -176,6 +182,36 @@
int index,
int offset, int size, long presentationTimeUs, int flags);
+ /** Similar to {@link queueInputBuffer} but submits a buffer that is
+ * potentially encrypted. The buffer's data is considered to be
+ * partitioned into "subSamples", each subSample starts with a
+ * (potentially empty) run of plain, unencrypted bytes followed
+ * by a (also potentially empty) run of encrypted bytes.
+ * @param numBytesOfClearData The number of leading unencrypted bytes in
+ * each subSample.
+ * @param numBytesOfEncryptedData The number of trailing encrypted bytes
+ * in each subSample.
+ * @param numSubSamples The number of subSamples that make up the
+ * buffer's contents.
+ * @param key A 16-byte opaque key
+ * @param iv A 16-byte initialization vector
+ * @param mode The type of encryption that has been applied
+ *
+ * Either numBytesOfClearData or numBytesOfEncryptedData (but not both)
+ * can be null to indicate that all respective sizes are 0.
+ */
+ public native final void queueSecureInputBuffer(
+ int index,
+ int offset,
+ int[] numBytesOfClearData,
+ int[] numBytesOfEncryptedData,
+ int numSubSamples,
+ byte[] key,
+ byte[] iv,
+ int mode,
+ long presentationTimeUs,
+ int flags);
+
// Returns the index of an input buffer to be filled with valid data
// or -1 if no such buffer is currently available.
// This method will return immediately if timeoutUs == 0, wait indefinitely
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 217216a..01d3833 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -126,6 +126,21 @@
return mCodec->queueInputBuffer(index, offset, size, timeUs, flags);
}
+status_t JMediaCodec::queueSecureInputBuffer(
+ size_t index,
+ size_t offset,
+ const CryptoPlugin::SubSample *subSamples,
+ size_t numSubSamples,
+ const uint8_t key[16],
+ const uint8_t iv[16],
+ CryptoPlugin::Mode mode,
+ int64_t presentationTimeUs,
+ uint32_t flags) {
+ return mCodec->queueSecureInputBuffer(
+ index, offset, subSamples, numSubSamples, key, iv, mode,
+ presentationTimeUs, flags);
+}
+
status_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
return mCodec->dequeueInputBuffer(index, timeoutUs);
}
@@ -367,6 +382,125 @@
throwExceptionAsNecessary(env, err);
}
+static void android_media_MediaCodec_queueSecureInputBuffer(
+ JNIEnv *env,
+ jobject thiz,
+ jint index,
+ jint offset,
+ jintArray numBytesOfClearDataObj,
+ jintArray numBytesOfEncryptedDataObj,
+ jint numSubSamples,
+ jbyteArray keyObj,
+ jbyteArray ivObj,
+ jint mode,
+ jlong timestampUs,
+ jint flags) {
+ ALOGV("android_media_MediaCodec_queueSecureInputBuffer");
+
+ sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+
+ if (codec == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return;
+ }
+
+ status_t err = OK;
+
+ CryptoPlugin::SubSample *subSamples = NULL;
+ jbyte *key = NULL;
+ jbyte *iv = NULL;
+
+ if (numSubSamples <= 0) {
+ err = -EINVAL;
+ } else if (numBytesOfClearDataObj == NULL
+ && numBytesOfEncryptedDataObj == NULL) {
+ err = -EINVAL;
+ } else if (numBytesOfEncryptedDataObj != NULL
+ && env->GetArrayLength(numBytesOfEncryptedDataObj) < numSubSamples) {
+ err = -ERANGE;
+ } else if (numBytesOfClearDataObj != NULL
+ && env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) {
+ err = -ERANGE;
+ } else {
+ jboolean isCopy;
+
+ jint *numBytesOfClearData =
+ (numBytesOfClearDataObj == NULL)
+ ? NULL
+ : env->GetIntArrayElements(numBytesOfClearDataObj, &isCopy);
+
+ jint *numBytesOfEncryptedData =
+ (numBytesOfEncryptedDataObj == NULL)
+ ? NULL
+ : env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
+
+ subSamples = new CryptoPlugin::SubSample[numSubSamples];
+
+ for (jint i = 0; i < numSubSamples; ++i) {
+ subSamples[i].mNumBytesOfClearData =
+ (numBytesOfClearData == NULL) ? 0 : numBytesOfClearData[i];
+
+ subSamples[i].mNumBytesOfEncryptedData =
+ (numBytesOfEncryptedData == NULL)
+ ? 0 : numBytesOfEncryptedData[i];
+ }
+
+ if (numBytesOfEncryptedData != NULL) {
+ env->ReleaseIntArrayElements(
+ numBytesOfEncryptedDataObj, numBytesOfEncryptedData, 0);
+ numBytesOfEncryptedData = NULL;
+ }
+
+ if (numBytesOfClearData != NULL) {
+ env->ReleaseIntArrayElements(
+ numBytesOfClearDataObj, numBytesOfClearData, 0);
+ numBytesOfClearData = NULL;
+ }
+ }
+
+ if (err == OK && keyObj != NULL) {
+ if (env->GetArrayLength(keyObj) != 16) {
+ err = -EINVAL;
+ } else {
+ jboolean isCopy;
+ key = env->GetByteArrayElements(keyObj, &isCopy);
+ }
+ }
+
+ if (err == OK && ivObj != NULL) {
+ if (env->GetArrayLength(ivObj) != 16) {
+ err = -EINVAL;
+ } else {
+ jboolean isCopy;
+ iv = env->GetByteArrayElements(ivObj, &isCopy);
+ }
+ }
+
+ if (err == OK) {
+ err = codec->queueSecureInputBuffer(
+ index, offset,
+ subSamples, numSubSamples,
+ (const uint8_t *)key, (const uint8_t *)iv,
+ (CryptoPlugin::Mode)mode,
+ timestampUs, flags);
+ }
+
+ if (iv != NULL) {
+ env->ReleaseByteArrayElements(ivObj, iv, 0);
+ iv = NULL;
+ }
+
+ if (key != NULL) {
+ env->ReleaseByteArrayElements(keyObj, key, 0);
+ key = NULL;
+ }
+
+ delete[] subSamples;
+ subSamples = NULL;
+
+ throwExceptionAsNecessary(env, err);
+}
+
static jint android_media_MediaCodec_dequeueInputBuffer(
JNIEnv *env, jobject thiz, jlong timeoutUs) {
ALOGV("android_media_MediaCodec_dequeueInputBuffer");
@@ -532,6 +666,9 @@
{ "queueInputBuffer", "(IIIJI)V",
(void *)android_media_MediaCodec_queueInputBuffer },
+ { "queueSecureInputBuffer", "(II[I[II[B[BIJI)V",
+ (void *)android_media_MediaCodec_queueSecureInputBuffer },
+
{ "dequeueInputBuffer", "(J)I",
(void *)android_media_MediaCodec_dequeueInputBuffer },
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index 6bb4071..570c33b 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -19,6 +19,7 @@
#include "jni.h"
+#include <media/hardware/CryptoAPI.h>
#include <media/stagefright/foundation/ABase.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -53,6 +54,17 @@
size_t index,
size_t offset, size_t size, int64_t timeUs, uint32_t flags);
+ status_t queueSecureInputBuffer(
+ size_t index,
+ size_t offset,
+ const CryptoPlugin::SubSample *subSamples,
+ size_t numSubSamples,
+ const uint8_t key[16],
+ const uint8_t iv[16],
+ CryptoPlugin::Mode mode,
+ int64_t presentationTimeUs,
+ uint32_t flags);
+
status_t dequeueInputBuffer(size_t *index, int64_t timeoutUs);
status_t dequeueOutputBuffer(
diff --git a/obex/MODULE_LICENSE_BSD_LIKE b/obex/MODULE_LICENSE_BSD_LIKE
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/obex/MODULE_LICENSE_BSD_LIKE
diff --git a/obex/NOTICE b/obex/NOTICE
new file mode 100644
index 0000000..92e8e59
--- /dev/null
+++ b/obex/NOTICE
@@ -0,0 +1,29 @@
+Copyright (c) 2008-2009, Motorola, Inc.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+- Neither the name of the Motorola, Inc. nor the names of its contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index 0574405..32ac8e1 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -34,9 +34,9 @@
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.WorkSource;
import android.text.TextUtils;
import android.text.format.Time;
-import android.util.EventLog;
import android.util.Slog;
import android.util.TimeUtils;
@@ -50,6 +50,7 @@
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.Map;
import java.util.TimeZone;
@@ -89,6 +90,7 @@
private int mDescriptor;
private int mBroadcastRefCount = 0;
private PowerManager.WakeLock mWakeLock;
+ private LinkedList<PendingIntent> mInFlight = new LinkedList<PendingIntent>();
private final AlarmThread mWaitThread = new AlarmThread();
private final AlarmHandler mHandler = new AlarmHandler();
private ClockReceiver mClockReceiver;
@@ -668,10 +670,12 @@
Intent.EXTRA_ALARM_COUNT, alarm.count),
mResultReceiver, mHandler);
- // we have an active broadcast so stay awake.
+ // we have an active broadcast so stay awake.
if (mBroadcastRefCount == 0) {
+ setWakelockWorkSource(alarm.operation);
mWakeLock.acquire();
}
+ mInFlight.add(alarm.operation);
mBroadcastRefCount++;
BroadcastStats bs = getStatsLocked(alarm.operation);
@@ -700,7 +704,22 @@
}
}
}
-
+
+ void setWakelockWorkSource(PendingIntent pi) {
+ try {
+ final int uid = ActivityManagerNative.getDefault()
+ .getUidForIntentSender(pi.getTarget());
+ if (uid >= 0) {
+ mWakeLock.setWorkSource(new WorkSource(uid));
+ return;
+ }
+ } catch (Exception e) {
+ }
+
+ // Something went wrong; fall back to attributing the lock to the OS
+ mWakeLock.setWorkSource(null);
+ }
+
private class AlarmHandler extends Handler {
public static final int ALARM_EVENT = 1;
public static final int MINUTE_CHANGE_EVENT = 2;
@@ -876,9 +895,20 @@
fs.count++;
}
}
+ mInFlight.removeFirst();
mBroadcastRefCount--;
if (mBroadcastRefCount == 0) {
mWakeLock.release();
+ } else {
+ // the next of our alarms is now in flight. reattribute the wakelock.
+ final PendingIntent nowInFlight = mInFlight.peekFirst();
+ if (nowInFlight != null) {
+ setWakelockWorkSource(nowInFlight);
+ } else {
+ // should never happen
+ Slog.e(TAG, "Alarm wakelock still held but sent queue empty");
+ mWakeLock.setWorkSource(null);
+ }
}
}
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 2da827e..80e59cd 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -4444,6 +4444,17 @@
return null;
}
+ public int getUidForIntentSender(IIntentSender sender) {
+ if (sender instanceof PendingIntentRecord) {
+ try {
+ PendingIntentRecord res = (PendingIntentRecord)sender;
+ return res.uid;
+ } catch (ClassCastException e) {
+ }
+ }
+ return -1;
+ }
+
public boolean isIntentSenderTargetedToPackage(IIntentSender pendingResult) {
if (!(pendingResult instanceof PendingIntentRecord)) {
return false;
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index b0657a6..77addd6 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -1740,7 +1740,7 @@
private long getTotalBytes(NetworkTemplate template, long start, long end) {
try {
- return mNetworkStats.getSummaryForNetwork(template, start, end).getTotalBytes();
+ return mNetworkStats.getNetworkTotalBytes(template, start, end);
} catch (RuntimeException e) {
Slog.w(TAG, "problem reading network stats: " + e);
return 0;
diff --git a/services/java/com/android/server/net/NetworkStatsRecorder.java b/services/java/com/android/server/net/NetworkStatsRecorder.java
index 290bd2c..540f606 100644
--- a/services/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/java/com/android/server/net/NetworkStatsRecorder.java
@@ -221,6 +221,11 @@
if (mLastSnapshot != null) {
mLastSnapshot = mLastSnapshot.withoutUid(uid);
}
+
+ final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null;
+ if (complete != null) {
+ complete.removeUid(uid);
+ }
}
/**
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index b847673..f7ba329 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -70,6 +70,7 @@
import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver;
import android.net.INetworkStatsService;
+import android.net.INetworkStatsSession;
import android.net.LinkProperties;
import android.net.NetworkIdentity;
import android.net.NetworkInfo;
@@ -412,40 +413,75 @@
}
@Override
- public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
- return mDevStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields);
+ public INetworkStatsSession openSession() {
+ mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
+
+ // return an IBinder which holds strong references to any loaded stats
+ // for its lifetime; when caller closes only weak references remain.
+
+ return new INetworkStatsSession.Stub() {
+ private NetworkStatsCollection mUidComplete;
+ private NetworkStatsCollection mUidTagComplete;
+
+ private NetworkStatsCollection getUidComplete() {
+ if (mUidComplete == null) {
+ mUidComplete = mUidRecorder.getOrLoadCompleteLocked();
+ }
+ return mUidComplete;
+ }
+
+ private NetworkStatsCollection getUidTagComplete() {
+ if (mUidTagComplete == null) {
+ mUidTagComplete = mUidTagRecorder.getOrLoadCompleteLocked();
+ }
+ return mUidTagComplete;
+ }
+
+ @Override
+ public NetworkStats getSummaryForNetwork(
+ NetworkTemplate template, long start, long end) {
+ return mDevStatsCached.getSummary(template, start, end);
+ }
+
+ @Override
+ public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
+ return mDevStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields);
+ }
+
+ @Override
+ public NetworkStats getSummaryForAllUid(
+ NetworkTemplate template, long start, long end, boolean includeTags) {
+ final NetworkStats stats = getUidComplete().getSummary(template, start, end);
+ if (includeTags) {
+ final NetworkStats tagStats = getUidTagComplete()
+ .getSummary(template, start, end);
+ stats.combineAllValues(tagStats);
+ }
+ return stats;
+ }
+
+ @Override
+ public NetworkStatsHistory getHistoryForUid(
+ NetworkTemplate template, int uid, int set, int tag, int fields) {
+ if (tag == TAG_NONE) {
+ return getUidComplete().getHistory(template, uid, set, tag, fields);
+ } else {
+ return getUidTagComplete().getHistory(template, uid, set, tag, fields);
+ }
+ }
+
+ @Override
+ public void close() {
+ mUidComplete = null;
+ mUidTagComplete = null;
+ }
+ };
}
@Override
- public NetworkStats getSummaryForNetwork(NetworkTemplate template, long start, long end) {
- return mDevStatsCached.getSummary(template, start, end);
- }
-
- @Override
- public NetworkStatsHistory getHistoryForUid(
- NetworkTemplate template, int uid, int set, int tag, int fields) {
- // TODO: transition to stats sessions to avoid WeakReferences
- if (tag == TAG_NONE) {
- return mUidRecorder.getOrLoadCompleteLocked().getHistory(
- template, uid, set, tag, fields);
- } else {
- return mUidTagRecorder.getOrLoadCompleteLocked().getHistory(
- template, uid, set, tag, fields);
- }
- }
-
- @Override
- public NetworkStats getSummaryForAllUid(
- NetworkTemplate template, long start, long end, boolean includeTags) {
- // TODO: transition to stats sessions to avoid WeakReferences
- final NetworkStats stats = mUidRecorder.getOrLoadCompleteLocked().getSummary(
- template, start, end);
- if (includeTags) {
- final NetworkStats tagStats = mUidTagRecorder.getOrLoadCompleteLocked().getSummary(
- template, start, end);
- stats.combineAllValues(tagStats);
- }
- return stats;
+ public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
+ mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
+ return mDevStatsCached.getSummary(template, start, end).getTotalBytes();
}
@Override
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index 4bea5e4..1bd15f6 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -60,6 +60,7 @@
import java.util.List;
import java.util.HashMap;
import java.util.Map;
+import java.util.Scanner;
/**
* UsbDeviceManager manages USB state in device mode.
@@ -81,6 +82,8 @@
"/sys/class/android_usb/android0/f_mass_storage/lun/file";
private static final String RNDIS_ETH_ADDR_PATH =
"/sys/class/android_usb/android0/f_rndis/ethaddr";
+ private static final String AUDIO_SOURCE_PCM_PATH =
+ "/sys/class/android_usb/android0/f_audio_source/pcm";
private static final int MSG_UPDATE_STATE = 0;
private static final int MSG_ENABLE_ADB = 1;
@@ -105,6 +108,7 @@
private final boolean mHasUsbAccessory;
private boolean mUseUsbNotification;
private boolean mAdbEnabled;
+ private boolean mAudioSourceEnabled;
private Map<String, List<Pair<String, String>>> mOemModeMap;
private class AdbSettingsObserver extends ContentObserver {
@@ -291,6 +295,8 @@
String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
updateState(state);
mAdbEnabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB);
+ mAudioSourceEnabled = containsFunction(mCurrentFunctions,
+ UsbManager.USB_FUNCTION_AUDIO_SOURCE);
// Upgrade step for previous versions that used persist.service.adb.enable
String value = SystemProperties.get("persist.service.adb.enable", "");
@@ -504,6 +510,28 @@
mContext.sendStickyBroadcast(intent);
}
+ private void updateAudioSourceFunction(boolean enabled) {
+ // send a sticky broadcast containing current USB state
+ Intent intent = new Intent(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.putExtra("state", (enabled ? 1 : 0));
+ if (enabled) {
+ try {
+ Scanner scanner = new Scanner(new File(AUDIO_SOURCE_PCM_PATH));
+ int card = scanner.nextInt();
+ int device = scanner.nextInt();
+ intent.putExtra("card", card);
+ intent.putExtra("device", device);
+ } catch (FileNotFoundException e) {
+ Slog.e(TAG, "could not open audio source PCM file", e);
+ }
+ }
+
+ mContext.sendStickyBroadcast(intent);
+ mAudioSourceEnabled = enabled;
+ }
+
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
@@ -523,6 +551,11 @@
}
if (mBootCompleted) {
updateUsbState();
+ boolean audioSourceEnabled = containsFunction(mCurrentFunctions,
+ UsbManager.USB_FUNCTION_AUDIO_SOURCE);
+ if (audioSourceEnabled != mAudioSourceEnabled) {
+ updateAudioSourceFunction(audioSourceEnabled);
+ }
}
break;
case MSG_ENABLE_ADB:
@@ -543,6 +576,7 @@
if (mCurrentAccessory != null) {
mSettingsManager.accessoryAttached(mCurrentAccessory);
}
+ updateAudioSourceFunction(mAudioSourceEnabled);
break;
}
}
diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java
index 6ba4c35..003dc17 100644
--- a/services/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/java/com/android/server/wm/AppWindowAnimator.java
@@ -259,6 +259,19 @@
return false;
}
+ boolean showAllWindowsLocked() {
+ boolean isAnimating = false;
+ final int NW = mAppToken.allAppWindows.size();
+ for (int i=0; i<NW; i++) {
+ WindowStateAnimator winAnimator = mAppToken.allAppWindows.get(i).mWinAnimator;
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
+ "performing show on: " + winAnimator);
+ winAnimator.performShowLocked();
+ isAnimating |= winAnimator.isAnimating();
+ }
+ return isAnimating;
+ }
+
void dump(PrintWriter pw, String prefix) {
if (freezingScreen) {
pw.print(prefix); pw.print(" freezingScreen="); pw.println(freezingScreen);
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 1f8348d..bf35154 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -124,19 +124,6 @@
}
}
- boolean showAllWindowsLocked() {
- boolean isAnimating = false;
- final int NW = allAppWindows.size();
- for (int i=0; i<NW; i++) {
- WindowStateAnimator winAnimator = allAppWindows.get(i).mWinAnimator;
- if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
- "performing show on: " + winAnimator);
- winAnimator.performShowLocked();
- isAnimating |= winAnimator.isAnimating();
- }
- return isAnimating;
- }
-
void updateReportedVisibilityLocked() {
if (appToken == null) {
return;
diff --git a/services/java/com/android/server/wm/DimAnimator.java b/services/java/com/android/server/wm/DimAnimator.java
index 405dd04..b08c864 100644
--- a/services/java/com/android/server/wm/DimAnimator.java
+++ b/services/java/com/android/server/wm/DimAnimator.java
@@ -41,14 +41,14 @@
DimAnimator (SurfaceSession session) {
if (mDimSurface == null) {
- if (WindowManagerService.SHOW_TRANSACTIONS ||
- WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
- " DIM " + mDimSurface + ": CREATE");
try {
mDimSurface = new Surface(session, 0,
"DimAnimator",
-1, 16, 16, PixelFormat.OPAQUE,
Surface.FX_SURFACE_DIM);
+ if (WindowManagerService.SHOW_TRANSACTIONS ||
+ WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
+ " DIM " + mDimSurface + ": CREATE");
mDimSurface.setAlpha(0.0f);
} catch (Exception e) {
Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
diff --git a/services/java/com/android/server/wm/DimSurface.java b/services/java/com/android/server/wm/DimSurface.java
index dc6cc0d..c1dbb36 100644
--- a/services/java/com/android/server/wm/DimSurface.java
+++ b/services/java/com/android/server/wm/DimSurface.java
@@ -32,14 +32,14 @@
DimSurface(SurfaceSession session) {
if (mDimSurface == null) {
- if (WindowManagerService.SHOW_TRANSACTIONS ||
- WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
- " DIM " + mDimSurface + ": CREATE");
try {
mDimSurface = new Surface(session, 0,
"DimSurface",
-1, 16, 16, PixelFormat.OPAQUE,
Surface.FX_SURFACE_DIM);
+ if (WindowManagerService.SHOW_TRANSACTIONS ||
+ WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
+ " DIM " + mDimSurface + ": CREATE");
mDimSurface.setAlpha(0.0f);
} catch (Exception e) {
Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index 67e057e..0d64b68 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -22,6 +22,7 @@
import com.android.internal.policy.impl.PhoneWindowManager;
import java.io.PrintWriter;
+import java.util.HashSet;
/**
* Singleton class that carries out the animations and Surface operations in a separate task
@@ -34,6 +35,9 @@
final Context mContext;
final WindowManagerPolicy mPolicy;
+ HashSet<WindowStateAnimator> mWinAnimators = new HashSet<WindowStateAnimator>();
+ HashSet<WindowStateAnimator> mFinished = new HashSet<WindowStateAnimator>();
+
boolean mAnimating;
boolean mTokenMayBeDrawn;
boolean mForceHiding;
@@ -171,16 +175,16 @@
++mTransactionSequence;
for (int i = mService.mWindows.size() - 1; i >= 0; i--) {
- WindowState w = mService.mWindows.get(i);
- WindowStateAnimator winAnimator = w.mWinAnimator;
- final WindowManager.LayoutParams attrs = w.mAttrs;
+ WindowState win = mService.mWindows.get(i);
+ WindowStateAnimator winAnimator = win.mWinAnimator;
+ final int flags = winAnimator.mAttrFlags;
if (winAnimator.mSurface != null) {
final boolean wasAnimating = winAnimator.mWasAnimating;
final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
if (WindowManagerService.DEBUG_WALLPAPER) {
- Slog.v(TAG, w + ": wasAnimating=" + wasAnimating +
+ Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
", nowAnimating=" + nowAnimating);
}
@@ -189,16 +193,16 @@
// a detached wallpaper animation.
if (nowAnimating) {
if (winAnimator.mAnimation != null) {
- if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0
+ if ((flags & FLAG_SHOW_WALLPAPER) != 0
&& winAnimator.mAnimation.getDetachWallpaper()) {
- mDetachedWallpaper = w;
+ mDetachedWallpaper = win;
}
final int backgroundColor = winAnimator.mAnimation.getBackgroundColor();
if (backgroundColor != 0) {
if (mWindowAnimationBackground == null
|| (winAnimator.mAnimLayer <
mWindowAnimationBackground.mWinAnimator.mAnimLayer)) {
- mWindowAnimationBackground = w;
+ mWindowAnimationBackground = win;
mWindowAnimationBackgroundColor = backgroundColor;
}
}
@@ -210,25 +214,25 @@
// animation, make a note so we can ensure the wallpaper is
// displayed behind it.
final AppWindowAnimator appAnimator =
- w.mAppToken == null ? null : w.mAppToken.mAppAnimator;
+ win.mAppToken == null ? null : win.mAppToken.mAppAnimator;
if (appAnimator != null && appAnimator.animation != null
&& appAnimator.animating) {
- if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0
+ if ((flags & FLAG_SHOW_WALLPAPER) != 0
&& appAnimator.animation.getDetachWallpaper()) {
- mDetachedWallpaper = w;
+ mDetachedWallpaper = win;
}
final int backgroundColor = appAnimator.animation.getBackgroundColor();
if (backgroundColor != 0) {
if (mWindowAnimationBackground == null
|| (winAnimator.mAnimLayer <
mWindowAnimationBackground.mWinAnimator.mAnimLayer)) {
- mWindowAnimationBackground = w;
+ mWindowAnimationBackground = win;
mWindowAnimationBackgroundColor = backgroundColor;
}
}
}
- if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == w) {
+ if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == win) {
mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
@@ -237,11 +241,11 @@
}
}
- if (mPolicy.doesForceHide(w, attrs)) {
+ if (mPolicy.doesForceHide(win, win.mAttrs)) {
if (!wasAnimating && nowAnimating) {
if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
"Animation started that could impact force hide: "
- + w);
+ + win);
mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
@@ -249,22 +253,22 @@
mPendingLayoutChanges);
}
mService.mFocusMayChange = true;
- } else if (w.isReadyForDisplay() && winAnimator.mAnimation == null) {
+ } else if (win.isReadyForDisplay() && winAnimator.mAnimation == null) {
mForceHiding = true;
}
- } else if (mPolicy.canBeForceHidden(w, attrs)) {
+ } else if (mPolicy.canBeForceHidden(win, win.mAttrs)) {
final boolean changed;
if (mForceHiding) {
- changed = w.hideLw(false, false);
+ changed = win.hideLw(false, false);
if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
- "Now policy hidden: " + w);
+ "Now policy hidden: " + win);
} else {
- changed = w.showLw(false, false);
+ changed = win.showLw(false, false);
if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
- "Now policy shown: " + w);
+ "Now policy shown: " + win);
if (changed) {
if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
- && w.isVisibleNow() /*w.isReadyForDisplay()*/) {
+ && win.isVisibleNow() /*w.isReadyForDisplay()*/) {
// Assume we will need to animate. If
// we don't (because the wallpaper will
// stay with the lock screen), then we will
@@ -274,7 +278,7 @@
winAnimator.setAnimation(a);
}
}
- if (mCurrentFocus == null || mCurrentFocus.mLayer < w.mLayer) {
+ if (mCurrentFocus == null || mCurrentFocus.mLayer < win.mLayer) {
// We are showing on to of the current
// focus, so re-evaluate focus to make
// sure it is correct.
@@ -282,8 +286,7 @@
}
}
}
- if (changed && (attrs.flags
- & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
+ if (changed && (flags & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
@@ -294,44 +297,43 @@
}
}
- final AppWindowToken atoken = w.mAppToken;
+ final AppWindowToken atoken = win.mAppToken;
if (atoken != null && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
if (atoken.lastTransactionSequence != mTransactionSequence) {
atoken.lastTransactionSequence = mTransactionSequence;
atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
atoken.startingDisplayed = false;
}
- if ((w.isOnScreen() || w.mAttrs.type
+ if ((win.isOnScreen() || winAnimator.mAttrType
== WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
- && !w.mExiting && !w.mDestroying) {
+ && !win.mExiting && !win.mDestroying) {
if (WindowManagerService.DEBUG_VISIBILITY ||
WindowManagerService.DEBUG_ORIENTATION) {
- Slog.v(TAG, "Eval win " + w + ": isDrawn="
- + w.isDrawnLw()
+ Slog.v(TAG, "Eval win " + win + ": isDrawn=" + win.isDrawnLw()
+ ", isAnimating=" + winAnimator.isAnimating());
- if (!w.isDrawnLw()) {
+ if (!win.isDrawnLw()) {
Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurface
- + " pv=" + w.mPolicyVisibility
+ + " pv=" + win.mPolicyVisibility
+ " mDrawState=" + winAnimator.mDrawState
- + " ah=" + w.mAttachedHidden
+ + " ah=" + win.mAttachedHidden
+ " th=" + atoken.hiddenRequested
+ " a=" + winAnimator.mAnimating);
}
}
- if (w != atoken.startingWindow) {
- if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
+ if (win != atoken.startingWindow) {
+ if (!atoken.mAppAnimator.freezingScreen || !win.mAppFreezing) {
atoken.numInterestingWindows++;
- if (w.isDrawnLw()) {
+ if (win.isDrawnLw()) {
atoken.numDrawnWindows++;
if (WindowManagerService.DEBUG_VISIBILITY ||
WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG,
"tokenMayBeDrawn: " + atoken
+ " freezingScreen=" + atoken.mAppAnimator.freezingScreen
- + " mAppFreezing=" + w.mAppFreezing);
+ + " mAppFreezing=" + win.mAppFreezing);
mTokenMayBeDrawn = true;
}
}
- } else if (w.isDrawnLw()) {
+ } else if (win.isDrawnLw()) {
atoken.startingDisplayed = true;
}
}
@@ -371,7 +373,7 @@
"allDrawn: " + wtoken
+ " interesting=" + numInteresting
+ " drawn=" + wtoken.numDrawnWindows);
- wtoken.showAllWindowsLocked();
+ wtoken.mAppAnimator.showAllWindowsLocked();
mService.unsetAppFreezingScreenLocked(wtoken, false, true);
if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG,
"Setting mOrientationChangeComplete=true because wtoken "
@@ -394,7 +396,7 @@
// We can now show all of the drawn windows!
if (!mService.mOpeningApps.contains(wtoken)) {
- mAnimating |= wtoken.showAllWindowsLocked();
+ mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked();
}
}
}
@@ -435,9 +437,16 @@
mScreenRotationAnimation.updateSurfaces();
}
- for (int i = mService.mWindows.size() - 1; i >= 0; i--) {
- WindowState w = mService.mWindows.get(i);
- w.mWinAnimator.prepareSurfaceLocked(true);
+ mFinished.clear();
+ for (final WindowStateAnimator winAnimator : mWinAnimators) {
+ if (winAnimator.mSurface == null) {
+ mFinished.add(winAnimator);
+ } else {
+ winAnimator.prepareSurfaceLocked(true);
+ }
+ }
+ for (final WindowStateAnimator winAnimator : mFinished) {
+ mWinAnimators.remove(winAnimator);
}
if (mDimParams != null) {
@@ -509,4 +518,18 @@
pw.println( " no DimAnimator ");
}
}
+
+ static class SetAnimationParams {
+ final WindowStateAnimator mWinAnimator;
+ final Animation mAnimation;
+ final int mAnimDw;
+ final int mAnimDh;
+ public SetAnimationParams(final WindowStateAnimator winAnimator,
+ final Animation animation, final int animDw, final int animDh) {
+ mWinAnimator = winAnimator;
+ mAnimation = animation;
+ mAnimDw = animDw;
+ mAnimDh = animDh;
+ }
+ }
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 716b7b1..6f7852d 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -351,32 +351,7 @@
* controlling the ordering of windows in different applications. This
* contains AppWindowToken objects.
*/
- final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>() {
- @Override
- public void add(int index, AppWindowToken object) {
- synchronized (mAnimator) {
- super.add(index, object);
- }
- };
- @Override
- public boolean add(AppWindowToken object) {
- synchronized (mAnimator) {
- return super.add(object);
- }
- };
- @Override
- public AppWindowToken remove(int index) {
- synchronized (mAnimator) {
- return super.remove(index);
- }
- };
- @Override
- public boolean remove(Object object) {
- synchronized (mAnimator) {
- return super.remove(object);
- }
- };
- };
+ final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>();
/**
* Application tokens that are in the process of exiting, but still
@@ -393,32 +368,7 @@
/**
* Z-ordered (bottom-most first) list of all Window objects.
*/
- final ArrayList<WindowState> mWindows = new ArrayList<WindowState>() {
- @Override
- public void add(int index, WindowState object) {
- synchronized (mAnimator) {
- super.add(index, object);
- }
- };
- @Override
- public boolean add(WindowState object) {
- synchronized (mAnimator) {
- return super.add(object);
- }
- };
- @Override
- public WindowState remove(int index) {
- synchronized (mAnimator) {
- return super.remove(index);
- }
- };
- @Override
- public boolean remove(Object object) {
- synchronized (mAnimator) {
- return super.remove(object);
- }
- };
- };
+ final ArrayList<WindowState> mWindows = new ArrayList<WindowState>();
/**
* Fake windows added to the window manager. Note: ordered from top to
@@ -6504,6 +6454,7 @@
public static final int SET_TRANSPARENT_REGION = ANIMATOR_WHAT_OFFSET + 1;
public static final int SET_WALLPAPER_OFFSET = ANIMATOR_WHAT_OFFSET + 2;
public static final int SET_DIM_PARAMETERS = ANIMATOR_WHAT_OFFSET + 3;
+ public static final int SET_MOVE_ANIMATION = ANIMATOR_WHAT_OFFSET + 4;
private Session mLastReportedHold;
@@ -6942,33 +6893,37 @@
// Animation messages. Move to Window{State}Animator
case SET_TRANSPARENT_REGION: {
- // TODO(cmautner): Remove sync.
- synchronized (mAnimator) {
- Pair<WindowStateAnimator, Region> pair =
+ Pair<WindowStateAnimator, Region> pair =
(Pair<WindowStateAnimator, Region>) msg.obj;
- final WindowStateAnimator winAnimator = pair.first;
- winAnimator.setTransparentRegionHint(pair.second);
- }
+ final WindowStateAnimator winAnimator = pair.first;
+ winAnimator.setTransparentRegionHint(pair.second);
scheduleAnimationLocked();
break;
}
case SET_WALLPAPER_OFFSET: {
- // TODO(cmautner): Remove sync.
- synchronized (mAnimator) {
- final WindowStateAnimator winAnimator = (WindowStateAnimator) msg.obj;
- winAnimator.setWallpaperOffset(msg.arg1, msg.arg2);
- }
+ final WindowStateAnimator winAnimator = (WindowStateAnimator) msg.obj;
+ winAnimator.setWallpaperOffset(msg.arg1, msg.arg2);
scheduleAnimationLocked();
break;
}
case SET_DIM_PARAMETERS: {
- synchronized (mAnimator) {
- mAnimator.mDimParams = (DimAnimator.Parameters) msg.obj;
- }
+ mAnimator.mDimParams = (DimAnimator.Parameters) msg.obj;
+
+ scheduleAnimationLocked();
+ break;
+ }
+
+ case SET_MOVE_ANIMATION: {
+ WindowAnimator.SetAnimationParams params =
+ (WindowAnimator.SetAnimationParams) msg.obj;
+ WindowStateAnimator winAnimator = params.mWinAnimator;
+ winAnimator.setAnimation(params.mAnimation);
+ winAnimator.mAnimDw = params.mAnimDw;
+ winAnimator.mAnimDh = params.mAnimDh;
scheduleAnimationLocked();
break;
@@ -7752,20 +7707,19 @@
AppWindowToken topOpeningApp = null;
int topOpeningLayer = 0;
+ // TODO(cmautner): Move to animation side.
NN = mOpeningApps.size();
for (i=0; i<NN; i++) {
AppWindowToken wtoken = mOpeningApps.get(i);
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
- "Now opening app" + wtoken);
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
wtoken.mAppAnimator.clearThumbnail();
wtoken.reportedVisible = false;
wtoken.inPendingTransaction = false;
wtoken.mAppAnimator.animation = null;
- setTokenVisibilityLocked(wtoken, animLp, true,
- transit, false);
+ setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
wtoken.updateReportedVisibilityLocked();
wtoken.waitingToShow = false;
- mAnimator.mAnimating |= wtoken.showAllWindowsLocked();
+ mAnimator.mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked();
if (animLp != null) {
int layer = -1;
for (int j=0; j<wtoken.windows.size(); j++) {
@@ -8624,6 +8578,7 @@
wsa.mSurfaceShown = false;
wsa.mSurface = null;
ws.mHasSurface = false;
+ mAnimator.mWinAnimators.remove(wsa);
mForceRemoves.add(ws);
i--;
N--;
@@ -8637,6 +8592,7 @@
wsa.mSurfaceShown = false;
wsa.mSurface = null;
ws.mHasSurface = false;
+ mAnimator.mWinAnimators.remove(wsa);
leakedSurface = true;
}
}
@@ -8676,6 +8632,7 @@
winAnimator.mSurfaceShown = false;
winAnimator.mSurface = null;
winAnimator.mWin.mHasSurface = false;
+ mAnimator.mWinAnimators.remove(winAnimator);
}
try {
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 6d0921e..220f5e0 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -121,6 +121,9 @@
/** Was this window last hidden? */
boolean mLastHidden;
+ int mAttrFlags;
+ int mAttrType;
+
public WindowStateAnimator(final WindowManagerService service, final WindowState win,
final WindowState attachedWindow) {
mService = service;
@@ -130,11 +133,12 @@
mSession = win.mSession;
mPolicy = mService.mPolicy;
mContext = mService.mContext;
+ mAttrFlags = win.mAttrs.flags;
+ mAttrType = win.mAttrs.type;
}
public void setAnimation(Animation anim) {
- if (localLOGV) Slog.v(
- TAG, "Setting animation in " + this + ": " + anim);
+ if (localLOGV) Slog.v(TAG, "Setting animation in " + this + ": " + anim);
mAnimating = false;
mLocalAnimating = false;
mAnimation = anim;
@@ -453,6 +457,7 @@
attrs.getTitle().toString(),
0, w, h, format, flags);
mWin.mHasSurface = true;
+ mAnimator.mWinAnimators.add(this);
if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG,
" CREATE SURFACE "
+ mSurface + " IN SESSION "
@@ -463,12 +468,14 @@
+ " / " + this);
} catch (Surface.OutOfResourcesException e) {
mWin.mHasSurface = false;
+ mAnimator.mWinAnimators.remove(this);
Slog.w(TAG, "OutOfResourcesException creating surface");
mService.reclaimSomeSurfaceMemoryLocked(this, "create", true);
mDrawState = NO_SURFACE;
return null;
} catch (Exception e) {
mWin.mHasSurface = false;
+ mAnimator.mWinAnimators.remove(this);
Slog.e(TAG, "Exception creating surface", e);
mDrawState = NO_SURFACE;
return null;
@@ -586,6 +593,7 @@
mSurfaceShown = false;
mSurface = null;
mWin.mHasSurface =false;
+ mAnimator.mWinAnimators.remove(this);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 1773e33..2033db6 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -70,7 +70,6 @@
import android.os.INetworkManagementService;
import android.os.IPowerManager;
import android.os.MessageQueue.IdleHandler;
-import android.os.SystemClock;
import android.os.UserId;
import android.test.AndroidTestCase;
import android.test.mock.MockPackageManager;
@@ -628,8 +627,8 @@
// pretend that 512 bytes total have happened
stats = new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 256L, 2L, 256L, 2L);
- expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
- .andReturn(stats).atLeastOnce();
+ expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
+ .andReturn(stats.getTotalBytes()).atLeastOnce();
expectPolicyDataEnable(TYPE_WIFI, true);
// TODO: consider making strongly ordered mock
@@ -699,8 +698,8 @@
{
expectCurrentTime();
expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
- expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats).atLeastOnce();
+ expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+ .andReturn(stats.getTotalBytes()).atLeastOnce();
expectPolicyDataEnable(TYPE_WIFI, true);
expectClearNotifications();
@@ -722,8 +721,8 @@
{
expectCurrentTime();
expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
- expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats).atLeastOnce();
+ expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+ .andReturn(stats.getTotalBytes()).atLeastOnce();
expectPolicyDataEnable(TYPE_WIFI, true);
expectRemoveInterfaceQuota(TEST_IFACE);
@@ -745,8 +744,8 @@
{
expectCurrentTime();
- expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats).atLeastOnce();
+ expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+ .andReturn(stats.getTotalBytes()).atLeastOnce();
expectPolicyDataEnable(TYPE_WIFI, true);
expectForceUpdate();
@@ -766,8 +765,8 @@
{
expectCurrentTime();
- expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats).atLeastOnce();
+ expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+ .andReturn(stats.getTotalBytes()).atLeastOnce();
expectPolicyDataEnable(TYPE_WIFI, false);
expectForceUpdate();
@@ -786,8 +785,8 @@
{
expectCurrentTime();
expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
- expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats).atLeastOnce();
+ expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+ .andReturn(stats.getTotalBytes()).atLeastOnce();
expectPolicyDataEnable(TYPE_WIFI, true);
// snoozed interface still has high quota so background data is
@@ -827,8 +826,8 @@
{
expectCurrentTime();
expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
- expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats).atLeastOnce();
+ expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+ .andReturn(stats.getTotalBytes()).atLeastOnce();
expectPolicyDataEnable(TYPE_WIFI, true);
expectRemoveInterfaceQuota(TEST_IFACE);
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index 103d8e1..6d9bb29 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -54,6 +54,7 @@
import android.content.Intent;
import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver;
+import android.net.INetworkStatsSession;
import android.net.LinkProperties;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
@@ -84,7 +85,7 @@
*/
@LargeTest
public class NetworkStatsServiceTest extends AndroidTestCase {
- private static final String TAG = "NetworkStatsServiceTest";
+ private static final String TAG = "NetworkStatsServiceTest";
private static final String TEST_IFACE = "test0";
private static final String TEST_IFACE2 = "test1";
@@ -113,6 +114,7 @@
private IConnectivityManager mConnManager;
private NetworkStatsService mService;
+ private INetworkStatsSession mSession;
private INetworkManagementEventObserver mNetworkObserver;
@Override
@@ -134,6 +136,7 @@
mService = new NetworkStatsService(
mServiceContext, mNetManager, mAlarmManager, mTime, mStatsDir, mSettings);
mService.bindConnectivityManager(mConnManager);
+ mSession = mService.openSession();
mElapsedRealtime = 0L;
@@ -172,6 +175,7 @@
mSettings = null;
mConnManager = null;
+ mSession.close();
mService = null;
super.tearDown();
@@ -349,7 +353,7 @@
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
// verify service recorded history
- history = mService.getHistoryForNetwork(sTemplateWifi, FIELD_ALL);
+ history = mSession.getHistoryForNetwork(sTemplateWifi, FIELD_ALL);
assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0);
assertEquals(HOUR_IN_MILLIS, history.getBucketDuration());
assertEquals(2, history.size());
@@ -367,7 +371,7 @@
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
// verify identical stats, but spread across 4 buckets now
- history = mService.getHistoryForNetwork(sTemplateWifi, FIELD_ALL);
+ history = mSession.getHistoryForNetwork(sTemplateWifi, FIELD_ALL);
assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0);
assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration());
assertEquals(4, history.size());
@@ -652,7 +656,7 @@
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
// first verify entire history present
- NetworkStats stats = mService.getSummaryForAllUid(
+ NetworkStats stats = mSession.getSummaryForAllUid(
sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true);
assertEquals(3, stats.size());
assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 1);
@@ -661,7 +665,7 @@
// now verify that recent history only contains one uid
final long currentTime = currentTimeMillis();
- stats = mService.getSummaryForAllUid(
+ stats = mSession.getSummaryForAllUid(
sTemplateWifi, currentTime - HOUR_IN_MILLIS, currentTime, true);
assertEquals(1, stats.size());
assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0);
@@ -723,7 +727,7 @@
assertUidTotal(sTemplateWifi, UID_RED, 160L, 4L, 160L, 4L, 2);
// verify entire history present
- final NetworkStats stats = mService.getSummaryForAllUid(
+ final NetworkStats stats = mSession.getSummaryForAllUid(
sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true);
assertEquals(4, stats.size());
assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 1);
@@ -775,20 +779,20 @@
}
private void assertNetworkTotal(NetworkTemplate template, long rxBytes, long rxPackets,
- long txBytes, long txPackets, int operations) {
- final NetworkStatsHistory history = mService.getHistoryForNetwork(template, FIELD_ALL);
+ long txBytes, long txPackets, int operations) throws Exception {
+ final NetworkStatsHistory history = mSession.getHistoryForNetwork(template, FIELD_ALL);
assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, rxPackets, txBytes,
txPackets, operations);
}
private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long rxPackets,
- long txBytes, long txPackets, int operations) {
+ long txBytes, long txPackets, int operations) throws Exception {
assertUidTotal(template, uid, SET_ALL, rxBytes, rxPackets, txBytes, txPackets, operations);
}
private void assertUidTotal(NetworkTemplate template, int uid, int set, long rxBytes,
- long rxPackets, long txBytes, long txPackets, int operations) {
- final NetworkStatsHistory history = mService.getHistoryForUid(
+ long rxPackets, long txBytes, long txPackets, int operations) throws Exception {
+ final NetworkStatsHistory history = mSession.getHistoryForUid(
template, uid, set, TAG_NONE, FIELD_ALL);
assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, rxPackets, txBytes,
txPackets, operations);
diff --git a/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java b/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
index b7e80d4..919e2b3 100644
--- a/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
+++ b/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
@@ -17,15 +17,16 @@
import android.content.Context;
import android.net.INetworkStatsService;
+import android.net.INetworkStatsSession;
+import android.net.NetworkStats;
import android.net.NetworkStats.Entry;
import android.net.NetworkTemplate;
-import android.net.NetworkStats;
+import android.net.TrafficStats;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.TelephonyManager;
import android.test.InstrumentationTestCase;
-import android.test.InstrumentationTestRunner;
import android.util.Log;
/**
@@ -71,13 +72,17 @@
* @param template {link {@link NetworkTemplate} to match.
*/
private void fetchStats(NetworkTemplate template) {
+ INetworkStatsSession session = null;
try {
mStatsService.forceUpdate();
- NetworkStats stats = mStatsService.getSummaryForAllUid(template, Long.MIN_VALUE,
- Long.MAX_VALUE, false);
+ session = mStatsService.openSession();
+ final NetworkStats stats = session.getSummaryForAllUid(
+ template, Long.MIN_VALUE, Long.MAX_VALUE, false);
reportStats(stats);
} catch (RemoteException e) {
Log.w(LOG_TAG, "Failed to fetch network stats.");
+ } finally {
+ TrafficStats.closeQuietly(session);
}
}
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 198fce4..689aa8e 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -639,6 +639,12 @@
// If an app requests write storage, they will also get read storage.
bool hasReadExternalStoragePermission = false;
+ // Implement transition to read and write call log.
+ bool hasReadContactsPermission = false;
+ bool hasWriteContactsPermission = false;
+ bool hasReadCallLogPermission = false;
+ bool hasWriteCallLogPermission = false;
+
// This next group of variables is used to implement a group of
// backward-compatibility heuristics necessitated by the addition of
// some new uses-feature constants in 2.1 and 2.2. In most cases, the
@@ -1006,6 +1012,14 @@
hasReadExternalStoragePermission = true;
} else if (name == "android.permission.READ_PHONE_STATE") {
hasReadPhoneStatePermission = true;
+ } else if (name == "android.permission.READ_CONTACTS") {
+ hasReadContactsPermission = true;
+ } else if (name == "android.permission.WRITE_CONTACTS") {
+ hasWriteContactsPermission = true;
+ } else if (name == "android.permission.READ_CALL_LOG") {
+ hasReadCallLogPermission = true;
+ } else if (name == "android.permission.WRITE_CALL_LOG") {
+ hasWriteCallLogPermission = true;
}
printf("uses-permission:'%s'\n", name.string());
} else {
@@ -1181,6 +1195,16 @@
printf("uses-permission:'android.permission.READ_EXTERNAL_STORAGE'\n");
}
+ // Pre-JellyBean call log permission compatibility.
+ if (targetSdk < 16) {
+ if (!hasReadCallLogPermission && hasReadContactsPermission) {
+ printf("uses-permission:'android.permission.READ_CALL_LOG'\n");
+ }
+ if (!hasWriteCallLogPermission && hasWriteContactsPermission) {
+ printf("uses-permission:'android.permission.WRITE_CALL_LOG'\n");
+ }
+ }
+
/* The following blocks handle printing "inferred" uses-features, based
* on whether related features or permissions are used by the app.
* Note that the various spec*Feature variables denote whether the