Merge "AAPT2: Fix resource type id symbol merging"
diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java
index 8e659e0..f53ca94 100644
--- a/core/java/android/bluetooth/OobData.java
+++ b/core/java/android/bluetooth/OobData.java
@@ -31,6 +31,8 @@
*/
public class OobData implements Parcelable {
private byte[] securityManagerTk;
+ private byte[] leSecureConnectionsConfirmation;
+ private byte[] leSecureConnectionsRandom;
public byte[] getSecurityManagerTk() {
return securityManagerTk;
@@ -45,10 +47,28 @@
this.securityManagerTk = securityManagerTk;
}
+ public byte[] getLeSecureConnectionsConfirmation() {
+ return leSecureConnectionsConfirmation;
+ }
+
+ public void setLeSecureConnectionsConfirmation(byte[] leSecureConnectionsConfirmation) {
+ this.leSecureConnectionsConfirmation = leSecureConnectionsConfirmation;
+ }
+
+ public byte[] getLeSecureConnectionsRandom() {
+ return leSecureConnectionsRandom;
+ }
+
+ public void setLeSecureConnectionsRandom(byte[] leSecureConnectionsRandom) {
+ this.leSecureConnectionsRandom = leSecureConnectionsRandom;
+ }
+
public OobData() { }
private OobData(Parcel in) {
securityManagerTk = in.createByteArray();
+ leSecureConnectionsConfirmation = in.createByteArray();
+ leSecureConnectionsRandom = in.createByteArray();
}
public int describeContents() {
@@ -58,6 +78,8 @@
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeByteArray(securityManagerTk);
+ out.writeByteArray(leSecureConnectionsConfirmation);
+ out.writeByteArray(leSecureConnectionsRandom);
}
public static final Parcelable.Creator<OobData> CREATOR
diff --git a/core/java/android/view/SoundEffectConstants.java b/core/java/android/view/SoundEffectConstants.java
index 4a77af4..8d891bb 100644
--- a/core/java/android/view/SoundEffectConstants.java
+++ b/core/java/android/view/SoundEffectConstants.java
@@ -37,6 +37,8 @@
* or {@link View#FOCUS_BACKWARD}
* @return The appropriate sonification constant.
+ * @throws {@link IllegalArgumentException} when the passed direction is not one of the
+ * documented values.
*/
public static int getContantForFocusDirection(int direction) {
switch (direction) {
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 745da51..bb77100 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -229,7 +229,6 @@
@Override
protected void destroyHardwareResources() {
destroyHardwareLayer();
- mUpdateSurface = mSurface != null;
}
private void destroyHardwareLayer() {
@@ -376,17 +375,17 @@
}
mLayer = mAttachInfo.mThreadedRenderer.createTextureLayer();
- if (!mUpdateSurface) {
+ boolean createNewSurface = (mSurface == null);
+ if (createNewSurface) {
// Create a new SurfaceTexture for the layer.
mSurface = new SurfaceTexture(false);
mLayer.setSurfaceTexture(mSurface);
nCreateNativeWindow(mSurface);
}
mSurface.setDefaultBufferSize(getWidth(), getHeight());
-
mSurface.setOnFrameAvailableListener(mUpdateListener, mAttachInfo.mHandler);
- if (mListener != null && !mUpdateSurface) {
+ if (mListener != null && createNewSurface) {
mListener.onSurfaceTextureAvailable(mSurface, getWidth(), getHeight());
}
mLayer.setLayerPaint(mLayerPaint);
@@ -745,9 +744,11 @@
"released SurfaceTexture");
}
if (mSurface != null) {
+ nDestroyNativeWindow();
mSurface.release();
}
mSurface = surfaceTexture;
+ nCreateNativeWindow(mSurface);
/*
* If the view is visible and we already made a layer, update the
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c37cf56..e60d918 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -20674,6 +20674,9 @@
Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
return false;
}
+
+ data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
+
boolean okay = false;
Point shadowSize = new Point();
@@ -23864,7 +23867,7 @@
* on the screen.
*/
private boolean shouldDrawRoundScrollbar() {
- if (!mResources.getConfiguration().isScreenRound()) {
+ if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
return false;
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 2bc1d74..757727b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -5539,6 +5539,10 @@
// Remember who the current drag target is pre-dispatch
final View prevDragView = mCurrentDragView;
+ if (what == DragEvent.ACTION_DROP) {
+ event.getClipData().prepareToEnterProcess();
+ }
+
// Now dispatch the drag/drop event
boolean result = mView.dispatchDragEvent(event);
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 77e8c0e9..e37cf96 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -625,8 +625,12 @@
final InputConnection mDummyInputConnection = new BaseInputConnection(this, false);
InputMethodManager(Looper looper) throws ServiceNotFoundException {
- mService = IInputMethodManager.Stub.asInterface(
- ServiceManager.getServiceOrThrow(Context.INPUT_METHOD_SERVICE));
+ this(IInputMethodManager.Stub.asInterface(
+ ServiceManager.getServiceOrThrow(Context.INPUT_METHOD_SERVICE)), looper);
+ }
+
+ InputMethodManager(IInputMethodManager service, Looper looper) {
+ mService = service;
mMainLooper = looper;
mH = new H(looper);
mIInputContext = new ControlledInputConnectionWrapper(looper,
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 23e291f..ffa7107 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -58,21 +58,19 @@
#endif
// For both of these, err should be in the errno range (positive), not a status_t (negative)
-
-static void signalExceptionForPriorityError(JNIEnv* env, int err)
-{
+static void signalExceptionForError(JNIEnv* env, int err, int tid) {
switch (err) {
case EINVAL:
- jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+ jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+ "Invalid argument: %d", tid);
break;
case ESRCH:
- jniThrowException(env, "java/lang/IllegalArgumentException", "Given thread does not exist");
+ jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+ "Given thread %d does not exist", tid);
break;
case EPERM:
- jniThrowException(env, "java/lang/SecurityException", "No permission to modify given thread");
- break;
- case EACCES:
- jniThrowException(env, "java/lang/SecurityException", "No permission to set to given priority");
+ jniThrowExceptionFmt(env, "java/lang/SecurityException",
+ "No permission to modify given thread %d", tid);
break;
default:
jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
@@ -80,23 +78,27 @@
}
}
-static void signalExceptionForGroupError(JNIEnv* env, int err)
-{
+static void signalExceptionForPriorityError(JNIEnv* env, int err, int tid) {
switch (err) {
- case EINVAL:
- jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
- break;
- case ESRCH:
- jniThrowException(env, "java/lang/IllegalArgumentException", "Given thread does not exist");
- break;
- case EPERM:
- jniThrowException(env, "java/lang/SecurityException", "No permission to modify given thread");
- break;
case EACCES:
- jniThrowException(env, "java/lang/SecurityException", "No permission to set to given group");
+ jniThrowExceptionFmt(env, "java/lang/SecurityException",
+ "No permission to set the priority of %d", tid);
break;
default:
- jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
+ signalExceptionForError(env, err, tid);
+ break;
+ }
+
+}
+
+static void signalExceptionForGroupError(JNIEnv* env, int err, int tid) {
+ switch (err) {
+ case EACCES:
+ jniThrowExceptionFmt(env, "java/lang/SecurityException",
+ "No permission to set the group of %d", tid);
+ break;
+ default:
+ signalExceptionForError(env, err, tid);
break;
}
}
@@ -171,7 +173,7 @@
SchedPolicy sp = (SchedPolicy) grp;
int res = set_sched_policy(tid, sp);
if (res != NO_ERROR) {
- signalExceptionForGroupError(env, -res);
+ signalExceptionForGroupError(env, -res, tid);
}
}
@@ -183,7 +185,7 @@
struct dirent *de;
if ((grp == SP_FOREGROUND) || (grp > SP_MAX)) {
- signalExceptionForGroupError(env, EINVAL);
+ signalExceptionForGroupError(env, EINVAL, pid);
return;
}
@@ -219,7 +221,7 @@
if (!(d = opendir(proc_path))) {
// If the process exited on us, don't generate an exception
if (errno != ENOENT)
- signalExceptionForGroupError(env, errno);
+ signalExceptionForGroupError(env, errno, pid);
return;
}
@@ -254,7 +256,7 @@
#ifdef ENABLE_CPUSETS
int err = set_cpuset_policy(t_pid, sp);
if (err != NO_ERROR) {
- signalExceptionForGroupError(env, -err);
+ signalExceptionForGroupError(env, -err, t_pid);
break;
}
#endif
@@ -266,14 +268,14 @@
// set both cpuset and cgroup for general threads
err = set_cpuset_policy(t_pid, sp);
if (err != NO_ERROR) {
- signalExceptionForGroupError(env, -err);
+ signalExceptionForGroupError(env, -err, t_pid);
break;
}
#endif
err = set_sched_policy(t_pid, sp);
if (err != NO_ERROR) {
- signalExceptionForGroupError(env, -err);
+ signalExceptionForGroupError(env, -err, t_pid);
break;
}
@@ -285,7 +287,7 @@
{
SchedPolicy sp;
if (get_sched_policy(pid, &sp) != 0) {
- signalExceptionForGroupError(env, errno);
+ signalExceptionForGroupError(env, errno, pid);
}
return (int) sp;
}
@@ -400,7 +402,7 @@
jintArray cpus;
int pid = getpid();
if (get_sched_policy(pid, &sp) != 0) {
- signalExceptionForGroupError(env, errno);
+ signalExceptionForGroupError(env, errno, pid);
return NULL;
}
get_exclusive_cpuset_cores(sp, &cpu_set);
@@ -449,10 +451,10 @@
errno = 0;
policy = sched_getscheduler(tid);
if (errno != 0) {
- signalExceptionForPriorityError(env, errno);
+ signalExceptionForPriorityError(env, errno, tid);
}
#else
- signalExceptionForPriorityError(env, ENOSYS);
+ signalExceptionForPriorityError(env, ENOSYS, tid);
#endif
return policy;
}
@@ -466,10 +468,10 @@
param.sched_priority = pri;
int rc = sched_setscheduler(tid, policy, ¶m);
if (rc) {
- signalExceptionForPriorityError(env, errno);
+ signalExceptionForPriorityError(env, errno, tid);
}
#else
- signalExceptionForPriorityError(env, ENOSYS);
+ signalExceptionForPriorityError(env, ENOSYS, tid);
#endif
}
@@ -494,9 +496,9 @@
int rc = androidSetThreadPriority(pid, pri);
if (rc != 0) {
if (rc == INVALID_OPERATION) {
- signalExceptionForPriorityError(env, errno);
+ signalExceptionForPriorityError(env, errno, pid);
} else {
- signalExceptionForGroupError(env, errno);
+ signalExceptionForGroupError(env, errno, pid);
}
}
@@ -516,7 +518,7 @@
errno = 0;
jint pri = getpriority(PRIO_PROCESS, pid);
if (errno != 0) {
- signalExceptionForPriorityError(env, errno);
+ signalExceptionForPriorityError(env, errno, pid);
}
//ALOGI("Returning priority of %" PRId32 ": %" PRId32 "\n", pid, pri);
return pri;
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index a8205c8..c5d8767 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -101,7 +101,7 @@
const LsaVector<const SkBitmap*>& getBitmapResources() const { return bitmapResources; }
const LsaVector<FunctorContainer>& getFunctors() const { return functors; }
- const LsaVector<VectorDrawableRoot*>& getVectorDrawables() { return vectorDrawables; }
+ const LsaVector<VectorDrawableRoot*>& getVectorDrawables() const { return vectorDrawables; }
size_t addChild(NodeOpType* childOp);
diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp
index fd3cf37..0d90afa 100644
--- a/libs/hwui/tests/unit/RenderNodeTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeTests.cpp
@@ -15,6 +15,7 @@
*/
#include <gtest/gtest.h>
+#include <VectorDrawable.h>
#include "AnimationContext.h"
#include "DamageAccumulator.h"
@@ -132,3 +133,38 @@
canvasContext->destroy(nullptr);
}
+
+RENDERTHREAD_TEST(RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) {
+
+ VectorDrawable::Group* group = new VectorDrawable::Group();
+ VectorDrawableRoot* vectorDrawable = new VectorDrawableRoot(group);
+ auto rootNode = TestUtils::createNode(0, 0, 200, 400,
+ [&](RenderProperties& props, Canvas& canvas) {
+ canvas.drawVectorDrawable(vectorDrawable);
+ });
+ ContextFactory contextFactory;
+ std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
+ renderThread, false, rootNode.get(), &contextFactory));
+ TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
+ DamageAccumulator damageAccumulator;
+ LayerUpdateQueue layerUpdateQueue;
+ info.damageAccumulator = &damageAccumulator;
+ info.layerUpdateQueue = &layerUpdateQueue;
+ info.observer = nullptr;
+
+ // Put node on HW layer
+ rootNode->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
+
+ TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode);
+ rootNode->prepareTree(info);
+
+ // Check that the VD is in the dislay list, and the layer update queue contains the correct
+ // damage rect.
+ EXPECT_FALSE(rootNode->getDisplayList()->getVectorDrawables().empty());
+ EXPECT_FALSE(info.layerUpdateQueue->entries().empty());
+ EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode);
+ EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage);
+
+ delete vectorDrawable;
+ canvasContext->destroy(nullptr);
+}
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 2c4c6e5..d413083 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -25,6 +25,7 @@
import android.system.OsConstants;
import android.util.Log;
import android.util.Pair;
+import android.annotation.IntDef;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
@@ -55,6 +56,8 @@
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import libcore.io.IoUtils;
import libcore.io.Streams;
@@ -1166,16 +1169,24 @@
// The following values are used for indicating pointers to the other Image File Directories.
// Indices of Exif Ifd tag groups
- private static final int IFD_TIFF_HINT = 0;
- private static final int IFD_EXIF_HINT = 1;
- private static final int IFD_GPS_HINT = 2;
- private static final int IFD_INTEROPERABILITY_HINT = 3;
- private static final int IFD_THUMBNAIL_HINT = 4;
- private static final int IFD_PREVIEW_HINT = 5;
- private static final int ORF_MAKER_NOTE_HINT = 6;
- private static final int ORF_CAMERA_SETTINGS_HINT = 7;
- private static final int ORF_IMAGE_PROCESSING_HINT = 8;
- private static final int PEF_HINT = 9;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({IFD_TYPE_PRIMARY, IFD_TYPE_EXIF, IFD_TYPE_GPS, IFD_TYPE_INTEROPERABILITY,
+ IFD_TYPE_THUMBNAIL, IFD_TYPE_PREVIEW, IFD_TYPE_ORF_MAKER_NOTE,
+ IFD_TYPE_ORF_CAMERA_SETTINGS, IFD_TYPE_ORF_IMAGE_PROCESSING, IFD_TYPE_PEF})
+ public @interface IfdType {}
+
+ private static final int IFD_TYPE_PRIMARY = 0;
+ private static final int IFD_TYPE_EXIF = 1;
+ private static final int IFD_TYPE_GPS = 2;
+ private static final int IFD_TYPE_INTEROPERABILITY = 3;
+ private static final int IFD_TYPE_THUMBNAIL = 4;
+ private static final int IFD_TYPE_PREVIEW = 5;
+ private static final int IFD_TYPE_ORF_MAKER_NOTE = 6;
+ private static final int IFD_TYPE_ORF_CAMERA_SETTINGS = 7;
+ private static final int IFD_TYPE_ORF_IMAGE_PROCESSING = 8;
+ private static final int IFD_TYPE_PEF = 9;
+
// List of Exif tag groups
private static final ExifTag[][] EXIF_TAGS = new ExifTag[][] {
IFD_TIFF_TAGS, IFD_EXIF_TAGS, IFD_GPS_TAGS, IFD_INTEROPERABILITY_TAGS,
@@ -1191,11 +1202,7 @@
new ExifTag(TAG_ORF_CAMERA_SETTINGS_IFD_POINTER, 8224, IFD_FORMAT_BYTE),
new ExifTag(TAG_ORF_IMAGE_PROCESSING_IFD_POINTER, 8256, IFD_FORMAT_BYTE)
};
- // List of indices of the indicated tag groups according to the EXIF_POINTER_TAGS
- private static final int[] EXIF_POINTER_TAG_HINTS = new int[] {
- IFD_PREVIEW_HINT, IFD_EXIF_HINT, IFD_GPS_HINT, IFD_INTEROPERABILITY_HINT,
- ORF_CAMERA_SETTINGS_HINT, ORF_IMAGE_PROCESSING_HINT
- };
+
// Tags for indicating the thumbnail offset and length
private static final ExifTag JPEG_INTERCHANGE_FORMAT_TAG =
new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT, 513, IFD_FORMAT_ULONG);
@@ -1209,6 +1216,8 @@
private static final HashSet<String> sTagSetForCompatibility = new HashSet<>(Arrays.asList(
TAG_F_NUMBER, TAG_DIGITAL_ZOOM_RATIO, TAG_EXPOSURE_TIME, TAG_SUBJECT_DISTANCE,
TAG_GPS_TIMESTAMP));
+ // Mappings from tag number to IFD type for pointer tags.
+ private static final HashMap sExifPointerTagMap = new HashMap();
// See JPEG File Interchange Format Version 1.02.
// The following values are defined for handling JPEG streams. In this implementation, we are
@@ -1260,14 +1269,22 @@
sFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
// Build up the hash tables to look up Exif tags for reading Exif tags.
- for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
- sExifTagMapsForReading[hint] = new HashMap();
- sExifTagMapsForWriting[hint] = new HashMap();
- for (ExifTag tag : EXIF_TAGS[hint]) {
- sExifTagMapsForReading[hint].put(tag.number, tag);
- sExifTagMapsForWriting[hint].put(tag.name, tag);
+ for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) {
+ sExifTagMapsForReading[ifdType] = new HashMap();
+ sExifTagMapsForWriting[ifdType] = new HashMap();
+ for (ExifTag tag : EXIF_TAGS[ifdType]) {
+ sExifTagMapsForReading[ifdType].put(tag.number, tag);
+ sExifTagMapsForWriting[ifdType].put(tag.name, tag);
}
}
+
+ // Build up the hash table to look up Exif pointer tags.
+ sExifPointerTagMap.put(EXIF_POINTER_TAGS[0].number, IFD_TYPE_PREVIEW); // 330
+ sExifPointerTagMap.put(EXIF_POINTER_TAGS[1].number, IFD_TYPE_EXIF); // 34665
+ sExifPointerTagMap.put(EXIF_POINTER_TAGS[2].number, IFD_TYPE_GPS); // 34853
+ sExifPointerTagMap.put(EXIF_POINTER_TAGS[3].number, IFD_TYPE_INTEROPERABILITY); // 40965
+ sExifPointerTagMap.put(EXIF_POINTER_TAGS[4].number, IFD_TYPE_ORF_CAMERA_SETTINGS); // 8224
+ sExifPointerTagMap.put(EXIF_POINTER_TAGS[5].number, IFD_TYPE_ORF_IMAGE_PROCESSING); // 8256
}
private final String mFilename;
@@ -1503,7 +1520,7 @@
}
for (int i = 0 ; i < EXIF_TAGS.length; ++i) {
- if (i == IFD_THUMBNAIL_HINT && !mHasThumbnail) {
+ if (i == IFD_TYPE_THUMBNAIL && !mHasThumbnail) {
continue;
}
final Object obj = sExifTagMapsForWriting[i].get(tag);
@@ -1662,7 +1679,7 @@
switch (mMimeType) {
case IMAGE_TYPE_JPEG: {
- getJpegAttributes(in, 0, IFD_TIFF_HINT); // 0 is offset
+ getJpegAttributes(in, 0, IFD_TYPE_PRIMARY); // 0 is offset
break;
}
case IMAGE_TYPE_RAF: {
@@ -1894,9 +1911,9 @@
}
ExifAttribute imageLengthAttribute =
- (ExifAttribute) mAttributes[IFD_THUMBNAIL_HINT].get(TAG_IMAGE_LENGTH);
+ (ExifAttribute) mAttributes[IFD_TYPE_THUMBNAIL].get(TAG_IMAGE_LENGTH);
ExifAttribute imageWidthAttribute =
- (ExifAttribute) mAttributes[IFD_THUMBNAIL_HINT].get(TAG_IMAGE_WIDTH);
+ (ExifAttribute) mAttributes[IFD_TYPE_THUMBNAIL].get(TAG_IMAGE_WIDTH);
if (imageLengthAttribute != null && imageWidthAttribute != null) {
int imageLength = imageLengthAttribute.getIntValue(mExifByteOrder);
int imageWidth = imageWidthAttribute.getIntValue(mExifByteOrder);
@@ -2165,9 +2182,9 @@
*
* @param inputStream The input stream that starts with the JPEG data.
* @param jpegOffset The offset value in input stream for JPEG data.
- * @param imageTypes The image type from which to retrieve metadata. Use IFD_TIFF_HINT for
- * primary image, IFD_PREVIEW_HINT for preview image, and
- * IFD_THUMBNAIL_HINT for thumbnail image.
+ * @param imageTypes The image type from which to retrieve metadata. Use IFD_TYPE_PRIMARY for
+ * primary image, IFD_TYPE_PREVIEW for preview image, and
+ * IFD_TYPE_THUMBNAIL for thumbnail image.
* @throws IOException If the data contains invalid JPEG markers, offsets, or length values.
*/
private void getJpegAttributes(InputStream inputStream, int jpegOffset, int imageType)
@@ -2268,7 +2285,7 @@
}
length = 0;
if (getAttribute(TAG_USER_COMMENT) == null) {
- mAttributes[IFD_EXIF_HINT].put(TAG_USER_COMMENT, ExifAttribute.createString(
+ mAttributes[IFD_TYPE_EXIF].put(TAG_USER_COMMENT, ExifAttribute.createString(
new String(bytes, ASCII)));
}
break;
@@ -2328,12 +2345,12 @@
parseTiffHeaders(dataInputStream, exifBytes.length);
// Read TIFF image file directories. See JEITA CP-3451C Section 4.5.2. Figure 6.
- readImageFileDirectory(dataInputStream, IFD_TIFF_HINT);
+ readImageFileDirectory(dataInputStream, IFD_TYPE_PRIMARY);
// Update ImageLength/Width tags for all image data.
- updateImageSizeValues(in, IFD_TIFF_HINT);
- updateImageSizeValues(in, IFD_PREVIEW_HINT);
- updateImageSizeValues(in, IFD_THUMBNAIL_HINT);
+ updateImageSizeValues(in, IFD_TYPE_PRIMARY);
+ updateImageSizeValues(in, IFD_TYPE_PREVIEW);
+ updateImageSizeValues(in, IFD_TYPE_THUMBNAIL);
// Check if each image data is in valid position.
validateImages(in);
@@ -2342,7 +2359,7 @@
// PEF files contain a MakerNote data, which contains the data for ColorSpace tag.
// See http://lclevy.free.fr/raw/ and piex.cc PefGetPreviewData()
ExifAttribute makerNoteAttribute =
- (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_MAKER_NOTE);
+ (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_MAKER_NOTE);
if (makerNoteAttribute != null) {
// Create an ordered DataInputStream for MakerNote
ByteOrderAwarenessDataInputStream makerNoteDataInputStream =
@@ -2353,13 +2370,13 @@
makerNoteDataInputStream.seek(PEF_MAKER_NOTE_SKIP_SIZE);
// Read IFD data from MakerNote
- readImageFileDirectory(makerNoteDataInputStream, PEF_HINT);
+ readImageFileDirectory(makerNoteDataInputStream, IFD_TYPE_PEF);
// Update ColorSpace tag
ExifAttribute colorSpaceAttribute =
- (ExifAttribute) mAttributes[PEF_HINT].get(TAG_COLOR_SPACE);
+ (ExifAttribute) mAttributes[IFD_TYPE_PEF].get(TAG_COLOR_SPACE);
if (colorSpaceAttribute != null) {
- mAttributes[IFD_EXIF_HINT].put(TAG_COLOR_SPACE, colorSpaceAttribute);
+ mAttributes[IFD_TYPE_EXIF].put(TAG_COLOR_SPACE, colorSpaceAttribute);
}
}
}
@@ -2392,7 +2409,7 @@
in.reset();
// Retrieve JPEG image metadata
- getJpegAttributes(in, rafJpegOffset, IFD_PREVIEW_HINT);
+ getJpegAttributes(in, rafJpegOffset, IFD_TYPE_PREVIEW);
// Skip to CFA header offset.
// A while loop is used because the skip method may not be able to skip the requested amount
@@ -2429,8 +2446,8 @@
ExifAttribute.createUShort(imageLength, mExifByteOrder);
ExifAttribute imageWidthAttribute =
ExifAttribute.createUShort(imageWidth, mExifByteOrder);
- mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_LENGTH, imageLengthAttribute);
- mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_WIDTH, imageWidthAttribute);
+ mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH, imageLengthAttribute);
+ mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH, imageWidthAttribute);
if (DEBUG) {
Log.d(TAG, "Updated to length: " + imageLength + ", width: " + imageWidth);
}
@@ -2459,7 +2476,7 @@
// proprietary tags and therefore does not have offical documentation
// See GetOlympusPreviewImage() in piex.cc & http://www.exiv2.org/tags-olympus.html
ExifAttribute makerNoteAttribute =
- (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_MAKER_NOTE);
+ (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_MAKER_NOTE);
if (makerNoteAttribute != null) {
// Create an ordered DataInputStream for MakerNote
ByteOrderAwarenessDataInputStream makerNoteDataInputStream =
@@ -2481,18 +2498,18 @@
}
// Read IFD data from MakerNote
- readImageFileDirectory(makerNoteDataInputStream, ORF_MAKER_NOTE_HINT);
+ readImageFileDirectory(makerNoteDataInputStream, IFD_TYPE_ORF_MAKER_NOTE);
// Retrieve & update preview image offset & length values
ExifAttribute imageLengthAttribute = (ExifAttribute)
- mAttributes[ORF_CAMERA_SETTINGS_HINT].get(TAG_ORF_PREVIEW_IMAGE_START);
+ mAttributes[IFD_TYPE_ORF_CAMERA_SETTINGS].get(TAG_ORF_PREVIEW_IMAGE_START);
ExifAttribute bitsPerSampleAttribute = (ExifAttribute)
- mAttributes[ORF_CAMERA_SETTINGS_HINT].get(TAG_ORF_PREVIEW_IMAGE_LENGTH);
+ mAttributes[IFD_TYPE_ORF_CAMERA_SETTINGS].get(TAG_ORF_PREVIEW_IMAGE_LENGTH);
if (imageLengthAttribute != null && bitsPerSampleAttribute != null) {
- mAttributes[IFD_PREVIEW_HINT].put(TAG_JPEG_INTERCHANGE_FORMAT,
+ mAttributes[IFD_TYPE_PREVIEW].put(TAG_JPEG_INTERCHANGE_FORMAT,
imageLengthAttribute);
- mAttributes[IFD_PREVIEW_HINT].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
+ mAttributes[IFD_TYPE_PREVIEW].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
bitsPerSampleAttribute);
}
@@ -2500,7 +2517,7 @@
// Retrieve primary image length & width values
// See piex.cc GetOlympusPreviewImage()
ExifAttribute aspectFrameAttribute = (ExifAttribute)
- mAttributes[ORF_IMAGE_PROCESSING_HINT].get(TAG_ORF_ASPECT_FRAME);
+ mAttributes[IFD_TYPE_ORF_IMAGE_PROCESSING].get(TAG_ORF_ASPECT_FRAME);
if (aspectFrameAttribute != null) {
int[] aspectFrameValues = new int[4];
aspectFrameValues = (int[]) aspectFrameAttribute.getValue(mExifByteOrder);
@@ -2519,8 +2536,8 @@
ExifAttribute primaryImageLengthAttribute =
ExifAttribute.createUShort(primaryImageLength, mExifByteOrder);
- mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_WIDTH, primaryImageWidthAttribute);
- mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_LENGTH, primaryImageLengthAttribute);
+ mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH, primaryImageWidthAttribute);
+ mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH, primaryImageLengthAttribute);
}
}
}
@@ -2535,47 +2552,19 @@
// Retrieve preview and/or thumbnail image data
ExifAttribute jpgFromRawAttribute =
- (ExifAttribute) mAttributes[IFD_TIFF_HINT].get(TAG_RW2_JPG_FROM_RAW);
+ (ExifAttribute) mAttributes[IFD_TYPE_PRIMARY].get(TAG_RW2_JPG_FROM_RAW);
if (jpgFromRawAttribute != null) {
- getJpegAttributes(in, mRw2JpgFromRawOffset, IFD_PREVIEW_HINT);
+ getJpegAttributes(in, mRw2JpgFromRawOffset, IFD_TYPE_PREVIEW);
}
// Set ISO tag value if necessary
ExifAttribute rw2IsoAttribute =
- (ExifAttribute) mAttributes[IFD_TIFF_HINT].get(TAG_RW2_ISO);
+ (ExifAttribute) mAttributes[IFD_TYPE_PRIMARY].get(TAG_RW2_ISO);
ExifAttribute exifIsoAttribute =
- (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_ISO_SPEED_RATINGS);
+ (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_ISO_SPEED_RATINGS);
if (rw2IsoAttribute != null && exifIsoAttribute == null) {
// Place this attribute only if it doesn't exist
- mAttributes[IFD_EXIF_HINT].put(TAG_ISO_SPEED_RATINGS, rw2IsoAttribute);
- }
- }
-
- // PEF is TIFF-based and contains 3 IFDs. It also contains a MakerNote data, which contains the
- // ColorSpace tag data.
- // See http://lclevy.free.fr/raw/ and piex.cc PefGetPreviewData()
- private void getPefAttributes(InputStream in) throws IOException {
- // Retrieve ColorSpace tag
- ExifAttribute makerNoteAttribute =
- (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_MAKER_NOTE);
- if (makerNoteAttribute != null) {
- // Create an ordered DataInputStream for MakerNote
- ByteOrderAwarenessDataInputStream makerNoteDataInputStream =
- new ByteOrderAwarenessDataInputStream(makerNoteAttribute.bytes);
- makerNoteDataInputStream.setByteOrder(mExifByteOrder);
-
- // Seek to MakerNote data
- makerNoteDataInputStream.seek(PEF_MAKER_NOTE_SKIP_SIZE);
-
- // Read IFD data from MakerNote
- readImageFileDirectory(makerNoteDataInputStream, PEF_HINT);
-
- // Update ColorSpace tag
- ExifAttribute colorSpaceAttribute =
- (ExifAttribute) mAttributes[PEF_HINT].get(TAG_COLOR_SPACE);
- if (colorSpaceAttribute != null) {
- mAttributes[IFD_EXIF_HINT].put(TAG_COLOR_SPACE, colorSpaceAttribute);
- }
+ mAttributes[IFD_TYPE_EXIF].put(TAG_ISO_SPEED_RATINGS, rw2IsoAttribute);
}
}
@@ -2693,25 +2682,25 @@
// The value of DATETIME tag has the same value of DATETIME_ORIGINAL tag.
String valueOfDateTimeOriginal = getAttribute(TAG_DATETIME_ORIGINAL);
if (valueOfDateTimeOriginal != null) {
- mAttributes[IFD_TIFF_HINT].put(TAG_DATETIME,
+ mAttributes[IFD_TYPE_PRIMARY].put(TAG_DATETIME,
ExifAttribute.createString(valueOfDateTimeOriginal));
}
// Add the default value.
if (getAttribute(TAG_IMAGE_WIDTH) == null) {
- mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_WIDTH,
+ mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH,
ExifAttribute.createULong(0, mExifByteOrder));
}
if (getAttribute(TAG_IMAGE_LENGTH) == null) {
- mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_LENGTH,
+ mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH,
ExifAttribute.createULong(0, mExifByteOrder));
}
if (getAttribute(TAG_ORIENTATION) == null) {
- mAttributes[IFD_TIFF_HINT].put(TAG_ORIENTATION,
+ mAttributes[IFD_TYPE_PRIMARY].put(TAG_ORIENTATION,
ExifAttribute.createULong(0, mExifByteOrder));
}
if (getAttribute(TAG_LIGHT_SOURCE) == null) {
- mAttributes[IFD_EXIF_HINT].put(TAG_LIGHT_SOURCE,
+ mAttributes[IFD_TYPE_EXIF].put(TAG_LIGHT_SOURCE,
ExifAttribute.createULong(0, mExifByteOrder));
}
}
@@ -2763,8 +2752,8 @@
}
// Reads image file directory, which is a tag group in EXIF.
- private void readImageFileDirectory(ByteOrderAwarenessDataInputStream dataInputStream, int hint)
- throws IOException {
+ private void readImageFileDirectory(ByteOrderAwarenessDataInputStream dataInputStream,
+ @IfdType int ifdType) throws IOException {
if (dataInputStream.peek() + 2 > dataInputStream.mLength) {
// Return if there is no data from the offset.
return;
@@ -2789,12 +2778,12 @@
long nextEntryOffset = dataInputStream.peek() + 4;
// Look up a corresponding tag from tag number
- ExifTag tag = (ExifTag) sExifTagMapsForReading[hint].get(tagNumber);
+ ExifTag tag = (ExifTag) sExifTagMapsForReading[ifdType].get(tagNumber);
if (DEBUG) {
- Log.d(TAG, String.format("hint: %d, tagNumber: %d, tagName: %s, dataFormat: %d, " +
- "numberOfComponents: %d", hint, tagNumber, tag != null ? tag.name : null,
- dataFormat, numberOfComponents));
+ Log.d(TAG, String.format("ifdType: %d, tagNumber: %d, tagName: %s, dataFormat: %d, "
+ + "numberOfComponents: %d", ifdType, tagNumber,
+ tag != null ? tag.name : null, dataFormat, numberOfComponents));
}
if (tag == null || dataFormat <= 0 ||
@@ -2821,7 +2810,8 @@
if (tag.name == TAG_MAKER_NOTE) {
// Save offset value for reading thumbnail
mOrfMakerNoteOffset = offset;
- } else if (hint == ORF_MAKER_NOTE_HINT && tag.name == TAG_ORF_THUMBNAIL_IMAGE) {
+ } else if (ifdType == IFD_TYPE_ORF_MAKER_NOTE
+ && tag.name == TAG_ORF_THUMBNAIL_IMAGE) {
// Retrieve & update values for thumbnail offset and length values for ORF
mOrfThumbnailOffset = offset;
mOrfThumbnailLength = numberOfComponents;
@@ -2833,10 +2823,10 @@
ExifAttribute jpegInterchangeFormatLengthAttribute =
ExifAttribute.createULong(mOrfThumbnailLength, mExifByteOrder);
- mAttributes[IFD_THUMBNAIL_HINT].put(TAG_COMPRESSION, compressionAttribute);
- mAttributes[IFD_THUMBNAIL_HINT].put(TAG_JPEG_INTERCHANGE_FORMAT,
+ mAttributes[IFD_TYPE_THUMBNAIL].put(TAG_COMPRESSION, compressionAttribute);
+ mAttributes[IFD_TYPE_THUMBNAIL].put(TAG_JPEG_INTERCHANGE_FORMAT,
jpegInterchangeFormatAttribute);
- mAttributes[IFD_THUMBNAIL_HINT].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
+ mAttributes[IFD_TYPE_THUMBNAIL].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
jpegInterchangeFormatLengthAttribute);
}
} else if (mMimeType == IMAGE_TYPE_RW2) {
@@ -2855,12 +2845,12 @@
}
// Recursively parse IFD when a IFD pointer tag appears.
- int innerIfdHint = getIfdHintFromTagNumber(tagNumber);
+ Object nextIfdType = sExifPointerTagMap.get(tagNumber);
if (DEBUG) {
- Log.d(TAG, "innerIfdHint: " + innerIfdHint + " byteCount: " + byteCount);
+ Log.d(TAG, "nextIfdType: " + nextIfdType + " byteCount: " + byteCount);
}
- if (innerIfdHint >= 0) {
+ if (nextIfdType != null) {
long offset = -1L;
// Get offset from data field
switch (dataFormat) {
@@ -2891,7 +2881,7 @@
}
if (offset > 0L && offset < dataInputStream.mLength) {
dataInputStream.seek(offset);
- readImageFileDirectory(dataInputStream, innerIfdHint);
+ readImageFileDirectory(dataInputStream, (int) nextIfdType);
} else {
Log.w(TAG, "Skip jump into the IFD since its offset is invalid: " + offset);
}
@@ -2903,7 +2893,7 @@
byte[] bytes = new byte[byteCount];
dataInputStream.readFully(bytes);
ExifAttribute attribute = new ExifAttribute(dataFormat, numberOfComponents, bytes);
- mAttributes[hint].put(tag.name, attribute);
+ mAttributes[ifdType].put(tag.name, attribute);
// DNG files have a DNG Version tag specifying the version of specifications that the
// image file is following.
@@ -2937,11 +2927,11 @@
// since the first IFD offset is at least 8.
if (nextIfdOffset > 8 && nextIfdOffset < dataInputStream.mLength) {
dataInputStream.seek(nextIfdOffset);
- if (mAttributes[IFD_THUMBNAIL_HINT].isEmpty()) {
+ if (mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) {
// Do not overwrite thumbnail IFD data if it alreay exists.
- readImageFileDirectory(dataInputStream, IFD_THUMBNAIL_HINT);
- } else if (mAttributes[IFD_PREVIEW_HINT].isEmpty()) {
- readImageFileDirectory(dataInputStream, IFD_PREVIEW_HINT);
+ readImageFileDirectory(dataInputStream, IFD_TYPE_THUMBNAIL);
+ } else if (mAttributes[IFD_TYPE_PREVIEW].isEmpty()) {
+ readImageFileDirectory(dataInputStream, IFD_TYPE_PREVIEW);
}
}
}
@@ -2976,7 +2966,7 @@
// Sets thumbnail offset & length attributes based on JpegInterchangeFormat or StripOffsets tags
private void setThumbnailData(InputStream in) throws IOException {
- HashMap thumbnailData = mAttributes[IFD_THUMBNAIL_HINT];
+ HashMap thumbnailData = mAttributes[IFD_TYPE_THUMBNAIL];
ExifAttribute compressionAttribute =
(ExifAttribute) thumbnailData.get(TAG_COMPRESSION);
@@ -3146,21 +3136,21 @@
// Validate primary, preview, thumbnail image data by comparing image size
private void validateImages(InputStream in) throws IOException {
// Swap images based on size (primary > preview > thumbnail)
- swapBasedOnImageSize(IFD_TIFF_HINT, IFD_PREVIEW_HINT);
- swapBasedOnImageSize(IFD_TIFF_HINT, IFD_THUMBNAIL_HINT);
- swapBasedOnImageSize(IFD_PREVIEW_HINT, IFD_THUMBNAIL_HINT);
+ swapBasedOnImageSize(IFD_TYPE_PRIMARY, IFD_TYPE_PREVIEW);
+ swapBasedOnImageSize(IFD_TYPE_PRIMARY, IFD_TYPE_THUMBNAIL);
+ swapBasedOnImageSize(IFD_TYPE_PREVIEW, IFD_TYPE_THUMBNAIL);
// Check whether thumbnail image exists and whether preview image satisfies the thumbnail
// image requirements
- if (mAttributes[IFD_THUMBNAIL_HINT].isEmpty()) {
- if (isThumbnail(mAttributes[IFD_PREVIEW_HINT])) {
- mAttributes[IFD_THUMBNAIL_HINT] = mAttributes[IFD_PREVIEW_HINT];
- mAttributes[IFD_PREVIEW_HINT] = new HashMap();
+ if (mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) {
+ if (isThumbnail(mAttributes[IFD_TYPE_PREVIEW])) {
+ mAttributes[IFD_TYPE_THUMBNAIL] = mAttributes[IFD_TYPE_PREVIEW];
+ mAttributes[IFD_TYPE_PREVIEW] = new HashMap();
}
}
// Check if the thumbnail image satisfies the thumbnail size requirements
- if (!isThumbnail(mAttributes[IFD_THUMBNAIL_HINT])) {
+ if (!isThumbnail(mAttributes[IFD_TYPE_THUMBNAIL])) {
Log.d(TAG, "No image meets the size requirements of a thumbnail image.");
}
}
@@ -3244,9 +3234,9 @@
if (newSubfileTypeValue == ORIGINAL_RESOLUTION_IMAGE) {
// Update only for the primary image (OriginalResolutionImage)
ExifAttribute pixelXDimAttribute =
- (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_PIXEL_X_DIMENSION);
+ (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_PIXEL_X_DIMENSION);
ExifAttribute pixelYDimAttribute =
- (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_PIXEL_Y_DIMENSION);
+ (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_PIXEL_Y_DIMENSION);
if (pixelXDimAttribute != null && pixelYDimAttribute != null) {
mAttributes[imageType].put(TAG_IMAGE_WIDTH, pixelXDimAttribute);
@@ -3259,16 +3249,6 @@
}
}
- // Gets the corresponding IFD group index of the given tag number for writing Exif Tags.
- private static int getIfdHintFromTagNumber(int tagNumber) {
- for (int i = 0; i < EXIF_POINTER_TAG_HINTS.length; ++i) {
- if (EXIF_POINTER_TAGS[i].number == tagNumber) {
- return EXIF_POINTER_TAG_HINTS[i];
- }
- }
- return -1;
- }
-
// Writes an Exif segment into the given output stream.
private int writeExifSegment(ByteOrderAwarenessDataOutputStream dataOutputStream,
int exifOffsetFromBeginning) throws IOException {
@@ -3285,33 +3265,33 @@
removeAttribute(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name);
// Remove null value tags.
- for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
- for (Object obj : mAttributes[hint].entrySet().toArray()) {
+ for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) {
+ for (Object obj : mAttributes[ifdType].entrySet().toArray()) {
final Map.Entry entry = (Map.Entry) obj;
if (entry.getValue() == null) {
- mAttributes[hint].remove(entry.getKey());
+ mAttributes[ifdType].remove(entry.getKey());
}
}
}
// Add IFD pointer tags. The next offset of primary image TIFF IFD will have thumbnail IFD
// offset when there is one or more tags in the thumbnail IFD.
- if (!mAttributes[IFD_EXIF_HINT].isEmpty()) {
- mAttributes[IFD_TIFF_HINT].put(EXIF_POINTER_TAGS[1].name,
+ if (!mAttributes[IFD_TYPE_EXIF].isEmpty()) {
+ mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[1].name,
ExifAttribute.createULong(0, mExifByteOrder));
}
- if (!mAttributes[IFD_GPS_HINT].isEmpty()) {
- mAttributes[IFD_TIFF_HINT].put(EXIF_POINTER_TAGS[2].name,
+ if (!mAttributes[IFD_TYPE_GPS].isEmpty()) {
+ mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[2].name,
ExifAttribute.createULong(0, mExifByteOrder));
}
- if (!mAttributes[IFD_INTEROPERABILITY_HINT].isEmpty()) {
- mAttributes[IFD_EXIF_HINT].put(EXIF_POINTER_TAGS[3].name,
+ if (!mAttributes[IFD_TYPE_INTEROPERABILITY].isEmpty()) {
+ mAttributes[IFD_TYPE_EXIF].put(EXIF_POINTER_TAGS[3].name,
ExifAttribute.createULong(0, mExifByteOrder));
}
if (mHasThumbnail) {
- mAttributes[IFD_THUMBNAIL_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.name,
+ mAttributes[IFD_TYPE_THUMBNAIL].put(JPEG_INTERCHANGE_FORMAT_TAG.name,
ExifAttribute.createULong(0, mExifByteOrder));
- mAttributes[IFD_THUMBNAIL_HINT].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name,
+ mAttributes[IFD_TYPE_THUMBNAIL].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name,
ExifAttribute.createULong(mThumbnailLength, mExifByteOrder));
}
@@ -3331,15 +3311,15 @@
// Calculate IFD offsets.
int position = 8;
- for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
- if (!mAttributes[hint].isEmpty()) {
- ifdOffsets[hint] = position;
- position += 2 + mAttributes[hint].size() * 12 + 4 + ifdDataSizes[hint];
+ for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) {
+ if (!mAttributes[ifdType].isEmpty()) {
+ ifdOffsets[ifdType] = position;
+ position += 2 + mAttributes[ifdType].size() * 12 + 4 + ifdDataSizes[ifdType];
}
}
if (mHasThumbnail) {
int thumbnailOffset = position;
- mAttributes[IFD_THUMBNAIL_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.name,
+ mAttributes[IFD_TYPE_THUMBNAIL].put(JPEG_INTERCHANGE_FORMAT_TAG.name,
ExifAttribute.createULong(thumbnailOffset, mExifByteOrder));
mThumbnailOffset = exifOffsetFromBeginning + thumbnailOffset;
position += mThumbnailLength;
@@ -3356,17 +3336,17 @@
}
// Update IFD pointer tags with the calculated offsets.
- if (!mAttributes[IFD_EXIF_HINT].isEmpty()) {
- mAttributes[IFD_TIFF_HINT].put(EXIF_POINTER_TAGS[1].name,
- ExifAttribute.createULong(ifdOffsets[IFD_EXIF_HINT], mExifByteOrder));
+ if (!mAttributes[IFD_TYPE_EXIF].isEmpty()) {
+ mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[1].name,
+ ExifAttribute.createULong(ifdOffsets[IFD_TYPE_EXIF], mExifByteOrder));
}
- if (!mAttributes[IFD_GPS_HINT].isEmpty()) {
- mAttributes[IFD_TIFF_HINT].put(EXIF_POINTER_TAGS[2].name,
- ExifAttribute.createULong(ifdOffsets[IFD_GPS_HINT], mExifByteOrder));
+ if (!mAttributes[IFD_TYPE_GPS].isEmpty()) {
+ mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[2].name,
+ ExifAttribute.createULong(ifdOffsets[IFD_TYPE_GPS], mExifByteOrder));
}
- if (!mAttributes[IFD_INTEROPERABILITY_HINT].isEmpty()) {
- mAttributes[IFD_EXIF_HINT].put(EXIF_POINTER_TAGS[3].name, ExifAttribute.createULong(
- ifdOffsets[IFD_INTEROPERABILITY_HINT], mExifByteOrder));
+ if (!mAttributes[IFD_TYPE_INTEROPERABILITY].isEmpty()) {
+ mAttributes[IFD_TYPE_EXIF].put(EXIF_POINTER_TAGS[3].name, ExifAttribute.createULong(
+ ifdOffsets[IFD_TYPE_INTEROPERABILITY], mExifByteOrder));
}
// Write TIFF Headers. See JEITA CP-3451C Section 4.5.2. Table 1.
@@ -3379,17 +3359,18 @@
dataOutputStream.writeUnsignedInt(IFD_OFFSET);
// Write IFD groups. See JEITA CP-3451C Section 4.5.8. Figure 9.
- for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
- if (!mAttributes[hint].isEmpty()) {
+ for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) {
+ if (!mAttributes[ifdType].isEmpty()) {
// See JEITA CP-3451C Section 4.6.2: IFD structure.
// Write entry count
- dataOutputStream.writeUnsignedShort(mAttributes[hint].size());
+ dataOutputStream.writeUnsignedShort(mAttributes[ifdType].size());
// Write entry info
- int dataOffset = ifdOffsets[hint] + 2 + mAttributes[hint].size() * 12 + 4;
- for (Map.Entry entry : (Set<Map.Entry>) mAttributes[hint].entrySet()) {
+ int dataOffset = ifdOffsets[ifdType] + 2 + mAttributes[ifdType].size() * 12 + 4;
+ for (Map.Entry entry : (Set<Map.Entry>) mAttributes[ifdType].entrySet()) {
// Convert tag name to tag number.
- final ExifTag tag = (ExifTag) sExifTagMapsForWriting[hint].get(entry.getKey());
+ final ExifTag tag =
+ (ExifTag) sExifTagMapsForWriting[ifdType].get(entry.getKey());
final int tagNumber = tag.number;
final ExifAttribute attribute = (ExifAttribute) entry.getValue();
final int size = attribute.size();
@@ -3414,14 +3395,14 @@
// Write the next offset. It writes the offset of thumbnail IFD if there is one or
// more tags in the thumbnail IFD when the current IFD is the primary image TIFF
// IFD; Otherwise 0.
- if (hint == 0 && !mAttributes[IFD_THUMBNAIL_HINT].isEmpty()) {
- dataOutputStream.writeUnsignedInt(ifdOffsets[IFD_THUMBNAIL_HINT]);
+ if (ifdType == 0 && !mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) {
+ dataOutputStream.writeUnsignedInt(ifdOffsets[IFD_TYPE_THUMBNAIL]);
} else {
dataOutputStream.writeUnsignedInt(0);
}
// Write values of data field exceeding 4 bytes after the next offset.
- for (Map.Entry entry : (Set<Map.Entry>) mAttributes[hint].entrySet()) {
+ for (Map.Entry entry : (Set<Map.Entry>) mAttributes[ifdType].entrySet()) {
ExifAttribute attribute = (ExifAttribute) entry.getValue();
if (attribute.bytes.length > 4) {
@@ -3748,9 +3729,9 @@
}
// Swaps image data based on image size
- private void swapBasedOnImageSize(int firstImageHint, int secondImageHint)
+ private void swapBasedOnImageSize(@IfdType int firstIfdType, @IfdType int secondIfdType)
throws IOException {
- if (mAttributes[firstImageHint].isEmpty() || mAttributes[secondImageHint].isEmpty()) {
+ if (mAttributes[firstIfdType].isEmpty() || mAttributes[secondIfdType].isEmpty()) {
if (DEBUG) {
Log.d(TAG, "Cannot perform swap since only one image data exists");
}
@@ -3758,13 +3739,13 @@
}
ExifAttribute firstImageLengthAttribute =
- (ExifAttribute) mAttributes[firstImageHint].get(TAG_IMAGE_LENGTH);
+ (ExifAttribute) mAttributes[firstIfdType].get(TAG_IMAGE_LENGTH);
ExifAttribute firstImageWidthAttribute =
- (ExifAttribute) mAttributes[firstImageHint].get(TAG_IMAGE_WIDTH);
+ (ExifAttribute) mAttributes[firstIfdType].get(TAG_IMAGE_WIDTH);
ExifAttribute secondImageLengthAttribute =
- (ExifAttribute) mAttributes[secondImageHint].get(TAG_IMAGE_LENGTH);
+ (ExifAttribute) mAttributes[secondIfdType].get(TAG_IMAGE_LENGTH);
ExifAttribute secondImageWidthAttribute =
- (ExifAttribute) mAttributes[secondImageHint].get(TAG_IMAGE_WIDTH);
+ (ExifAttribute) mAttributes[secondIfdType].get(TAG_IMAGE_WIDTH);
if (firstImageLengthAttribute == null || firstImageWidthAttribute == null) {
if (DEBUG) {
@@ -3782,9 +3763,9 @@
if (firstImageLengthValue < secondImageLengthValue &&
firstImageWidthValue < secondImageWidthValue) {
- HashMap tempMap = mAttributes[firstImageHint];
- mAttributes[firstImageHint] = mAttributes[secondImageHint];
- mAttributes[secondImageHint] = tempMap;
+ HashMap tempMap = mAttributes[firstIfdType];
+ mAttributes[firstIfdType] = mAttributes[secondIfdType];
+ mAttributes[secondIfdType] = tempMap;
}
}
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
index b75f529..ddccc14 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
@@ -42,16 +42,21 @@
* Displays an alphanumeric (latin-1) key entry for the user to enter
* an unlock password
*/
-
public class KeyguardPasswordView extends KeyguardAbsKeyInputView
implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
private final boolean mShowImeAtScreenOn;
private final int mDisappearYTranslation;
+ // A delay constant to be used in a workaround for the situation where InputMethodManagerService
+ // is not switched to the new user yet.
+ // TODO: Remove this by ensuring such a race condition never happens.
+ private static final int DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON = 500; // 500ms
+
InputMethodManager mImm;
private TextView mPasswordEntry;
private TextViewInputDisabler mPasswordEntryDisabler;
+ private View mSwitchImeButton;
private Interpolator mLinearOutSlowInInterpolator;
private Interpolator mFastOutLinearInInterpolator;
@@ -141,12 +146,31 @@
mPasswordEntry.requestFocus();
}
+ private void updateSwitchImeButton() {
+ // If there's more than one IME, enable the IME switcher button
+ final boolean wasVisible = mSwitchImeButton.getVisibility() == View.VISIBLE;
+ final boolean shouldBeVisible = hasMultipleEnabledIMEsOrSubtypes(mImm, false);
+ if (wasVisible != shouldBeVisible) {
+ mSwitchImeButton.setVisibility(shouldBeVisible ? View.VISIBLE : View.GONE);
+ }
+
+ // TODO: Check if we still need this hack.
+ // If no icon is visible, reset the start margin on the password field so the text is
+ // still centered.
+ if (mSwitchImeButton.getVisibility() != View.VISIBLE) {
+ android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams();
+ if (params instanceof MarginLayoutParams) {
+ final MarginLayoutParams mlp = (MarginLayoutParams) params;
+ mlp.setMarginStart(0);
+ mPasswordEntry.setLayoutParams(params);
+ }
+ }
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- boolean imeOrDeleteButtonVisible = false;
-
mImm = (InputMethodManager) getContext().getSystemService(
Context.INPUT_METHOD_SERVICE);
@@ -171,31 +195,29 @@
mPasswordEntry.requestFocus();
- // If there's more than one IME, enable the IME switcher button
- View switchImeButton = findViewById(R.id.switch_ime_button);
- if (switchImeButton != null && hasMultipleEnabledIMEsOrSubtypes(mImm, false)) {
- switchImeButton.setVisibility(View.VISIBLE);
- imeOrDeleteButtonVisible = true;
- switchImeButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mCallback.userActivity(); // Leave the screen on a bit longer
- // Do not show auxiliary subtypes in password lock screen.
- mImm.showInputMethodPicker(false /* showAuxiliarySubtypes */);
- }
- });
- }
-
- // If no icon is visible, reset the start margin on the password field so the text is
- // still centered.
- if (!imeOrDeleteButtonVisible) {
- android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams();
- if (params instanceof MarginLayoutParams) {
- final MarginLayoutParams mlp = (MarginLayoutParams) params;
- mlp.setMarginStart(0);
- mPasswordEntry.setLayoutParams(params);
+ mSwitchImeButton = findViewById(R.id.switch_ime_button);
+ mSwitchImeButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mCallback.userActivity(); // Leave the screen on a bit longer
+ // Do not show auxiliary subtypes in password lock screen.
+ mImm.showInputMethodPicker(false /* showAuxiliarySubtypes */);
}
- }
+ });
+
+ // If there's more than one IME, enable the IME switcher button
+ updateSwitchImeButton();
+
+ // When we the current user is switching, InputMethodManagerService sometimes has not
+ // switched internal state yet here. As a quick workaround, we check the keyboard state
+ // again.
+ // TODO: Remove this workaround by ensuring such a race condition never happens.
+ postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ updateSwitchImeButton();
+ }
+ }, DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON);
}
@Override
diff --git a/packages/SettingsLib/res/values-ky-rKG/arrays.xml b/packages/SettingsLib/res/values-ky-rKG/arrays.xml
index a06ecfb..1aadb9b 100644
--- a/packages/SettingsLib/res/values-ky-rKG/arrays.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/arrays.xml
@@ -147,7 +147,7 @@
<string-array name="track_frame_time_entries">
<item msgid="2193584639058893150">"Өчүк"</item>
<item msgid="2751513398307949636">"Экранда тилке катары"</item>
- <item msgid="2355151170975410323">"Төмөнкүдө <xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g>"</item>
+ <item msgid="2355151170975410323">"Төмөнкүдө: <xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g>"</item>
</string-array>
<string-array name="debug_hw_overdraw_entries">
<item msgid="8190572633763871652">"Өчүк"</item>
diff --git a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
index cf08f50..687b3fc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
+++ b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
@@ -167,7 +167,7 @@
return (policy != null) ? policy.warningBytes : WARNING_DISABLED;
}
- public void setPolicyWarningBytes(NetworkTemplate template, long warningBytes) {
+ private void setPolicyWarningBytesInner(NetworkTemplate template, long warningBytes) {
final NetworkPolicy policy = getOrCreatePolicy(template);
policy.warningBytes = warningBytes;
policy.inferred = false;
@@ -175,12 +175,28 @@
writeAsync();
}
+ public void setPolicyWarningBytes(NetworkTemplate template, long warningBytes) {
+ long limitBytes = getPolicyLimitBytes(template);
+
+ // If the warningBytes are larger than limitBytes, set the warningBytes to limitBytes
+ warningBytes = Math.min(warningBytes, limitBytes);
+ setPolicyWarningBytesInner(template, warningBytes);
+ }
+
public long getPolicyLimitBytes(NetworkTemplate template) {
final NetworkPolicy policy = getPolicy(template);
return (policy != null) ? policy.limitBytes : LIMIT_DISABLED;
}
+
public void setPolicyLimitBytes(NetworkTemplate template, long limitBytes) {
+ long warningBytes = getPolicyWarningBytes(template);
+
+ // If the warningBytes are larger than limitBytes, set the warningBytes to limitBytes
+ if (warningBytes > limitBytes) {
+ setPolicyWarningBytesInner(template, limitBytes);
+ }
+
final NetworkPolicy policy = getOrCreatePolicy(template);
policy.limitBytes = limitBytes;
policy.inferred = false;
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 5acc177..a93c3e2 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -313,7 +313,7 @@
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampe de poche"</string>
<string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Données mobiles"</string>
- <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Consommation des données"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Conso des données"</string>
<string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Données restantes"</string>
<string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Limite dépassée"</string>
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> utilisés"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index de96cb0..a15ba26 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -309,7 +309,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Đang dùng làm điểm truy cập Internet"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Điểm phát sóng"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Thông báo"</string>
- <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Đèn nháy"</string>
+ <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Đèn pin"</string>
<string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Dữ liệu di động"</string>
<string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Sử dụng dữ liệu"</string>
<string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dữ liệu còn lại"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
index ac90ce7..19a5d52 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
@@ -237,6 +237,10 @@
mQSPanel.setListening(mListening && mQsExpanded);
}
+ public void setHeaderListening(boolean listening) {
+ mHeader.setListening(listening);
+ }
+
public void setQsExpansion(float expansion, float headerTranslation) {
if (DEBUG) Log.d(TAG, "setQSExpansion " + expansion + " " + headerTranslation);
mQsExpansion = expansion;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index b6597a0..ed0fc1f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -251,10 +251,12 @@
if (mListening) {
refreshAllTiles();
}
- if (listening) {
- mBrightnessController.registerCallbacks();
- } else {
- mBrightnessController.unregisterCallbacks();
+ if (mBrightnessView.getVisibility() == View.VISIBLE) {
+ if (listening) {
+ mBrightnessController.registerCallbacks();
+ } else {
+ mBrightnessController.unregisterCallbacks();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index f27f8f5..812c5c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1617,6 +1617,9 @@
if (mQsExpanded) {
onQsExpansionStarted();
}
+ // Since there are QS tiles in the header now, we need to make sure we start listening
+ // immediately so they can be up to date.
+ mQsContainer.setHeaderListening(true);
}
@Override
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 488f0e7..6b73fec 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -49,7 +49,6 @@
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
-import android.os.IBinder;
import android.os.IDeviceIdleController;
import android.os.IMaintenanceActivityListener;
import android.os.Looper;
@@ -1238,7 +1237,7 @@
}
}
- public final class LocalService {
+ public class LocalService {
public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync,
String reason) {
addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 649016f..09a3a17 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3807,6 +3807,15 @@
app.killedByAm = false;
checkTime(startTime, "startProcess: starting to update pids map");
synchronized (mPidsSelfLocked) {
+ ProcessRecord oldApp;
+ // If there is already an app occupying that pid that hasn't been cleaned up
+ if ((oldApp = mPidsSelfLocked.get(startResult.pid)) != null && !app.isolated) {
+ // Clean up anything relating to this pid first
+ Slog.w(TAG, "Reusing pid " + startResult.pid
+ + " while app is still mapped to it");
+ cleanUpApplicationRecordLocked(oldApp, false, false, -1,
+ true /*replacingPid*/);
+ }
this.mPidsSelfLocked.put(startResult.pid, app);
if (isActivityProcess) {
Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
@@ -5039,7 +5048,8 @@
private final void handleAppDiedLocked(ProcessRecord app,
boolean restarting, boolean allowRestart) {
int pid = app.pid;
- boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);
+ boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,
+ false /*replacingPid*/);
if (!kept && !restarting) {
removeLruProcessLocked(app);
if (pid > 0) {
@@ -16816,7 +16826,8 @@
* app that was passed in must remain on the process lists.
*/
private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
- boolean restarting, boolean allowRestart, int index) {
+ boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
+ Slog.d(TAG, "cleanUpApplicationRecord -- " + app.pid);
if (index >= 0) {
removeLruProcessLocked(app);
ProcessList.remove(app.pid);
@@ -16947,7 +16958,9 @@
if (!app.persistent || app.isolated) {
if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
"Removing non-persistent process during cleanup: " + app);
- removeProcessNameLocked(app.processName, app.uid);
+ if (!replacingPid) {
+ removeProcessNameLocked(app.processName, app.uid);
+ }
if (mHeavyWeightProcess == app) {
mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
mHeavyWeightProcess.userId, 0));
@@ -21279,7 +21292,7 @@
// Ignore exceptions.
}
}
- cleanUpApplicationRecordLocked(app, false, true, -1);
+ cleanUpApplicationRecordLocked(app, false, true, -1, false /*replacingPid*/);
mRemovedProcesses.remove(i);
if (app.persistent) {
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index d02fbbf..219e095 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -304,6 +304,11 @@
boolean didSomething = false;
final BroadcastRecord br = mPendingBroadcast;
if (br != null && br.curApp.pid == app.pid) {
+ if (br.curApp != app) {
+ Slog.e(TAG, "App mismatch when sending pending broadcast to "
+ + app.processName + ", intended target is " + br.curApp.processName);
+ return false;
+ }
try {
mPendingBroadcast = null;
processCurBroadcastLocked(br, app);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 085de43..9ca609f 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -1050,6 +1050,8 @@
builder.setTicker(title);
builder.setContentTitle(title);
builder.setContentText(body);
+ builder.setDefaults(Notification.DEFAULT_ALL);
+ builder.setPriority(Notification.PRIORITY_HIGH);
final Intent snoozeIntent = buildSnoozeWarningIntent(policy.template);
builder.setDeleteIntent(PendingIntent.getBroadcast(
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index c78e94b..d3dab44 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -517,6 +517,11 @@
// placement for this window during this period, one or more frame will
// show up with wrong position or scale.
win.mWinAnimator.mAnimating = false;
+
+ if (win.mDestroying) {
+ win.mDestroying = false;
+ mService.mDestroySurface.remove(win);
+ }
}
}
requestUpdateWallpaperIfNeeded();
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index c26c078..4c9211a 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -1462,7 +1462,7 @@
mObscured = true;
}
- if (w.mHasSurface) {
+ if (w.mHasSurface && canBeSeen) {
if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
mHoldScreen = w.mSession;
mHoldScreenWindow = w;
@@ -1485,43 +1485,39 @@
}
final int type = attrs.type;
- if (canBeSeen
- && (type == TYPE_SYSTEM_DIALOG
- || type == TYPE_SYSTEM_ERROR
- || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) {
+ if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
+ || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
mSyswin = true;
}
- if (canBeSeen) {
- // This function assumes that the contents of the default display are
- // processed first before secondary displays.
- final DisplayContent displayContent = w.getDisplayContent();
- if (displayContent != null && displayContent.isDefaultDisplay) {
- // While a dream or keyguard is showing, obscure ordinary application
- // content on secondary displays (by forcibly enabling mirroring unless
- // there is other content we want to show) but still allow opaque
- // keyguard dialogs to be shown.
- if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
- mObscureApplicationContentOnSecondaryDisplays = true;
- }
- mDisplayHasContent = true;
- } else if (displayContent != null &&
- (!mObscureApplicationContentOnSecondaryDisplays
- || (mObscured && type == TYPE_KEYGUARD_DIALOG))) {
- // Allow full screen keyguard presentation dialogs to be seen.
- mDisplayHasContent = true;
+ // This function assumes that the contents of the default display are
+ // processed first before secondary displays.
+ final DisplayContent displayContent = w.getDisplayContent();
+ if (displayContent != null && displayContent.isDefaultDisplay) {
+ // While a dream or keyguard is showing, obscure ordinary application
+ // content on secondary displays (by forcibly enabling mirroring unless
+ // there is other content we want to show) but still allow opaque
+ // keyguard dialogs to be shown.
+ if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+ mObscureApplicationContentOnSecondaryDisplays = true;
}
- if (mPreferredRefreshRate == 0
- && w.mAttrs.preferredRefreshRate != 0) {
- mPreferredRefreshRate = w.mAttrs.preferredRefreshRate;
- }
- if (mPreferredModeId == 0
- && w.mAttrs.preferredDisplayModeId != 0) {
- mPreferredModeId = w.mAttrs.preferredDisplayModeId;
- }
- if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) {
- mSustainedPerformanceModeCurrent = true;
- }
+ mDisplayHasContent = true;
+ } else if (displayContent != null &&
+ (!mObscureApplicationContentOnSecondaryDisplays
+ || (mObscured && type == TYPE_KEYGUARD_DIALOG))) {
+ // Allow full screen keyguard presentation dialogs to be seen.
+ mDisplayHasContent = true;
+ }
+ if (mPreferredRefreshRate == 0
+ && w.mAttrs.preferredRefreshRate != 0) {
+ mPreferredRefreshRate = w.mAttrs.preferredRefreshRate;
+ }
+ if (mPreferredModeId == 0
+ && w.mAttrs.preferredDisplayModeId != 0) {
+ mPreferredModeId = w.mAttrs.preferredDisplayModeId;
+ }
+ if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) {
+ mSustainedPerformanceModeCurrent = true;
}
}
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 541be3d..7303358 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -16,17 +16,12 @@
package com.android.server;
-import static android.content.Intent.ACTION_UID_REMOVED;
-import static android.content.Intent.EXTRA_UID;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.net.NetworkPolicy.CYCLE_NONE;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
-import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
-import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
import static android.net.NetworkPolicyManager.computeNextCycleBoundary;
import static android.net.TrafficStats.KB_IN_BYTES;
@@ -34,28 +29,36 @@
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.Time.TIMEZONE_UTC;
+
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING;
-import static org.easymock.EasyMock.anyInt;
-import static org.easymock.EasyMock.anyLong;
-import static org.easymock.EasyMock.aryEq;
-import static org.easymock.EasyMock.capture;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.eq;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.isA;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
import android.app.IActivityManager;
import android.app.INotificationManager;
-import android.app.IProcessObserver;
+import android.app.IUidObserver;
import android.app.Notification;
+import android.app.usage.UsageStatsManagerInternal;
+import android.content.Context;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
-import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver;
import android.net.INetworkPolicyListener;
@@ -69,38 +72,39 @@
import android.net.NetworkTemplate;
import android.os.Binder;
import android.os.INetworkManagementService;
-import android.os.MessageQueue.IdleHandler;
+import android.os.PowerManagerInternal;
import android.os.UserHandle;
import android.test.AndroidTestCase;
-import android.test.mock.MockPackageManager;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.Suppress;
import android.text.format.Time;
+import android.util.Log;
import android.util.TrustedTime;
+import com.android.server.net.NetworkPolicyManagerInternal;
import com.android.server.net.NetworkPolicyManagerService;
+
+import libcore.io.IoUtils;
+
import com.google.common.util.concurrent.AbstractFuture;
-import org.easymock.Capture;
-import org.easymock.EasyMock;
-import org.easymock.IAnswer;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import java.io.File;
-import java.util.Calendar;
+import java.util.ArrayList;
import java.util.LinkedHashSet;
-import java.util.TimeZone;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import java.util.logging.Handler;
-
-import libcore.io.IoUtils;
/**
* Tests for {@link NetworkPolicyManagerService}.
*/
-@LargeTest
public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
private static final String TAG = "NetworkPolicyManagerServiceTest";
@@ -112,20 +116,22 @@
private BroadcastInterceptingContext mServiceContext;
private File mPolicyDir;
+ private List<Class<?>> mLocalServices = new ArrayList<>();
- private IActivityManager mActivityManager;
- private INetworkStatsService mStatsService;
- private INetworkManagementService mNetworkManager;
- private INetworkPolicyListener mPolicyListener;
- private TrustedTime mTime;
- private IConnectivityManager mConnManager;
- private INotificationManager mNotifManager;
+ private @Mock IActivityManager mActivityManager;
+ private @Mock INetworkStatsService mStatsService;
+ private @Mock INetworkManagementService mNetworkManager;
+ private @Mock TrustedTime mTime;
+ private @Mock IConnectivityManager mConnManager;
+ private @Mock INotificationManager mNotifManager;
+ private @Mock UsageStatsManagerInternal mUsageStats;
+ private @Mock PackageManager mPackageManager;
- private NetworkPolicyManagerService mService;
- private IProcessObserver mProcessObserver;
+ private IUidObserver mUidObserver;
private INetworkManagementEventObserver mNetworkObserver;
- private Binder mStubBinder = new Binder();
+ private NetworkPolicyListenerAnswer mPolicyListener;
+ private NetworkPolicyManagerService mService;
private long mStartTime;
private long mElapsedRealtime;
@@ -138,39 +144,22 @@
private static final int UID_A = UserHandle.getUid(USER_ID, APP_ID_A);
private static final int UID_B = UserHandle.getUid(USER_ID, APP_ID_B);
- private static final int PID_1 = 400;
- private static final int PID_2 = 401;
- private static final int PID_3 = 402;
+ private static final String PKG_NAME_A = "name.is.A,pkg.A";
- public void _setUp() throws Exception {
+ public void setUp() throws Exception {
super.setUp();
+ MockitoAnnotations.initMocks(this);
+
+ final Context context = getContext();
+
setCurrentTimeMillis(TEST_START);
// intercept various broadcasts, and pretend that uids have packages
- mServiceContext = new BroadcastInterceptingContext(getContext()) {
+ mServiceContext = new BroadcastInterceptingContext(context) {
@Override
public PackageManager getPackageManager() {
- return new MockPackageManager() {
- @Override
- public String[] getPackagesForUid(int uid) {
- return new String[] { "com.example" };
- }
-
- @Override
- public PackageInfo getPackageInfo(String packageName, int flags) {
- final PackageInfo info = new PackageInfo();
- final Signature signature;
- if ("android".equals(packageName)) {
- signature = new Signature("F00D");
- } else {
- signature = new Signature("DEAD");
- }
- info.signatures = new Signature[] { signature };
- return info;
- }
-
- };
+ return mPackageManager;
}
@Override
@@ -179,54 +168,69 @@
}
};
- mPolicyDir = getContext().getFilesDir();
+ mPolicyDir = context.getFilesDir();
if (mPolicyDir.exists()) {
IoUtils.deleteContents(mPolicyDir);
}
- mActivityManager = createMock(IActivityManager.class);
- mStatsService = createMock(INetworkStatsService.class);
- mNetworkManager = createMock(INetworkManagementService.class);
- mPolicyListener = createMock(INetworkPolicyListener.class);
- mTime = createMock(TrustedTime.class);
- mConnManager = createMock(IConnectivityManager.class);
- mNotifManager = createMock(INotificationManager.class);
+ doAnswer(new Answer<Void>() {
- mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager,
- mStatsService, mNetworkManager, mTime, mPolicyDir, true);
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ mUidObserver = (IUidObserver) invocation.getArguments()[0];
+ Log.d(TAG, "set mUidObserver to " + mUidObserver);
+ return null;
+ }
+ }).when(mActivityManager).registerUidObserver(any(), anyInt());
+
+ addLocalServiceMock(PowerManagerInternal.class);
+ addLocalServiceMock(DeviceIdleController.LocalService.class);
+ addLocalServiceMock(UsageStatsManagerInternal.class, mUsageStats);
+
+ mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mStatsService,
+ mNetworkManager, mTime, mPolicyDir, true);
mService.bindConnectivityManager(mConnManager);
mService.bindNotificationManager(mNotifManager);
+ mPolicyListener = new NetworkPolicyListenerAnswer(mService);
- // RemoteCallbackList needs a binder to use as key
- expect(mPolicyListener.asBinder()).andReturn(mStubBinder).atLeastOnce();
- replay();
- mService.registerListener(mPolicyListener);
- verifyAndReset();
+ // Sets some common expectations.
+ when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenAnswer(
+ new Answer<PackageInfo>() {
- // catch IProcessObserver during systemReady()
- final Capture<IProcessObserver> processObserver = new Capture<IProcessObserver>();
- mActivityManager.registerProcessObserver(capture(processObserver));
- expectLastCall().atLeastOnce();
-
- // catch INetworkManagementEventObserver during systemReady()
- final Capture<INetworkManagementEventObserver> networkObserver = new Capture<
- INetworkManagementEventObserver>();
- mNetworkManager.registerObserver(capture(networkObserver));
- expectLastCall().atLeastOnce();
-
- expect(mNetworkManager.isBandwidthControlEnabled()).andReturn(true).atLeastOnce();
+ @Override
+ public PackageInfo answer(InvocationOnMock invocation) throws Throwable {
+ final String packageName = (String) invocation.getArguments()[0];
+ final PackageInfo info = new PackageInfo();
+ final Signature signature;
+ if ("android".equals(packageName)) {
+ signature = new Signature("F00D");
+ } else {
+ signature = new Signature("DEAD");
+ }
+ info.signatures = new Signature[] {
+ signature
+ };
+ return info;
+ }
+ });
+ when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
+ .thenReturn(new ApplicationInfo());
+ when(mPackageManager.getPackagesForUid(UID_A)).thenReturn(new String[] {PKG_NAME_A});
+ when(mUsageStats.getIdleUidsForUser(anyInt())).thenReturn(new int[]{});
+ when(mNetworkManager.isBandwidthControlEnabled()).thenReturn(true);
expectCurrentTime();
- replay();
+ // Prepare NPMS.
mService.systemReady();
- verifyAndReset();
- mProcessObserver = processObserver.getValue();
+ // catch INetworkManagementEventObserver during systemReady()
+ ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
+ ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
+ verify(mNetworkManager).registerObserver(networkObserver.capture());
mNetworkObserver = networkObserver.getValue();
-
}
- public void _tearDown() throws Exception {
+ public void tearDown() throws Exception {
for (File file : mPolicyDir.listFiles()) {
file.delete();
}
@@ -236,170 +240,51 @@
mActivityManager = null;
mStatsService = null;
- mPolicyListener = null;
mTime = null;
mService = null;
- mProcessObserver = null;
+
+ // TODO: must remove services, otherwise next test will fail.
+ // JUnit4 would avoid that hack by using a static setup.
+ removeLocalServiceMocks();
+
+ // Added by NetworkPolicyManagerService's constructor.
+ LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
super.tearDown();
}
- @Suppress
- public void testPolicyChangeTriggersBroadcast() throws Exception {
+ // NOTE: testPolicyChangeTriggersListener() and testUidForeground() are too superficial, they
+ // don't check for side-effects (like calls to NetworkManagementService) neither cover all
+ // different modes (Data Saver, Battery Saver, Doze, App idle, etc...).
+ // These scenarios are extensively tested on CTS' HostsideRestrictBackgroundNetworkTests.
+
+ public void testPolicyChangeTriggersListener() throws Exception {
+ mPolicyListener.expect().onRestrictBackgroundBlacklistChanged(anyInt(), anyBoolean());
+
mService.setUidPolicy(APP_ID_A, POLICY_NONE);
-
- // change background policy and expect broadcast
- final Future<Intent> backgroundChanged = mServiceContext.nextBroadcastIntent(
- ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
-
mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
- backgroundChanged.get();
+ mPolicyListener.waitAndVerify().onRestrictBackgroundBlacklistChanged(APP_ID_A, true);
}
- @Suppress
- public void testPidForegroundCombined() throws Exception {
- IdleFuture idle;
-
- // push all uid into background
- idle = expectIdle();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
- mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
- mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, false);
- idle.get();
+ public void testUidForeground() throws Exception {
+ // push all uids into background
+ mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE);
+ mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_SERVICE);
assertFalse(mService.isUidForeground(UID_A));
assertFalse(mService.isUidForeground(UID_B));
- // push one of the shared pids into foreground
- idle = expectIdle();
- mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
- idle.get();
+ // push one of the uids into foreground
+ mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_TOP);
assertTrue(mService.isUidForeground(UID_A));
assertFalse(mService.isUidForeground(UID_B));
// and swap another uid into foreground
- idle = expectIdle();
- mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
- mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, true);
- idle.get();
+ mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE);
+ mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_TOP);
assertFalse(mService.isUidForeground(UID_A));
assertTrue(mService.isUidForeground(UID_B));
-
- // push both pid into foreground
- idle = expectIdle();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
- mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
- idle.get();
- assertTrue(mService.isUidForeground(UID_A));
-
- // pull one out, should still be foreground
- idle = expectIdle();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
- idle.get();
- assertTrue(mService.isUidForeground(UID_A));
-
- // pull final pid out, should now be background
- idle = expectIdle();
- mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
- idle.get();
- assertFalse(mService.isUidForeground(UID_A));
- }
-
- @Suppress
- public void testPolicyNone() throws Exception {
- Future<Void> future;
-
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, true);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
- future.get();
- verifyAndReset();
-
- // POLICY_NONE should RULE_ALLOW in foreground
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, true);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mService.setUidPolicy(APP_ID_A, POLICY_NONE);
- future.get();
- verifyAndReset();
-
- // POLICY_NONE should RULE_ALLOW in background
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
- future.get();
- verifyAndReset();
- }
-
- @Suppress
- public void testPolicyReject() throws Exception {
- Future<Void> future;
-
- // POLICY_REJECT should RULE_ALLOW in background
- expectSetUidMeteredNetworkBlacklist(UID_A, true);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
- replay();
- mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
- future.get();
- verifyAndReset();
-
- // POLICY_REJECT should RULE_ALLOW in foreground
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, true);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
- future.get();
- verifyAndReset();
-
- // POLICY_REJECT should RULE_REJECT in background
- expectSetUidMeteredNetworkBlacklist(UID_A, true);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
- replay();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
- future.get();
- verifyAndReset();
- }
-
- @Suppress
- public void testPolicyRejectAddRemove() throws Exception {
- Future<Void> future;
-
- // POLICY_NONE should have RULE_ALLOW in background
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
- mService.setUidPolicy(APP_ID_A, POLICY_NONE);
- future.get();
- verifyAndReset();
-
- // adding POLICY_REJECT should cause RULE_REJECT
- expectSetUidMeteredNetworkBlacklist(UID_A, true);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
- replay();
- mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
- future.get();
- verifyAndReset();
-
- // removing POLICY_REJECT should return us to RULE_ALLOW
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mService.setUidPolicy(APP_ID_A, POLICY_NONE);
- future.get();
- verifyAndReset();
}
public void testLastCycleBoundaryThisMonth() throws Exception {
@@ -544,11 +429,9 @@
assertTimeEquals(expectedCycle, actualCycle);
}
- @Suppress
public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
NetworkState[] state = null;
NetworkStats stats = null;
- Future<Void> future;
final long TIME_FEB_15 = 1171497600000L;
final long TIME_MAR_10 = 1173484800000L;
@@ -559,75 +442,39 @@
// first, pretend that wifi network comes online. no policy active,
// which means we shouldn't push limit to interface.
state = new NetworkState[] { buildWifi() };
- expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+ when(mConnManager.getAllNetworkState()).thenReturn(state);
expectCurrentTime();
- expectClearNotifications();
- expectAdvisePersistThreshold();
- future = expectMeteredIfacesChanged();
- replay();
+ mPolicyListener.expect().onMeteredIfacesChanged(any());
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
- future.get();
- verifyAndReset();
+ mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any());
// now change cycle to be on 15th, and test in early march, to verify we
// pick cycle day in previous month.
- expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+ when(mConnManager.getAllNetworkState()).thenReturn(state);
expectCurrentTime();
// pretend that 512 bytes total have happened
stats = new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 256L, 2L, 256L, 2L);
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, true);
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
+ .thenReturn(stats.getTotalBytes());
- // TODO: consider making strongly ordered mock
- expectRemoveInterfaceQuota(TEST_IFACE);
- expectSetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512);
-
- expectClearNotifications();
- expectAdvisePersistThreshold();
- future = expectMeteredIfacesChanged(TEST_IFACE);
-
- replay();
+ mPolicyListener.expect().onMeteredIfacesChanged(any());
setNetworkPolicies(new NetworkPolicy(
sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
- future.get();
- verifyAndReset();
+ mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
+ // TODO: consider making strongly ordered mock
+ verifyPolicyDataEnable(TYPE_WIFI, true);
+ verifyRemoveInterfaceQuota(TEST_IFACE);
+ verifySetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512);
}
- @Suppress
- public void testUidRemovedPolicyCleared() throws Exception {
- Future<Void> future;
-
- // POLICY_REJECT should RULE_REJECT in background
- expectSetUidMeteredNetworkBlacklist(UID_A, true);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
- replay();
- mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
- future.get();
- verifyAndReset();
-
- // uninstall should clear RULE_REJECT
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- final Intent intent = new Intent(ACTION_UID_REMOVED);
- intent.putExtra(EXTRA_UID, UID_A);
- mServiceContext.sendBroadcast(intent);
- future.get();
- verifyAndReset();
- }
-
- @Suppress
public void testOverWarningLimitNotification() throws Exception {
NetworkState[] state = null;
NetworkStats stats = null;
- Future<Void> future;
- Future<String> tagFuture;
+ Future<String> tagFuture = null;
final long TIME_FEB_15 = 1171497600000L;
final long TIME_MAR_10 = 1173484800000L;
@@ -642,20 +489,15 @@
{
expectCurrentTime();
- expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, true);
+ when(mConnManager.getAllNetworkState()).thenReturn(state);
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+ currentTimeMillis())).thenReturn(stats.getTotalBytes());
- expectClearNotifications();
- expectAdvisePersistThreshold();
- future = expectMeteredIfacesChanged();
-
- replay();
+ mPolicyListener.expect().onMeteredIfacesChanged(any());
setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1
* MB_IN_BYTES, 2 * MB_IN_BYTES, false));
- future.get();
- verifyAndReset();
+ mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any());
+ verifyPolicyDataEnable(TYPE_WIFI, true);
}
// bring up wifi network
@@ -666,22 +508,17 @@
{
expectCurrentTime();
- expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, true);
+ when(mConnManager.getAllNetworkState()).thenReturn(state);
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+ currentTimeMillis())).thenReturn(stats.getTotalBytes());
- expectRemoveInterfaceQuota(TEST_IFACE);
- expectSetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
-
- expectClearNotifications();
- expectAdvisePersistThreshold();
- future = expectMeteredIfacesChanged(TEST_IFACE);
-
- replay();
+ mPolicyListener.expect().onMeteredIfacesChanged(any());
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
- future.get();
- verifyAndReset();
+ mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
+ verifyPolicyDataEnable(TYPE_WIFI, true);
+ verifyRemoveInterfaceQuota(TEST_IFACE);
+ verifySetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
}
// go over warning, which should kick notification
@@ -691,18 +528,15 @@
{
expectCurrentTime();
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, true);
-
- expectForceUpdate();
- expectClearNotifications();
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+ currentTimeMillis())).thenReturn(stats.getTotalBytes());
tagFuture = expectEnqueueNotification();
- replay();
mNetworkObserver.limitReached(null, TEST_IFACE);
+
assertNotificationType(TYPE_WARNING, tagFuture.get());
- verifyAndReset();
+ verifyPolicyDataEnable(TYPE_WIFI, true);
+
}
// go over limit, which should kick notification and dialog
@@ -712,18 +546,14 @@
{
expectCurrentTime();
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, false);
-
- expectForceUpdate();
- expectClearNotifications();
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+ currentTimeMillis())).thenReturn(stats.getTotalBytes());
tagFuture = expectEnqueueNotification();
- replay();
mNetworkObserver.limitReached(null, TEST_IFACE);
+
assertNotificationType(TYPE_LIMIT, tagFuture.get());
- verifyAndReset();
+ verifyPolicyDataEnable(TYPE_WIFI, false);
}
// now snooze policy, which should remove quota
@@ -731,35 +561,27 @@
{
expectCurrentTime();
- expect(mConnManager.getAllNetworkState()).andReturn(state).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
- // still restricted.
- expectRemoveInterfaceQuota(TEST_IFACE);
- expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
- expectAdvisePersistThreshold();
- expectMeteredIfacesChanged(TEST_IFACE);
-
- future = expectClearNotifications();
+ when(mConnManager.getAllNetworkState()).thenReturn(state);
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+ currentTimeMillis())).thenReturn(stats.getTotalBytes());
tagFuture = expectEnqueueNotification();
- replay();
+ mPolicyListener.expect().onMeteredIfacesChanged(any());
mService.snoozeLimit(sTemplateWifi);
+ mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get());
- future.get();
- verifyAndReset();
+ // snoozed interface still has high quota so background data is
+ // still restricted.
+ verifyRemoveInterfaceQuota(TEST_IFACE);
+ verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
+ verifyPolicyDataEnable(TYPE_WIFI, true);
}
}
- @Suppress
public void testMeteredNetworkWithoutLimit() throws Exception {
NetworkState[] state = null;
NetworkStats stats = null;
- Future<Void> future;
- Future<String> tagFuture;
final long TIME_FEB_15 = 1171497600000L;
final long TIME_MAR_10 = 1173484800000L;
@@ -774,24 +596,19 @@
{
expectCurrentTime();
- expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, true);
+ when(mConnManager.getAllNetworkState()).thenReturn(state);
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+ currentTimeMillis())).thenReturn(stats.getTotalBytes());
- expectRemoveInterfaceQuota(TEST_IFACE);
- expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
-
- expectClearNotifications();
- expectAdvisePersistThreshold();
- future = expectMeteredIfacesChanged(TEST_IFACE);
-
- replay();
+ mPolicyListener.expect().onMeteredIfacesChanged(any());
setNetworkPolicies(new NetworkPolicy(
sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED,
true));
- future.get();
- verifyAndReset();
+ mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
+ verifyPolicyDataEnable(TYPE_WIFI, true);
+ verifyRemoveInterfaceQuota(TEST_IFACE);
+ verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
}
}
@@ -814,87 +631,36 @@
}
private void expectCurrentTime() throws Exception {
- expect(mTime.forceRefresh()).andReturn(false).anyTimes();
- expect(mTime.hasCache()).andReturn(true).anyTimes();
- expect(mTime.currentTimeMillis()).andReturn(currentTimeMillis()).anyTimes();
- expect(mTime.getCacheAge()).andReturn(0L).anyTimes();
- expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
- }
-
- private void expectForceUpdate() throws Exception {
- mStatsService.forceUpdate();
- expectLastCall().atLeastOnce();
- }
-
- private Future<Void> expectClearNotifications() throws Exception {
- final FutureAnswer future = new FutureAnswer();
- mNotifManager.cancelNotificationWithTag(
- isA(String.class), isA(String.class), anyInt(), anyInt());
- expectLastCall().andAnswer(future).anyTimes();
- return future;
+ when(mTime.forceRefresh()).thenReturn(false);
+ when(mTime.hasCache()).thenReturn(true);
+ when(mTime.currentTimeMillis()).thenReturn(currentTimeMillis());
+ when(mTime.getCacheAge()).thenReturn(0L);
+ when(mTime.getCacheCertainty()).thenReturn(0L);
}
private Future<String> expectEnqueueNotification() throws Exception {
- final FutureCapture<String> tag = new FutureCapture<String>();
- mNotifManager.enqueueNotificationWithTag(isA(String.class), isA(String.class),
- capture(tag.capture), anyInt(),
- isA(Notification.class), isA(int[].class), UserHandle.myUserId());
- return tag;
+ final FutureAnswer<String> futureAnswer = new FutureAnswer<String>(2);
+ doAnswer(futureAnswer).when(mNotifManager).enqueueNotificationWithTag(
+ anyString(), anyString(), anyString() /* capture here (index 2)*/,
+ anyInt(), isA(Notification.class), isA(int[].class), anyInt());
+ return futureAnswer;
}
- private void expectSetInterfaceQuota(String iface, long quotaBytes) throws Exception {
- mNetworkManager.setInterfaceQuota(iface, quotaBytes);
- expectLastCall().atLeastOnce();
+ private void verifySetInterfaceQuota(String iface, long quotaBytes) throws Exception {
+ verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(iface, quotaBytes);
}
- private void expectRemoveInterfaceQuota(String iface) throws Exception {
- mNetworkManager.removeInterfaceQuota(iface);
- expectLastCall().atLeastOnce();
+ private void verifyRemoveInterfaceQuota(String iface) throws Exception {
+ verify(mNetworkManager, atLeastOnce()).removeInterfaceQuota(iface);
}
- private void expectSetInterfaceAlert(String iface, long alertBytes) throws Exception {
- mNetworkManager.setInterfaceAlert(iface, alertBytes);
- expectLastCall().atLeastOnce();
- }
-
- private void expectRemoveInterfaceAlert(String iface) throws Exception {
- mNetworkManager.removeInterfaceAlert(iface);
- expectLastCall().atLeastOnce();
- }
-
- private void expectSetUidMeteredNetworkBlacklist(int uid, boolean rejectOnQuotaInterfaces)
- throws Exception {
- mNetworkManager.setUidMeteredNetworkBlacklist(uid, rejectOnQuotaInterfaces);
- expectLastCall().atLeastOnce();
- }
-
- private void expectSetUidForeground(int uid, boolean uidForeground) throws Exception {
- mStatsService.setUidForeground(uid, uidForeground);
- expectLastCall().atLeastOnce();
- }
-
- private Future<Void> expectRulesChanged(int uid, int policy) throws Exception {
- final FutureAnswer future = new FutureAnswer();
- mPolicyListener.onUidRulesChanged(eq(uid), eq(policy));
- expectLastCall().andAnswer(future);
- return future;
- }
-
- private Future<Void> expectMeteredIfacesChanged(String... ifaces) throws Exception {
- final FutureAnswer future = new FutureAnswer();
- mPolicyListener.onMeteredIfacesChanged(aryEq(ifaces));
- expectLastCall().andAnswer(future);
- return future;
- }
-
- private Future<Void> expectPolicyDataEnable(int type, boolean enabled) throws Exception {
+ private Future<Void> verifyPolicyDataEnable(int type, boolean enabled) throws Exception {
// TODO: bring back this test
return null;
}
- private void expectAdvisePersistThreshold() throws Exception {
- mStatsService.advisePersistThreshold(anyLong());
- expectLastCall().anyTimes();
+ private void verifyAdvisePersistThreshold() throws Exception {
+ verify(mStatsService).advisePersistThreshold(anyLong());
}
private static class TestAbstractFuture<T> extends AbstractFuture<T> {
@@ -908,50 +674,21 @@
}
}
- private static class FutureAnswer extends TestAbstractFuture<Void> implements IAnswer<Void> {
+ private static class FutureAnswer<T> extends TestAbstractFuture<T> implements Answer<Void> {
+ private final int index;
+
+ FutureAnswer(int index) {
+ this.index = index;
+ }
@Override
- public Void answer() {
- set(null);
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ @SuppressWarnings("unchecked")
+ T captured = (T) invocation.getArguments()[index];
+ set(captured);
return null;
}
}
- private static class FutureCapture<T> extends TestAbstractFuture<T> {
- public Capture<T> capture = new Capture<T>() {
- @Override
- public void setValue(T value) {
- super.setValue(value);
- set(value);
- }
- };
- }
-
- private static class IdleFuture extends AbstractFuture<Void> implements IdleHandler {
- @Override
- public Void get() throws InterruptedException, ExecutionException {
- try {
- return get(5, TimeUnit.SECONDS);
- } catch (TimeoutException e) {
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public boolean queueIdle() {
- set(null);
- return false;
- }
- }
-
- /**
- * Wait until {@link #mService} internal {@link Handler} is idle.
- */
- private IdleFuture expectIdle() {
- final IdleFuture future = new IdleFuture();
- mService.addIdleHandler(future);
- return future;
- }
-
private static void assertTimeEquals(long expected, long actual) {
if (expected != actual) {
fail("expected " + formatTime(expected) + " but was actually " + formatTime(actual));
@@ -979,7 +716,7 @@
}
private static void assertNotificationType(int expected, String actualTag) {
- assertEquals(
+ assertEquals("notification type mismatch for '" + actualTag +"'",
Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
}
@@ -1000,15 +737,78 @@
mElapsedRealtime += duration;
}
- private void replay() {
- EasyMock.replay(mActivityManager, mStatsService, mPolicyListener, mNetworkManager, mTime,
- mConnManager, mNotifManager);
+ /**
+ * Creates a mock and registers it to {@link LocalServices}.
+ */
+ private <T> T addLocalServiceMock(Class<T> clazz) {
+ final T mock = mock(clazz);
+ return addLocalServiceMock(clazz, mock);
}
- private void verifyAndReset() {
- EasyMock.verify(mActivityManager, mStatsService, mPolicyListener, mNetworkManager, mTime,
- mConnManager, mNotifManager);
- EasyMock.reset(mActivityManager, mStatsService, mPolicyListener, mNetworkManager, mTime,
- mConnManager, mNotifManager);
+ /**
+ * Registers a mock to {@link LocalServices}.
+ */
+ private <T> T addLocalServiceMock(Class<T> clazz, T mock) {
+ LocalServices.addService(clazz, mock);
+ mLocalServices.add(clazz);
+ return mock;
+ }
+
+ /**
+ * Unregisters all mocks from {@link LocalServices}.
+ */
+ private void removeLocalServiceMocks() {
+ for (Class<?> clazz : mLocalServices) {
+ Log.d(TAG, "removeLocalServiceMock(): " + clazz.getName());
+ LocalServices.removeServiceForTest(clazz);
+ }
+ mLocalServices.clear();
+ }
+
+ /**
+ * Custom Mockito answer used to verify async {@link INetworkPolicyListener} calls.
+ *
+ * <p>Typical usage:
+ * <pre><code>
+ * mPolicyListener.expect().someCallback(any());
+ * // do something on objects under test
+ * mPolicyListener.waitAndVerify().someCallback(eq(expectedValue));
+ * </code></pre>
+ */
+ final class NetworkPolicyListenerAnswer implements Answer<Void> {
+ private CountDownLatch latch;
+ private final INetworkPolicyListener listener;
+
+ NetworkPolicyListenerAnswer(NetworkPolicyManagerService service) {
+ this.listener = mock(INetworkPolicyListener.class);
+ // RemoteCallbackList needs a binder to use as key
+ when(listener.asBinder()).thenReturn(new Binder());
+ service.registerListener(listener);
+ }
+
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Log.d(TAG,"counting down on answer: " + invocation);
+ latch.countDown();
+ return null;
+ }
+
+ INetworkPolicyListener expect() {
+ assertNull("expect() called before waitAndVerify()", latch);
+ latch = new CountDownLatch(1);
+ return doAnswer(this).when(listener);
+ }
+
+ INetworkPolicyListener waitAndVerify() {
+ assertNotNull("waitAndVerify() called before expect()", latch);
+ try {
+ assertTrue("callback not called in 5 seconds", latch.await(5, TimeUnit.SECONDS));
+ } catch (InterruptedException e) {
+ fail("Thread interrupted before callback called");
+ } finally {
+ latch = null;
+ }
+ return verify(listener, atLeastOnce());
+ }
}
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 8560651..efd479f 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -563,6 +563,7 @@
mAccessoryModeRequestTime + ACCESSORY_REQUEST_TIMEOUT;
if (mConfigured && enteringAccessoryMode) {
+ mAccessoryModeRequestTime = 0;
// successfully entered accessory mode
if (mAccessoryStrings != null) {
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index d7d4e84..f5e422d 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -212,6 +212,20 @@
*/
public static final int MAXIMUM_NUMBER_OF_CALLS_REACHED = 53;
+ /**
+ * The call was terminated because cellular data has been disabled.
+ * Used when in a video call and the user disables cellular data via the settings.
+ * {@hide}
+ */
+ public static final int DATA_DISABLED = 54;
+
+ /**
+ * The call was terminated because the data policy has disabled cellular data.
+ * Used when in a video call and the user has exceeded the device data limit.
+ * {@hide}
+ */
+ public static final int DATA_LIMIT_REACHED = 55;
+
//*********************************************************************************************
// When adding a disconnect type:
// 1) Please assign the new type the next id value below.
@@ -220,14 +234,14 @@
// 4) Update toString() with the newly added disconnect type.
// 5) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause.
//
- // NextId: 54
+ // NextId: 56
//*********************************************************************************************
/** Smallest valid value for call disconnect codes. */
public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
/** Largest valid value for call disconnect codes. */
- public static final int MAXIMUM_VALID_VALUE = MAXIMUM_NUMBER_OF_CALLS_REACHED;
+ public static final int MAXIMUM_VALID_VALUE = DATA_LIMIT_REACHED;
/** Private constructor to avoid class instantiation. */
private DisconnectCause() {
@@ -343,6 +357,10 @@
return "ANSWERED_ELSEWHERE";
case MAXIMUM_NUMBER_OF_CALLS_REACHED:
return "MAXIMUM_NUMER_OF_CALLS_REACHED";
+ case DATA_DISABLED:
+ return "DATA_DISABLED";
+ case DATA_LIMIT_REACHED:
+ return "DATA_LIMIT_REACHED";
default:
return "INVALID: " + cause;
}
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java
index 408ad31..56b8822 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.java
+++ b/telephony/java/com/android/ims/ImsReasonInfo.java
@@ -298,6 +298,16 @@
public static final int CODE_REMOTE_CALL_DECLINE = 1404;
/**
+ * Indicates the call was disconnected due to the user reaching their data limit.
+ */
+ public static final int CODE_DATA_LIMIT_REACHED = 1405;
+
+ /**
+ * Indicates the call was disconnected due to the user disabling cellular data.
+ */
+ public static final int CODE_DATA_DISABLED = 1406;
+
+ /**
* Network string error messages.
* mExtraMessage may have these values.
*/
diff --git a/tools/aapt/ApkBuilder.h b/tools/aapt/ApkBuilder.h
index 0d7f06b..5d3abc6 100644
--- a/tools/aapt/ApkBuilder.h
+++ b/tools/aapt/ApkBuilder.h
@@ -32,7 +32,7 @@
class ApkBuilder : public android::RefBase {
public:
- ApkBuilder(const sp<WeakResourceFilter>& configFilter);
+ explicit ApkBuilder(const sp<WeakResourceFilter>& configFilter);
/**
* Tells the builder to generate a separate APK for resources that
diff --git a/tools/aapt/CacheUpdater.h b/tools/aapt/CacheUpdater.h
index 10a1bbc..6fa96d6 100644
--- a/tools/aapt/CacheUpdater.h
+++ b/tools/aapt/CacheUpdater.h
@@ -51,7 +51,7 @@
class SystemCacheUpdater : public CacheUpdater {
public:
// Constructor to set bundle to pass to preProcessImage
- SystemCacheUpdater (Bundle* b)
+ explicit SystemCacheUpdater (Bundle* b)
: bundle(b) { };
// Make sure all the directories along this path exist
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index cbad4b9..d80aaba 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -248,7 +248,7 @@
}
static void printResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree,
- uint32_t attrRes, String8 attrLabel, String8* outError)
+ uint32_t attrRes, const String8& attrLabel, String8* outError)
{
Res_value value;
AaptXml::getResolvedResourceAttribute(resTable, tree, attrRes, &value, outError);
@@ -399,7 +399,7 @@
ResTable::normalizeForOutput(reason.string()).string());
}
-Vector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost,
+Vector<String8> getNfcAidCategories(AssetManager& assets, const String8& xmlPath, bool offHost,
String8 *outError = NULL)
{
Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER);
diff --git a/tools/aapt/ConfigDescription.h b/tools/aapt/ConfigDescription.h
index 4f999a2..09430f2 100644
--- a/tools/aapt/ConfigDescription.h
+++ b/tools/aapt/ConfigDescription.h
@@ -29,7 +29,7 @@
size = sizeof(android::ResTable_config);
}
- ConfigDescription(const android::ResTable_config&o) {
+ ConfigDescription(const android::ResTable_config&o) { // NOLINT(implicit)
*static_cast<android::ResTable_config*>(this) = o;
size = sizeof(android::ResTable_config);
}
diff --git a/tools/aapt/CrunchCache.cpp b/tools/aapt/CrunchCache.cpp
index 0d574cf..7b8a576 100644
--- a/tools/aapt/CrunchCache.cpp
+++ b/tools/aapt/CrunchCache.cpp
@@ -94,7 +94,7 @@
delete dw;
}
-bool CrunchCache::needsUpdating(String8 relativePath) const
+bool CrunchCache::needsUpdating(const String8& relativePath) const
{
// Retrieve modification dates for this file entry under the source and
// cache directory trees. The vectors will return a modification date of 0
diff --git a/tools/aapt/CrunchCache.h b/tools/aapt/CrunchCache.h
index be3da5c..4d6a169 100644
--- a/tools/aapt/CrunchCache.h
+++ b/tools/aapt/CrunchCache.h
@@ -81,7 +81,7 @@
* // Recrunch sourceFile out to destFile.
*
*/
- bool needsUpdating(String8 relativePath) const;
+ bool needsUpdating(const String8& relativePath) const;
// DATA MEMBERS ====================================================
diff --git a/tools/aapt/FileFinder.cpp b/tools/aapt/FileFinder.cpp
index 18775c0..c9d0744 100644
--- a/tools/aapt/FileFinder.cpp
+++ b/tools/aapt/FileFinder.cpp
@@ -77,7 +77,7 @@
return true;
}
-void SystemFileFinder::checkAndAddFile(String8 path, const struct stat* stats,
+void SystemFileFinder::checkAndAddFile(const String8& path, const struct stat* stats,
Vector<String8>& extensions,
KeyedVector<String8,time_t>& fileStore)
{
diff --git a/tools/aapt/FileFinder.h b/tools/aapt/FileFinder.h
index 6974aee..f405381 100644
--- a/tools/aapt/FileFinder.h
+++ b/tools/aapt/FileFinder.h
@@ -72,7 +72,7 @@
* time as the value.
*
*/
- static void checkAndAddFile(String8 path, const struct stat* stats,
+ static void checkAndAddFile(const String8& path, const struct stat* stats,
Vector<String8>& extensions,
KeyedVector<String8,time_t>& fileStore);
diff --git a/tools/aapt/IndentPrinter.h b/tools/aapt/IndentPrinter.h
index 6fc94bc..bd0edcb 100644
--- a/tools/aapt/IndentPrinter.h
+++ b/tools/aapt/IndentPrinter.h
@@ -3,7 +3,7 @@
class IndentPrinter {
public:
- IndentPrinter(FILE* stream, int indentSize=2)
+ explicit IndentPrinter(FILE* stream, int indentSize=2)
: mStream(stream)
, mIndentSize(indentSize)
, mIndent(0)
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index b278831..b4c4d05 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -399,7 +399,7 @@
const DefaultKeyedVector<String8, sp<AaptGroup> >& groups = dir->getFiles();
int N = groups.size();
for (int i=0; i<N; i++) {
- String8 leafName = groups.keyAt(i);
+ const String8& leafName = groups.keyAt(i);
const sp<AaptGroup>& group = groups.valueAt(i);
const DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> >& files
@@ -422,7 +422,7 @@
set->add(leafName, group);
resources->add(resType, set);
} else {
- sp<ResourceTypeSet> set = resources->valueAt(index);
+ const sp<ResourceTypeSet>& set = resources->valueAt(index);
index = set->indexOfKey(leafName);
if (index < 0) {
if (kIsDebug) {
@@ -457,7 +457,7 @@
int N = dirs.size();
for (int i=0; i<N; i++) {
- sp<AaptDir> d = dirs.itemAt(i);
+ const sp<AaptDir>& d = dirs.itemAt(i);
if (kIsDebug) {
printf("Collecting dir #%d %p: %s, leaf %s\n", i, d.get(), d->getPath().string(),
d->getLeaf().string());
@@ -615,7 +615,7 @@
// get the overlay resources of the requested type
ssize_t index = overlayRes->indexOfKey(resTypeString);
if (index >= 0) {
- sp<ResourceTypeSet> overlaySet = overlayRes->valueAt(index);
+ const sp<ResourceTypeSet>& overlaySet = overlayRes->valueAt(index);
// for each of the resources, check for a match in the previously built
// non-overlay "baseset".
@@ -765,7 +765,7 @@
return addTagAttribute(node, ns8, attr8, value, errorOnFailedInsert, false);
}
-static void fullyQualifyClassName(const String8& package, sp<XMLNode> node,
+static void fullyQualifyClassName(const String8& package, const sp<XMLNode>& node,
const String16& attrName) {
XMLNode::attribute_entry* attr = node->editAttribute(
String16("http://schemas.android.com/apk/res/android"), attrName);
@@ -1350,7 +1350,7 @@
ResourceDirIterator it(resources->valueAt(index), String8("values"));
ssize_t res;
while ((res=it.next()) == NO_ERROR) {
- sp<AaptFile> file = it.getFile();
+ const sp<AaptFile>& file = it.getFile();
res = compileResourceFile(bundle, assets, file, it.getParams(),
(current!=assets), &table);
if (res != NO_ERROR) {
@@ -2688,7 +2688,7 @@
String8 dest(bundle->getRClassDir());
if (bundle->getMakePackageDirs()) {
- String8 pkg(package);
+ const String8& pkg(package);
const char* last = pkg.string();
const char* s = last-1;
do {
diff --git a/tools/aapt/ResourceFilter.h b/tools/aapt/ResourceFilter.h
index d6430c0..40d5b75 100644
--- a/tools/aapt/ResourceFilter.h
+++ b/tools/aapt/ResourceFilter.h
@@ -78,7 +78,7 @@
class StrongResourceFilter : public ResourceFilter {
public:
StrongResourceFilter() {}
- StrongResourceFilter(const std::set<ConfigDescription>& configs)
+ explicit StrongResourceFilter(const std::set<ConfigDescription>& configs)
: mConfigs(configs) {}
android::status_t parse(const android::String8& str);
@@ -106,7 +106,7 @@
*/
class InverseResourceFilter : public ResourceFilter {
public:
- InverseResourceFilter(const android::sp<ResourceFilter>& filter)
+ explicit InverseResourceFilter(const android::sp<ResourceFilter>& filter)
: mFilter(filter) {}
bool match(const android::ResTable_config& config) const {
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 4d5bb31..76c59dd 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -4081,7 +4081,7 @@
j = 0;
for (i=0; i<N; i++) {
- sp<ConfigList> e = origOrder.itemAt(i);
+ const sp<ConfigList>& e = origOrder.itemAt(i);
// There will always be enough room for the remaining entries.
while (mOrderedConfigs.itemAt(j) != NULL) {
j++;
@@ -4203,7 +4203,7 @@
size_t j=0;
for (i=0; i<N; i++) {
- sp<Type> t = origOrder.itemAt(i);
+ const sp<Type>& t = origOrder.itemAt(i);
// There will always be enough room for the remaining types.
while (mOrderedTypes.itemAt(j) != NULL) {
j++;
@@ -4636,7 +4636,7 @@
c->getEntries();
const size_t entryCount = entries.size();
for (size_t ei = 0; ei < entryCount; ei++) {
- sp<Entry> e = entries.valueAt(ei);
+ const sp<Entry>& e = entries.valueAt(ei);
if (e == NULL || e->getType() != Entry::TYPE_BAG) {
continue;
}
diff --git a/tools/aapt/StringPool.h b/tools/aapt/StringPool.h
index 4b0d920..625b0bf 100644
--- a/tools/aapt/StringPool.h
+++ b/tools/aapt/StringPool.h
@@ -41,7 +41,7 @@
public:
struct entry {
entry() : offset(0) { }
- entry(const String16& _value) : value(_value), offset(0), hasStyles(false) { }
+ explicit entry(const String16& _value) : value(_value), offset(0), hasStyles(false) { }
entry(const entry& o) : value(o.value), offset(o.offset),
hasStyles(o.hasStyles), indices(o.indices),
configTypeName(o.configTypeName), configs(o.configs) { }
diff --git a/tools/aapt/WorkQueue.h b/tools/aapt/WorkQueue.h
index d38f05d..ab5f969 100644
--- a/tools/aapt/WorkQueue.h
+++ b/tools/aapt/WorkQueue.h
@@ -47,7 +47,7 @@
};
/* Creates a work queue with the specified maximum number of work threads. */
- WorkQueue(size_t maxThreads, bool canCallJava = true);
+ explicit WorkQueue(size_t maxThreads, bool canCallJava = true);
/* Destroys the work queue.
* Cancels pending work and waits for all remaining threads to complete.
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index 5b215da..15ec4af 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -67,7 +67,7 @@
static const String16 RESOURCES_PRV_PREFIX(RESOURCES_ROOT_PRV_NAMESPACE);
static const String16 RESOURCES_TOOLS_NAMESPACE("http://schemas.android.com/tools");
-String16 getNamespaceResourcePackage(String16 appPackage, String16 namespaceUri, bool* outIsPublic)
+String16 getNamespaceResourcePackage(const String16& appPackage, const String16& namespaceUri, bool* outIsPublic)
{
//printf("%s starts with %s?\n", String8(namespaceUri).string(),
// String8(RESOURCES_PREFIX).string());
@@ -98,7 +98,7 @@
status_t hasSubstitutionErrors(const char* fileName,
ResXMLTree* inXml,
- String16 str16)
+ const String16& str16)
{
const char16_t* str = str16.string();
const char16_t* p = str;
diff --git a/tools/aapt/XMLNode.h b/tools/aapt/XMLNode.h
index 749bf9f..ac92018 100644
--- a/tools/aapt/XMLNode.h
+++ b/tools/aapt/XMLNode.h
@@ -178,7 +178,7 @@
XMLNode(const String8& filename, const String16& s1, const String16& s2, bool isNamespace);
// Creating a CDATA node.
- XMLNode(const String8& filename);
+ explicit XMLNode(const String8& filename);
status_t collect_strings(StringPool* dest, Vector<uint32_t>* outResIds,
bool stripComments, bool stripRawValues) const;
diff --git a/tools/aapt/pseudolocalize.h b/tools/aapt/pseudolocalize.h
index 1faecd1..9bb1fd8 100644
--- a/tools/aapt/pseudolocalize.h
+++ b/tools/aapt/pseudolocalize.h
@@ -43,7 +43,7 @@
class Pseudolocalizer {
public:
- Pseudolocalizer(PseudolocalizationMethod m);
+ explicit Pseudolocalizer(PseudolocalizationMethod m);
~Pseudolocalizer() { if (mImpl) delete mImpl; }
void setMethod(PseudolocalizationMethod m);
String16 start() { return mImpl->start(); }
diff --git a/tools/aapt2/ConfigDescription.h b/tools/aapt2/ConfigDescription.h
index ef0d147..6858c62 100644
--- a/tools/aapt2/ConfigDescription.h
+++ b/tools/aapt2/ConfigDescription.h
@@ -51,7 +51,7 @@
static void applyVersionForCompatibility(ConfigDescription* config);
ConfigDescription();
- ConfigDescription(const android::ResTable_config& o);
+ ConfigDescription(const android::ResTable_config& o); // NOLINT(implicit)
ConfigDescription(const ConfigDescription& o);
ConfigDescription(ConfigDescription&& o);
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 0ba0345..09a04e0 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -100,7 +100,7 @@
ResourceNameRef() = default;
ResourceNameRef(const ResourceNameRef&) = default;
ResourceNameRef(ResourceNameRef&&) = default;
- ResourceNameRef(const ResourceName& rhs);
+ ResourceNameRef(const ResourceName& rhs); // NOLINT(implicit)
ResourceNameRef(const StringPiece& p, ResourceType t, const StringPiece& e);
ResourceNameRef& operator=(const ResourceNameRef& rhs) = default;
ResourceNameRef& operator=(ResourceNameRef&& rhs) = default;
@@ -126,7 +126,7 @@
ResourceId();
ResourceId(const ResourceId& rhs);
- ResourceId(uint32_t resId);
+ ResourceId(uint32_t resId); // NOLINT(implicit)
ResourceId(uint8_t p, uint8_t t, uint16_t e);
bool isValid() const;
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index 4d418d9..460de0e 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -274,7 +274,7 @@
}
bool ResourceTable::addResource(const ResourceNameRef& name,
- const ResourceId resId,
+ const ResourceId& resId,
const ConfigDescription& config,
const StringPiece& product,
std::unique_ptr<Value> value,
@@ -325,7 +325,7 @@
}
bool ResourceTable::addResourceAllowMangled(const ResourceNameRef& name,
- const ResourceId id,
+ const ResourceId& id,
const ConfigDescription& config,
const StringPiece& product,
std::unique_ptr<Value> value,
@@ -335,12 +335,12 @@
}
bool ResourceTable::addResourceImpl(const ResourceNameRef& name,
- const ResourceId resId,
+ const ResourceId& resId,
const ConfigDescription& config,
const StringPiece& product,
std::unique_ptr<Value> value,
const char* validChars,
- std::function<int(Value*,Value*)> conflictResolver,
+ const std::function<int(Value*,Value*)>& conflictResolver,
IDiagnostics* diag) {
assert(value && "value can't be nullptr");
assert(diag && "diagnostics can't be nullptr");
@@ -426,18 +426,18 @@
return true;
}
-bool ResourceTable::setSymbolState(const ResourceNameRef& name, const ResourceId resId,
+bool ResourceTable::setSymbolState(const ResourceNameRef& name, const ResourceId& resId,
const Symbol& symbol, IDiagnostics* diag) {
return setSymbolStateImpl(name, resId, symbol, kValidNameChars, diag);
}
bool ResourceTable::setSymbolStateAllowMangled(const ResourceNameRef& name,
- const ResourceId resId,
+ const ResourceId& resId,
const Symbol& symbol, IDiagnostics* diag) {
return setSymbolStateImpl(name, resId, symbol, kValidNameMangledChars, diag);
}
-bool ResourceTable::setSymbolStateImpl(const ResourceNameRef& name, const ResourceId resId,
+bool ResourceTable::setSymbolStateImpl(const ResourceNameRef& name, const ResourceId& resId,
const Symbol& symbol, const char* validChars,
IDiagnostics* diag) {
assert(diag && "diagnostics can't be nullptr");
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index a5efe35..6b52a43 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -103,7 +103,7 @@
*/
std::vector<std::unique_ptr<ResourceConfigValue>> values;
- ResourceEntry(const StringPiece& name) : name(name.toString()) { }
+ explicit ResourceEntry(const StringPiece& name) : name(name.toString()) { }
ResourceConfigValue* findValue(const ConfigDescription& config);
ResourceConfigValue* findValue(const ConfigDescription& config, const StringPiece& product);
@@ -200,7 +200,7 @@
IDiagnostics* diag);
bool addResource(const ResourceNameRef& name,
- const ResourceId resId,
+ const ResourceId& resId,
const ConfigDescription& config,
const StringPiece& product,
std::unique_ptr<Value> value,
@@ -231,19 +231,19 @@
IDiagnostics* diag);
bool addResourceAllowMangled(const ResourceNameRef& name,
- const ResourceId id,
+ const ResourceId& id,
const ConfigDescription& config,
const StringPiece& product,
std::unique_ptr<Value> value,
IDiagnostics* diag);
bool setSymbolState(const ResourceNameRef& name,
- const ResourceId resId,
+ const ResourceId& resId,
const Symbol& symbol,
IDiagnostics* diag);
bool setSymbolStateAllowMangled(const ResourceNameRef& name,
- const ResourceId resId,
+ const ResourceId& resId,
const Symbol& symbol,
IDiagnostics* diag);
@@ -294,16 +294,16 @@
IDiagnostics* diag);
bool addResourceImpl(const ResourceNameRef& name,
- ResourceId resId,
+ const ResourceId& resId,
const ConfigDescription& config,
const StringPiece& product,
std::unique_ptr<Value> value,
const char* validChars,
- std::function<int(Value*,Value*)> conflictResolver,
+ const std::function<int(Value*,Value*)>& conflictResolver,
IDiagnostics* diag);
bool setSymbolStateImpl(const ResourceNameRef& name,
- ResourceId resId,
+ const ResourceId& resId,
const Symbol& symbol,
const char* validChars,
IDiagnostics* diag);
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 7dc88ded..773616d 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -545,7 +545,7 @@
std::unique_ptr<Item> parseItemForAttribute(
const StringPiece& value,
uint32_t typeMask,
- std::function<void(const ResourceName&)> onCreateReference) {
+ const std::function<void(const ResourceName&)>& onCreateReference) {
std::unique_ptr<BinaryPrimitive> nullOrEmpty = tryParseNullOrEmpty(value);
if (nullOrEmpty) {
return std::move(nullOrEmpty);
@@ -604,7 +604,7 @@
*/
std::unique_ptr<Item> parseItemForAttribute(
const StringPiece& str, const Attribute* attr,
- std::function<void(const ResourceName&)> onCreateReference) {
+ const std::function<void(const ResourceName&)>& onCreateReference) {
const uint32_t typeMask = attr->typeMask;
std::unique_ptr<Item> value = parseItemForAttribute(str, typeMask, onCreateReference);
if (value) {
diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h
index 31b8e89..a57d89d 100644
--- a/tools/aapt2/ResourceUtils.h
+++ b/tools/aapt2/ResourceUtils.h
@@ -163,11 +163,11 @@
*/
std::unique_ptr<Item> parseItemForAttribute(
const StringPiece& value, const Attribute* attr,
- std::function<void(const ResourceName&)> onCreateReference = {});
+ const std::function<void(const ResourceName&)>& onCreateReference = {});
std::unique_ptr<Item> parseItemForAttribute(
const StringPiece& value, uint32_t typeMask,
- std::function<void(const ResourceName&)> onCreateReference = {});
+ const std::function<void(const ResourceName&)>& onCreateReference = {});
uint32_t androidTypeToAttributeTypeMask(uint16_t type);
diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h
index 8ae71ad..e6af716 100644
--- a/tools/aapt2/ResourceValues.h
+++ b/tools/aapt2/ResourceValues.h
@@ -198,7 +198,7 @@
struct RawString : public BaseItem<RawString> {
StringPool::Ref value;
- RawString(const StringPool::Ref& ref);
+ explicit RawString(const StringPool::Ref& ref);
bool equals(const Value* value) const override;
bool flatten(android::Res_value* outValue) const override;
@@ -209,7 +209,7 @@
struct String : public BaseItem<String> {
StringPool::Ref value;
- String(const StringPool::Ref& ref);
+ explicit String(const StringPool::Ref& ref);
bool equals(const Value* value) const override;
bool flatten(android::Res_value* outValue) const override;
@@ -220,7 +220,7 @@
struct StyledString : public BaseItem<StyledString> {
StringPool::StyleRef value;
- StyledString(const StringPool::StyleRef& ref);
+ explicit StyledString(const StringPool::StyleRef& ref);
bool equals(const Value* value) const override;
bool flatten(android::Res_value* outValue) const override;
@@ -237,7 +237,7 @@
io::IFile* file = nullptr;
FileReference() = default;
- FileReference(const StringPool::Ref& path);
+ explicit FileReference(const StringPool::Ref& path);
bool equals(const Value* value) const override;
bool flatten(android::Res_value* outValue) const override;
@@ -252,7 +252,7 @@
android::Res_value value;
BinaryPrimitive() = default;
- BinaryPrimitive(const android::Res_value& val);
+ explicit BinaryPrimitive(const android::Res_value& val);
BinaryPrimitive(uint8_t dataType, uint32_t data);
bool equals(const Value* value) const override;
@@ -272,7 +272,7 @@
int32_t maxInt;
std::vector<Symbol> symbols;
- Attribute(bool w, uint32_t t = 0u);
+ explicit Attribute(bool w, uint32_t t = 0u);
bool equals(const Value* value) const override;
Attribute* clone(StringPool* newPool) const override;
diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp
index 91e755d..ccf0383 100644
--- a/tools/aapt2/SdkConstants.cpp
+++ b/tools/aapt2/SdkConstants.cpp
@@ -52,7 +52,7 @@
return p.first < entryId;
}
-size_t findAttributeSdkLevel(ResourceId id) {
+size_t findAttributeSdkLevel(const ResourceId& id) {
if (id.packageId() != 0x01 && id.typeId() != 0x01) {
return 0;
}
diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h
index f28679f..c9dbdca 100644
--- a/tools/aapt2/SdkConstants.h
+++ b/tools/aapt2/SdkConstants.h
@@ -47,7 +47,7 @@
SDK_MARSHMALLOW = 23,
};
-size_t findAttributeSdkLevel(ResourceId id);
+size_t findAttributeSdkLevel(const ResourceId& id);
size_t findAttributeSdkLevel(const ResourceName& name);
std::pair<StringPiece, int> getDevelopmentSdkCodeNameAndVersion();
diff --git a/tools/aapt2/StringPool.h b/tools/aapt2/StringPool.h
index 72ae9d1..13545be 100644
--- a/tools/aapt2/StringPool.h
+++ b/tools/aapt2/StringPool.h
@@ -65,7 +65,7 @@
private:
friend class StringPool;
- Ref(Entry* entry);
+ explicit Ref(Entry* entry);
Entry* mEntry;
};
@@ -88,7 +88,7 @@
private:
friend class StringPool;
- StyleRef(StyleEntry* entry);
+ explicit StyleRef(StyleEntry* entry);
StyleEntry* mEntry;
};
diff --git a/tools/aapt2/compile/IdAssigner.cpp b/tools/aapt2/compile/IdAssigner.cpp
index 501ae9d..4a3f1e1 100644
--- a/tools/aapt2/compile/IdAssigner.cpp
+++ b/tools/aapt2/compile/IdAssigner.cpp
@@ -28,7 +28,7 @@
* Assigns the intended ID to the ResourceTablePackage, ResourceTableType, and ResourceEntry,
* as long as there is no existing ID or the ID is the same.
*/
-static bool assignId(IDiagnostics* diag, const ResourceId id, const ResourceName& name,
+static bool assignId(IDiagnostics* diag, const ResourceId& id, const ResourceName& name,
ResourceTablePackage* pkg, ResourceTableType* type, ResourceEntry* entry) {
if (pkg->id.value() == id.packageId()) {
if (!type->id || type->id.value() == id.typeId()) {
diff --git a/tools/aapt2/flatten/TableFlattener_test.cpp b/tools/aapt2/flatten/TableFlattener_test.cpp
index 0b92ba5..b25bfa7 100644
--- a/tools/aapt2/flatten/TableFlattener_test.cpp
+++ b/tools/aapt2/flatten/TableFlattener_test.cpp
@@ -64,7 +64,7 @@
::testing::AssertionResult exists(ResTable* table,
const StringPiece& expectedName,
- const ResourceId expectedId,
+ const ResourceId& expectedId,
const ConfigDescription& expectedConfig,
const uint8_t expectedDataType, const uint32_t expectedData,
const uint32_t expectedSpecFlags) {
diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp
index d26f2e4..4d1e178 100644
--- a/tools/aapt2/flatten/XmlFlattener_test.cpp
+++ b/tools/aapt2/flatten/XmlFlattener_test.cpp
@@ -43,7 +43,7 @@
}
::testing::AssertionResult flatten(xml::XmlResource* doc, android::ResXMLTree* outTree,
- XmlFlattenerOptions options = {}) {
+ const XmlFlattenerOptions& options = {}) {
using namespace android; // For NO_ERROR on windows because it is a macro.
BigBuffer buffer(1024);
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index acb0f38..ff777a3 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -528,7 +528,7 @@
static bool writeStableIdMapToPath(IDiagnostics* diag,
const std::unordered_map<ResourceName, ResourceId>& idMap,
- const std::string idMapPath) {
+ const std::string& idMapPath) {
std::ofstream fout(idMapPath, std::ofstream::binary);
if (!fout) {
diag->error(DiagMessage(idMapPath) << strerror(errno));
@@ -823,7 +823,7 @@
}
bool writeJavaFile(ResourceTable* table, const StringPiece& packageNameToGenerate,
- const StringPiece& outPackage, JavaClassGeneratorOptions javaOptions) {
+ const StringPiece& outPackage, const JavaClassGeneratorOptions& javaOptions) {
if (!mOptions.generateJavaClassPath) {
return true;
}
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index 8016f3b..379c991 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -135,7 +135,7 @@
const bool manglePackage,
const bool overlay,
const bool allowNewResources,
- FileMergeCallback callback) {
+ const FileMergeCallback& callback) {
bool error = false;
for (auto& srcType : srcPackage->types) {
diff --git a/tools/aapt2/link/TableMerger.h b/tools/aapt2/link/TableMerger.h
index 6997f93..3473a27 100644
--- a/tools/aapt2/link/TableMerger.h
+++ b/tools/aapt2/link/TableMerger.h
@@ -115,7 +115,7 @@
const bool manglePackage,
const bool overlay,
const bool allowNewResources,
- FileMergeCallback callback);
+ const FileMergeCallback& callback);
std::unique_ptr<FileReference> cloneAndMangleFile(const std::string& package,
const FileReference& value);
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index 6c506df..0c92718 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -63,7 +63,7 @@
return nullptr;
}
-const SymbolTable::Symbol* SymbolTable::findById(ResourceId id) {
+const SymbolTable::Symbol* SymbolTable::findById(const ResourceId& id) {
if (const std::shared_ptr<Symbol>& s = mIdCache.get(id)) {
return s.get();
}
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index 43f4dd7..bd01b64 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -86,7 +86,7 @@
* are typically stored in a cache which may evict entries.
*/
const Symbol* findByName(const ResourceName& name);
- const Symbol* findById(ResourceId id);
+ const Symbol* findById(const ResourceId& id);
/**
* Let's the ISymbolSource decide whether looking up by name or ID is faster, if both
diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp
index 98ff87f..ca25c6a 100644
--- a/tools/aapt2/proto/TableProtoDeserializer.cpp
+++ b/tools/aapt2/proto/TableProtoDeserializer.cpp
@@ -228,7 +228,7 @@
}
} else if (pbValue.has_compound_value()) {
- const pb::CompoundValue pbCompoundValue = pbValue.compound_value();
+ const pb::CompoundValue& pbCompoundValue = pbValue.compound_value();
if (pbCompoundValue.has_attr()) {
const pb::Attribute& pbAttr = pbCompoundValue.attr();
std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(isWeak);