summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/INotificationManager.aidl1
-rw-r--r--core/java/android/app/Instrumentation.java6
-rw-r--r--core/java/android/app/NotificationManager.java12
-rw-r--r--core/java/android/bluetooth/BluetoothGattCharacteristic.java2
-rw-r--r--core/java/android/content/Intent.java23
-rw-r--r--core/java/android/hardware/camera2/legacy/GLThreadManager.java14
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java81
-rw-r--r--core/java/android/hardware/camera2/legacy/RequestThreadManager.java59
-rw-r--r--core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java64
-rw-r--r--core/java/android/net/ConnectivityManager.java23
-rw-r--r--core/java/android/net/IConnectivityManager.aidl3
-rw-r--r--core/java/android/net/INetworkStatsService.aidl4
-rw-r--r--core/java/android/net/LocalServerSocket.java10
-rw-r--r--core/java/android/net/NetworkIdentity.java34
-rw-r--r--core/java/android/net/NetworkMisc.java17
-rw-r--r--core/java/android/net/NetworkPolicy.java2
-rw-r--r--core/java/android/net/NetworkState.java7
-rw-r--r--core/java/android/net/NetworkTemplate.java71
-rw-r--r--core/java/android/os/BaseBundle.java10
-rw-r--r--core/java/android/os/Bundle.java62
-rw-r--r--core/java/android/os/Debug.java10
-rw-r--r--core/java/android/os/PersistableBundle.java3
-rw-r--r--core/java/android/provider/Settings.java2
-rw-r--r--core/java/android/service/notification/ZenModeConfig.java24
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java4
-rw-r--r--core/java/android/view/RenderNodeAnimator.java53
-rw-r--r--core/java/android/view/ThreadedRenderer.java9
-rw-r--r--core/java/android/view/View.java24
-rw-r--r--core/java/android/view/ViewGroup.java105
-rw-r--r--core/java/android/view/accessibility/AccessibilityCache.java1
-rw-r--r--core/java/android/widget/AbsListView.java69
-rw-r--r--core/java/android/widget/HorizontalScrollView.java15
-rw-r--r--core/java/android/widget/ListPopupWindow.java8
-rw-r--r--core/java/android/widget/RadialTimePickerView.java39
-rw-r--r--core/java/android/widget/Switch.java4
35 files changed, 557 insertions, 318 deletions
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index bdcff38..88b9080 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -71,6 +71,7 @@ interface INotificationManager
ComponentName getEffectsSuppressor();
boolean matchesCallFilter(in Bundle extras);
+ boolean isSystemConditionProviderEnabled(String path);
ZenModeConfig getZenModeConfig();
boolean setZenModeConfig(in ZenModeConfig config);
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 3c30404..ad2b61f 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1217,8 +1217,10 @@ public class Instrumentation {
public void callActivityOnNewIntent(Activity activity, ReferrerIntent intent) {
final String oldReferrer = activity.mReferrer;
try {
- activity.mReferrer = intent.mReferrer;
- callActivityOnNewIntent(activity, new Intent(intent));
+ if (intent != null) {
+ activity.mReferrer = intent.mReferrer;
+ }
+ callActivityOnNewIntent(activity, intent != null ? new Intent(intent) : null);
} finally {
activity.mReferrer = oldReferrer;
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 7dc1ad6..cf54107 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -264,5 +264,17 @@ public class NotificationManager
}
}
+ /**
+ * @hide
+ */
+ public boolean isSystemConditionProviderEnabled(String path) {
+ INotificationManager service = getService();
+ try {
+ return service.isSystemConditionProviderEnabled(path);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
private Context mContext;
}
diff --git a/core/java/android/bluetooth/BluetoothGattCharacteristic.java b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
index a86677c..7cdcc2c 100644
--- a/core/java/android/bluetooth/BluetoothGattCharacteristic.java
+++ b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
@@ -502,7 +502,7 @@ public class BluetoothGattCharacteristic {
* @return Cached value of the characteristic
*/
public String getStringValue(int offset) {
- if (offset > mValue.length) return null;
+ if (mValue == null || offset > mValue.length) return null;
byte[] strBytes = new byte[mValue.length - offset];
for (int i=0; i != (mValue.length-offset); ++i) strBytes[i] = mValue[offset+i];
return new String(strBytes);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index de7fbab..5ebbf16 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -4391,7 +4391,7 @@ public class Intent implements Parcelable, Cloneable {
// scheme
else if (uri.startsWith("scheme=", i)) {
if (inSelector) {
- intent.mData = Uri.parse(value);
+ intent.mData = Uri.parse(value + ":");
} else {
scheme = value;
}
@@ -4461,14 +4461,19 @@ public class Intent implements Parcelable, Cloneable {
String authority = null;
intent.mPackage = data.substring(14, end);
int newEnd;
- if (end < data.length() && (newEnd=data.indexOf('/', end+1)) >= 0) {
- // Found a scheme, remember it.
- scheme = data.substring(end+1, newEnd);
- end = newEnd;
- if (end < data.length() && (newEnd=data.indexOf('/', end+1)) >= 0) {
- // Found a authority, remember it.
- authority = data.substring(end+1, newEnd);
+ if ((end+1) < data.length()) {
+ if ((newEnd=data.indexOf('/', end+1)) >= 0) {
+ // Found a scheme, remember it.
+ scheme = data.substring(end+1, newEnd);
end = newEnd;
+ if (end < data.length() && (newEnd=data.indexOf('/', end+1)) >= 0) {
+ // Found a authority, remember it.
+ authority = data.substring(end+1, newEnd);
+ end = newEnd;
+ }
+ } else {
+ // All we have is a scheme.
+ scheme = data.substring(end+1);
}
}
if (scheme == null) {
@@ -7355,7 +7360,7 @@ public class Intent implements Parcelable, Cloneable {
toUriInner(frag, scheme, defAction, defPackage, flags);
if (mSelector != null) {
- uri.append("SEL;");
+ frag.append("SEL;");
// Note that for now we are not going to try to handle the
// data part; not clear how to represent this as a URI, and
// not much utility in it.
diff --git a/core/java/android/hardware/camera2/legacy/GLThreadManager.java b/core/java/android/hardware/camera2/legacy/GLThreadManager.java
index 64c532b..b160d2a 100644
--- a/core/java/android/hardware/camera2/legacy/GLThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/GLThreadManager.java
@@ -22,6 +22,8 @@ import android.os.ConditionVariable;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
+import android.util.Pair;
+import android.util.Size;
import android.view.Surface;
import java.util.Collection;
@@ -57,11 +59,11 @@ public class GLThreadManager {
*/
private static class ConfigureHolder {
public final ConditionVariable condition;
- public final Collection<Surface> surfaces;
+ public final Collection<Pair<Surface, Size>> surfaces;
public final CaptureCollector collector;
- public ConfigureHolder(ConditionVariable condition, Collection<Surface> surfaces,
- CaptureCollector collector) {
+ public ConfigureHolder(ConditionVariable condition, Collection<Pair<Surface,
+ Size>> surfaces, CaptureCollector collector) {
this.condition = condition;
this.surfaces = surfaces;
this.collector = collector;
@@ -202,10 +204,12 @@ public class GLThreadManager {
* Configure the GL renderer for the given set of output surfaces, and block until
* this configuration has been applied.
*
- * @param surfaces a collection of {@link android.view.Surface}s to configure.
+ * @param surfaces a collection of pairs of {@link android.view.Surface}s and their
+ * corresponding sizes to configure.
* @param collector a {@link CaptureCollector} to retrieve requests from.
*/
- public void setConfigurationAndWait(Collection<Surface> surfaces, CaptureCollector collector) {
+ public void setConfigurationAndWait(Collection<Pair<Surface, Size>> surfaces,
+ CaptureCollector collector) {
checkNotNull(collector, "collector must not be null");
Handler handler = mGLHandlerThread.getHandler();
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index 3a976ba..3043d13 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -24,7 +24,6 @@ import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.impl.CameraDeviceImpl;
import android.hardware.camera2.impl.CaptureResultExtras;
import android.hardware.camera2.ICameraDeviceCallbacks;
-import android.hardware.camera2.params.StreamConfiguration;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.hardware.camera2.utils.ArrayUtils;
import android.hardware.camera2.utils.CameraBinderDecorator;
@@ -36,6 +35,7 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.RemoteException;
import android.util.Log;
+import android.util.Pair;
import android.util.Size;
import android.view.Surface;
@@ -78,6 +78,15 @@ public class LegacyCameraDevice implements AutoCloseable {
private final Handler mResultHandler;
private static final int ILLEGAL_VALUE = -1;
+ // Keep up to date with values in hardware/libhardware/include/hardware/gralloc.h
+ private static final int GRALLOC_USAGE_RENDERSCRIPT = 0x00100000;
+ private static final int GRALLOC_USAGE_SW_READ_OFTEN = 0x00000003;
+ private static final int GRALLOC_USAGE_HW_TEXTURE = 0x00000100;
+ private static final int GRALLOC_USAGE_HW_COMPOSER = 0x00000800;
+ private static final int GRALLOC_USAGE_HW_VIDEO_ENCODER = 0x00010000;
+
+ private static final int MAX_DIMEN_FOR_ROUNDING = 1080; // maximum allowed width for rounding
+
private CaptureResultExtras getExtrasFromRequest(RequestHolder holder) {
if (holder == null) {
return new CaptureResultExtras(ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE,
@@ -276,6 +285,7 @@ public class LegacyCameraDevice implements AutoCloseable {
* on success.
*/
public int configureOutputs(List<Surface> outputs) {
+ List<Pair<Surface, Size>> sizedSurfaces = new ArrayList<>();
if (outputs != null) {
for (Surface output : outputs) {
if (output == null) {
@@ -289,16 +299,25 @@ public class LegacyCameraDevice implements AutoCloseable {
try {
Size s = getSurfaceSize(output);
int surfaceType = detectSurfaceType(output);
- Size[] sizes = streamConfigurations.getOutputSizes(surfaceType);
+ int usageFlags = detectSurfaceUsageFlags(output);
+ // Keep up to date with allowed consumer types in
+ // frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+ int disallowedFlags = GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_RENDERSCRIPT;
+ int allowedFlags = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN |
+ GRALLOC_USAGE_HW_COMPOSER;
+ boolean flexibleConsumer = ((usageFlags & disallowedFlags) == 0 &&
+ (usageFlags & allowedFlags) != 0);
+
+ Size[] sizes = streamConfigurations.getOutputSizes(surfaceType);
if (sizes == null) {
// WAR: Override default format to IMPLEMENTATION_DEFINED for b/9487482
if ((surfaceType >= LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888 &&
surfaceType <= LegacyMetadataMapper.HAL_PIXEL_FORMAT_BGRA_8888)) {
- // YUV_420_888 is always present in LEGACY for all IMPLEMENTATION_DEFINED
- // output sizes, and is publicly visible in the API (i.e.
- // {@code #getOutputSizes} works here).
+ // YUV_420_888 is always present in LEGACY for all
+ // IMPLEMENTATION_DEFINED output sizes, and is publicly visible in the
+ // API (i.e. {@code #getOutputSizes} works here).
sizes = streamConfigurations.getOutputSizes(ImageFormat.YUV_420_888);
} else if (surfaceType == LegacyMetadataMapper.HAL_PIXEL_FORMAT_BLOB) {
sizes = streamConfigurations.getOutputSizes(ImageFormat.JPEG);
@@ -306,12 +325,18 @@ public class LegacyCameraDevice implements AutoCloseable {
}
if (!ArrayUtils.contains(sizes, s)) {
- String reason = (sizes == null) ? "format is invalid." :
- ("size not in valid set: " + Arrays.toString(sizes));
- Log.e(TAG, String.format("Surface with size (w=%d, h=%d) and format 0x%x is"
- + " not valid, %s", s.getWidth(), s.getHeight(), surfaceType,
- reason));
- return BAD_VALUE;
+ if (flexibleConsumer && (s = findClosestSize(s, sizes)) != null) {
+ sizedSurfaces.add(new Pair<>(output, s));
+ } else {
+ String reason = (sizes == null) ? "format is invalid." :
+ ("size not in valid set: " + Arrays.toString(sizes));
+ Log.e(TAG, String.format("Surface with size (w=%d, h=%d) and format " +
+ "0x%x is not valid, %s", s.getWidth(), s.getHeight(),
+ surfaceType, reason));
+ return BAD_VALUE;
+ }
+ } else {
+ sizedSurfaces.add(new Pair<>(output, s));
}
} catch (BufferQueueAbandonedException e) {
Log.e(TAG, "Surface bufferqueue is abandoned, cannot configure as output: ", e);
@@ -323,7 +348,7 @@ public class LegacyCameraDevice implements AutoCloseable {
boolean success = false;
if (mDeviceState.setConfiguring()) {
- mRequestThreadManager.configure(outputs);
+ mRequestThreadManager.configure(sizedSurfaces);
success = mDeviceState.setIdle();
}
@@ -473,6 +498,31 @@ public class LegacyCameraDevice implements AutoCloseable {
}
}
+ static long findEuclidDistSquare(Size a, Size b) {
+ long d0 = a.getWidth() - b.getWidth();
+ long d1 = a.getHeight() - b.getHeight();
+ return d0 * d0 + d1 * d1;
+ }
+
+ // Keep up to date with rounding behavior in
+ // frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+ static Size findClosestSize(Size size, Size[] supportedSizes) {
+ if (size == null || supportedSizes == null) {
+ return null;
+ }
+ Size bestSize = null;
+ for (Size s : supportedSizes) {
+ if (s.equals(size)) {
+ return size;
+ } else if (s.getWidth() <= MAX_DIMEN_FOR_ROUNDING && (bestSize == null ||
+ LegacyCameraDevice.findEuclidDistSquare(size, s) <
+ LegacyCameraDevice.findEuclidDistSquare(bestSize, s))) {
+ bestSize = s;
+ }
+ }
+ return bestSize;
+ }
+
/**
* Query the surface for its currently configured default buffer size.
* @param surface a non-{@code null} {@code Surface}
@@ -490,6 +540,11 @@ public class LegacyCameraDevice implements AutoCloseable {
return new Size(dimens[0], dimens[1]);
}
+ static int detectSurfaceUsageFlags(Surface surface) {
+ checkNotNull(surface);
+ return nativeDetectSurfaceUsageFlags(surface);
+ }
+
static int detectSurfaceType(Surface surface) throws BufferQueueAbandonedException {
checkNotNull(surface);
return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceType(surface));
@@ -608,5 +663,7 @@ public class LegacyCameraDevice implements AutoCloseable {
private static native int nativeSetNextTimestamp(Surface surface, long timestamp);
+ private static native int nativeDetectSurfaceUsageFlags(Surface surface);
+
static native int nativeGetJpegFooterSize();
}
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index 35deb71..6535a4e 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -41,6 +41,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -116,9 +117,10 @@ public class RequestThreadManager {
*/
private static class ConfigureHolder {
public final ConditionVariable condition;
- public final Collection<Surface> surfaces;
+ public final Collection<Pair<Surface, Size>> surfaces;
- public ConfigureHolder(ConditionVariable condition, Collection<Surface> surfaces) {
+ public ConfigureHolder(ConditionVariable condition, Collection<Pair<Surface,
+ Size>> surfaces) {
this.condition = condition;
this.surfaces = surfaces;
}
@@ -317,7 +319,7 @@ public class RequestThreadManager {
startPreview();
}
- private void configureOutputs(Collection<Surface> outputs) {
+ private void configureOutputs(Collection<Pair<Surface, Size>> outputs) {
if (DEBUG) {
String outputsStr = outputs == null ? "null" : (outputs.size() + " surfaces");
Log.d(TAG, "configureOutputs with " + outputsStr);
@@ -346,10 +348,15 @@ public class RequestThreadManager {
mJpegSurfaceIds.clear();
mPreviewTexture = null;
+ List<Size> previewOutputSizes = new ArrayList<>();
+ List<Size> callbackOutputSizes = new ArrayList<>();
+
int facing = mCharacteristics.get(CameraCharacteristics.LENS_FACING);
int orientation = mCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
if (outputs != null) {
- for (Surface s : outputs) {
+ for (Pair<Surface, Size> outPair : outputs) {
+ Surface s = outPair.first;
+ Size outSize = outPair.second;
try {
int format = LegacyCameraDevice.detectSurfaceType(s);
LegacyCameraDevice.setSurfaceOrientation(s, facing, orientation);
@@ -362,9 +369,11 @@ public class RequestThreadManager {
}
mJpegSurfaceIds.add(LegacyCameraDevice.getSurfaceId(s));
mCallbackOutputs.add(s);
+ callbackOutputSizes.add(outSize);
break;
default:
mPreviewOutputs.add(s);
+ previewOutputSizes.add(outSize);
break;
}
} catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
@@ -391,18 +400,9 @@ public class RequestThreadManager {
mParams.setPreviewFpsRange(bestRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
bestRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
- if (mPreviewOutputs.size() > 0) {
- List<Size> outputSizes = new ArrayList<>(outputs.size());
- for (Surface s : mPreviewOutputs) {
- try {
- Size size = LegacyCameraDevice.getSurfaceSize(s);
- outputSizes.add(size);
- } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
- Log.w(TAG, "Surface abandoned, skipping...", e);
- }
- }
+ if (previewOutputSizes.size() > 0) {
- Size largestOutput = SizeAreaComparator.findLargestByArea(outputSizes);
+ Size largestOutput = SizeAreaComparator.findLargestByArea(previewOutputSizes);
// Find largest jpeg dimension - assume to have the same aspect ratio as sensor.
Size largestJpegDimen = ParameterUtils.getLargestSupportedJpegSizeByArea(mParams);
@@ -439,7 +439,8 @@ public class RequestThreadManager {
}
}
- Size smallestSupportedJpegSize = calculatePictureSize(mCallbackOutputs, mParams);
+ Size smallestSupportedJpegSize = calculatePictureSize(mCallbackOutputs,
+ callbackOutputSizes, mParams);
if (smallestSupportedJpegSize != null) {
/*
* Set takePicture size to the smallest supported JPEG size large enough
@@ -457,7 +458,12 @@ public class RequestThreadManager {
mGLThreadManager.start();
}
mGLThreadManager.waitUntilStarted();
- mGLThreadManager.setConfigurationAndWait(mPreviewOutputs, mCaptureCollector);
+ List<Pair<Surface, Size>> previews = new ArrayList<>();
+ Iterator<Size> previewSizeIter = previewOutputSizes.iterator();
+ for (Surface p : mPreviewOutputs) {
+ previews.add(new Pair<>(p, previewSizeIter.next()));
+ }
+ mGLThreadManager.setConfigurationAndWait(previews, mCaptureCollector);
mGLThreadManager.allowNewFrames();
mPreviewTexture = mGLThreadManager.getCurrentSurfaceTexture();
if (mPreviewTexture != null) {
@@ -499,26 +505,25 @@ public class RequestThreadManager {
* {@code null} if the {@code callbackOutputs} did not have any {@code JPEG}
* surfaces.
*/
- private Size calculatePictureSize(
- Collection<Surface> callbackOutputs, Camera.Parameters params) {
+ private Size calculatePictureSize( List<Surface> callbackOutputs,
+ List<Size> callbackSizes, Camera.Parameters params) {
/*
* Find the largest JPEG size (if any), from the configured outputs:
* - the api1 picture size should be set to the smallest legal size that's at least as large
* as the largest configured JPEG size
*/
- List<Size> configuredJpegSizes = new ArrayList<Size>();
+ if (callbackOutputs.size() != callbackSizes.size()) {
+ throw new IllegalStateException("Input collections must be same length");
+ }
+ List<Size> configuredJpegSizes = new ArrayList<>();
+ Iterator<Size> sizeIterator = callbackSizes.iterator();
for (Surface callbackSurface : callbackOutputs) {
- try {
-
+ Size jpegSize = sizeIterator.next();
if (!LegacyCameraDevice.containsSurfaceId(callbackSurface, mJpegSurfaceIds)) {
continue; // Ignore non-JPEG callback formats
}
- Size jpegSize = LegacyCameraDevice.getSurfaceSize(callbackSurface);
configuredJpegSizes.add(jpegSize);
- } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
- Log.w(TAG, "Surface abandoned, skipping...", e);
- }
}
if (!configuredJpegSizes.isEmpty()) {
/*
@@ -994,7 +999,7 @@ public class RequestThreadManager {
*
* @param outputs a {@link java.util.Collection} of outputs to configure.
*/
- public void configure(Collection<Surface> outputs) {
+ public void configure(Collection<Pair<Surface, Size>> outputs) {
Handler handler = mRequestThread.waitAndGetHandler();
final ConditionVariable condition = new ConditionVariable(/*closed*/false);
ConfigureHolder holder = new ConfigureHolder(condition, outputs);
diff --git a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
index c0d1d5e..4853b81 100644
--- a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
+++ b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
@@ -397,16 +397,9 @@ public class SurfaceTextureRenderer {
EGL14.EGL_NONE
};
for (EGLSurfaceHolder holder : surfaces) {
- try {
- Size size = LegacyCameraDevice.getSurfaceSize(holder.surface);
- holder.width = size.getWidth();
- holder.height = size.getHeight();
- holder.eglSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, mConfigs,
- holder.surface, surfaceAttribs, /*offset*/ 0);
- checkEglError("eglCreateWindowSurface");
- } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
- Log.w(TAG, "Surface abandoned, skipping...", e);
- }
+ holder.eglSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, mConfigs,
+ holder.surface, surfaceAttribs, /*offset*/ 0);
+ checkEglError("eglCreateWindowSurface");
}
}
@@ -417,24 +410,17 @@ public class SurfaceTextureRenderer {
int maxLength = 0;
for (EGLSurfaceHolder holder : surfaces) {
- try {
- Size size = LegacyCameraDevice.getSurfaceSize(holder.surface);
- int length = size.getWidth() * size.getHeight();
- // Find max surface size, ensure PBuffer can hold this many pixels
- maxLength = (length > maxLength) ? length : maxLength;
- int[] surfaceAttribs = {
- EGL14.EGL_WIDTH, size.getWidth(),
- EGL14.EGL_HEIGHT, size.getHeight(),
- EGL14.EGL_NONE
- };
- holder.width = size.getWidth();
- holder.height = size.getHeight();
- holder.eglSurface =
- EGL14.eglCreatePbufferSurface(mEGLDisplay, mConfigs, surfaceAttribs, 0);
- checkEglError("eglCreatePbufferSurface");
- } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
- Log.w(TAG, "Surface abandoned, skipping...", e);
- }
+ int length = holder.width * holder.height;
+ // Find max surface size, ensure PBuffer can hold this many pixels
+ maxLength = (length > maxLength) ? length : maxLength;
+ int[] surfaceAttribs = {
+ EGL14.EGL_WIDTH, holder.width,
+ EGL14.EGL_HEIGHT, holder.height,
+ EGL14.EGL_NONE
+ };
+ holder.eglSurface =
+ EGL14.eglCreatePbufferSurface(mEGLDisplay, mConfigs, surfaceAttribs, 0);
+ checkEglError("eglCreatePbufferSurface");
}
mPBufferPixels = ByteBuffer.allocateDirect(maxLength * PBUFFER_PIXEL_BYTES)
.order(ByteOrder.nativeOrder());
@@ -569,7 +555,7 @@ public class SurfaceTextureRenderer {
*
* @param surfaces a {@link Collection} of surfaces.
*/
- public void configureSurfaces(Collection<Surface> surfaces) {
+ public void configureSurfaces(Collection<Pair<Surface, Size>> surfaces) {
releaseEGLContext();
if (surfaces == null || surfaces.size() == 0) {
@@ -577,18 +563,20 @@ public class SurfaceTextureRenderer {
return;
}
- for (Surface s : surfaces) {
+ for (Pair<Surface, Size> p : surfaces) {
+ Surface s = p.first;
+ Size surfaceSize = p.second;
// If pixel conversions aren't handled by egl, use a pbuffer
try {
+ EGLSurfaceHolder holder = new EGLSurfaceHolder();
+ holder.surface = s;
+ holder.width = surfaceSize.getWidth();
+ holder.height = surfaceSize.getHeight();
if (LegacyCameraDevice.needsConversion(s)) {
// Always override to YV12 output for YUV surface formats.
LegacyCameraDevice.setSurfaceFormat(s, ImageFormat.YV12);
- EGLSurfaceHolder holder = new EGLSurfaceHolder();
- holder.surface = s;
mConversionSurfaces.add(holder);
} else {
- EGLSurfaceHolder holder = new EGLSurfaceHolder();
- holder.surface = s;
mSurfaces.add(holder);
}
} catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
@@ -672,10 +660,11 @@ public class SurfaceTextureRenderer {
List<Long> targetSurfaceIds = LegacyCameraDevice.getSurfaceIds(targetSurfaces);
for (EGLSurfaceHolder holder : mSurfaces) {
if (LegacyCameraDevice.containsSurfaceId(holder.surface, targetSurfaceIds)) {
- makeCurrent(holder.eglSurface);
- try {
+ try{
LegacyCameraDevice.setSurfaceDimens(holder.surface, holder.width,
holder.height);
+ makeCurrent(holder.eglSurface);
+
LegacyCameraDevice.setNextTimestamp(holder.surface, captureHolder.second);
drawFrame(mSurfaceTexture, holder.width, holder.height);
swapBuffers(holder.eglSurface);
@@ -695,10 +684,11 @@ public class SurfaceTextureRenderer {
try {
int format = LegacyCameraDevice.detectSurfaceType(holder.surface);
+ LegacyCameraDevice.setSurfaceDimens(holder.surface, holder.width,
+ holder.height);
LegacyCameraDevice.setNextTimestamp(holder.surface, captureHolder.second);
LegacyCameraDevice.produceFrame(holder.surface, mPBufferPixels.array(),
holder.width, holder.height, format);
- swapBuffers(holder.eglSurface);
} catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
Log.w(TAG, "Surface abandoned, dropping frame. ", e);
}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 4215f20..7d5db85 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -37,6 +37,7 @@ import android.os.Messenger;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
import android.util.Log;
@@ -100,7 +101,7 @@ public class ConnectivityManager {
/**
* Identical to {@link #CONNECTIVITY_ACTION} broadcast, but sent without any
- * applicable {@link Settings.Global#CONNECTIVITY_CHANGE_DELAY}.
+ * historic {@link Settings.Global#CONNECTIVITY_CHANGE_DELAY}.
*
* @hide
*/
@@ -428,18 +429,6 @@ public class ConnectivityManager {
public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI;
/**
- * Default value for {@link Settings.Global#CONNECTIVITY_CHANGE_DELAY} in
- * milliseconds. This was introduced because IPv6 routes seem to take a
- * moment to settle - trying network activity before the routes are adjusted
- * can lead to packets using the wrong interface or having the wrong IP address.
- * This delay is a bit crude, but in the future hopefully we will have kernel
- * notifications letting us know when it's safe to use the new network.
- *
- * @hide
- */
- public static final int CONNECTIVITY_CHANGE_DELAY_DEFAULT = 3000;
-
- /**
* @hide
*/
public final static int REQUEST_ID_UNSET = 0;
@@ -1295,9 +1284,15 @@ public class ConnectivityManager {
if (b != null) {
try {
ITelephony it = ITelephony.Stub.asInterface(b);
- return it.getDataEnabled();
+ int subId = SubscriptionManager.getDefaultDataSubId();
+ Log.d("ConnectivityManager", "getMobileDataEnabled()+ subId=" + subId);
+ boolean retVal = it.getDataEnabled(subId);
+ Log.d("ConnectivityManager", "getMobileDataEnabled()- subId=" + subId
+ + " retVal=" + retVal);
+ return retVal;
} catch (RemoteException e) { }
}
+ Log.d("ConnectivityManager", "getMobileDataEnabled()- remote exception retVal=false");
return false;
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 8021210..d9921a6 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -68,9 +68,6 @@ interface IConnectivityManager
boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress);
- /** Policy control over specific {@link NetworkStateTracker}. */
- void setPolicyDataEnable(int networkType, boolean enabled);
-
int tether(String iface);
int untether(String iface);
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index b7b8731..2c3881c 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -40,8 +40,12 @@ interface INetworkStatsService {
/** Mark given UID as being in foreground for stats purposes. */
void setUidForeground(int uid, boolean uidForeground);
+
+ /** Force update of ifaces. */
+ void forceUpdateIfaces();
/** Force update of statistics. */
void forceUpdate();
+
/** Advise persistance threshold; may be overridden internally. */
void advisePersistThreshold(long thresholdBytes);
diff --git a/core/java/android/net/LocalServerSocket.java b/core/java/android/net/LocalServerSocket.java
index a36203b..9464222 100644
--- a/core/java/android/net/LocalServerSocket.java
+++ b/core/java/android/net/LocalServerSocket.java
@@ -20,12 +20,8 @@ import java.io.IOException;
import java.io.FileDescriptor;
/**
- * non-standard class for creating inbound UNIX-domain socket
- * on the Android platform, this is created in the Linux non-filesystem
- * namespace.
- *
- * On simulator platforms, this may be created in a temporary directory on
- * the filesystem
+ * Non-standard class for creating an inbound UNIX-domain socket
+ * in the Linux abstract namespace.
*/
public class LocalServerSocket {
private final LocalSocketImpl impl;
@@ -35,7 +31,7 @@ public class LocalServerSocket {
private static final int LISTEN_BACKLOG = 50;
/**
- * Crewates a new server socket listening at specified name.
+ * Creates a new server socket listening at specified name.
* On the Android platform, the name is created in the Linux
* abstract namespace (instead of on the filesystem).
*
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index d36707e..a9de23e 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -25,6 +25,7 @@ import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.telephony.TelephonyManager;
+import android.util.Slog;
import java.util.Objects;
@@ -35,10 +36,16 @@ import java.util.Objects;
* @hide
*/
public class NetworkIdentity implements Comparable<NetworkIdentity> {
+ private static final String TAG = "NetworkIdentity";
+
/**
* When enabled, combine all {@link #mSubType} together under
* {@link #SUBTYPE_COMBINED}.
+ *
+ * @deprecated we no longer offer to collect statistics on a per-subtype
+ * basis; this is always disabled.
*/
+ @Deprecated
public static final boolean COMBINE_SUBTYPE_ENABLED = true;
public static final int SUBTYPE_COMBINED = -1;
@@ -133,6 +140,18 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
}
/**
+ * Scrub given IMSI on production builds.
+ */
+ public static String[] scrubSubscriberId(String[] subscriberId) {
+ if (subscriberId == null) return null;
+ final String[] res = new String[subscriberId.length];
+ for (int i = 0; i < res.length; i++) {
+ res[i] = NetworkIdentity.scrubSubscriberId(subscriberId[i]);
+ }
+ return res;
+ }
+
+ /**
* Build a {@link NetworkIdentity} from the given {@link NetworkState},
* assuming that any mobile networks are using the current IMSI.
*/
@@ -140,23 +159,18 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
final int type = state.networkInfo.getType();
final int subType = state.networkInfo.getSubtype();
- // TODO: consider moving subscriberId over to LinkCapabilities, so it
- // comes from an authoritative source.
-
String subscriberId = null;
String networkId = null;
boolean roaming = false;
if (isNetworkTypeMobile(type)) {
- final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
- Context.TELEPHONY_SERVICE);
- roaming = telephony.isNetworkRoaming();
- if (state.subscriberId != null) {
- subscriberId = state.subscriberId;
- } else {
- subscriberId = telephony.getSubscriberId();
+ if (state.subscriberId == null) {
+ Slog.w(TAG, "Active mobile network without subscriber!");
}
+ subscriberId = state.subscriberId;
+ roaming = state.networkInfo.isRoaming();
+
} else if (type == TYPE_WIFI) {
if (state.networkId != null) {
networkId = state.networkId;
diff --git a/core/java/android/net/NetworkMisc.java b/core/java/android/net/NetworkMisc.java
index 5d2a43d..b92c9e3 100644
--- a/core/java/android/net/NetworkMisc.java
+++ b/core/java/android/net/NetworkMisc.java
@@ -20,15 +20,18 @@ import android.os.Parcel;
import android.os.Parcelable;
/**
- * A grab-bag of information (metadata, policies, properties, etc) about a {@link Network}.
+ * A grab-bag of information (metadata, policies, properties, etc) about a
+ * {@link Network}. Since this contains PII, it should not be sent outside the
+ * system.
*
* @hide
*/
public class NetworkMisc implements Parcelable {
/**
- * If the {@link Network} is a VPN, whether apps are allowed to bypass the VPN. This is set by
- * a {@link VpnService} and used by {@link ConnectivityService} when creating a VPN.
+ * If the {@link Network} is a VPN, whether apps are allowed to bypass the
+ * VPN. This is set by a {@link VpnService} and used by
+ * {@link ConnectivityManager} when creating a VPN.
*/
public boolean allowBypass;
@@ -41,6 +44,11 @@ public class NetworkMisc implements Parcelable {
*/
public boolean explicitlySelected;
+ /**
+ * For mobile networks, this is the subscriber ID (such as IMSI).
+ */
+ public String subscriberId;
+
public NetworkMisc() {
}
@@ -48,6 +56,7 @@ public class NetworkMisc implements Parcelable {
if (nm != null) {
allowBypass = nm.allowBypass;
explicitlySelected = nm.explicitlySelected;
+ subscriberId = nm.subscriberId;
}
}
@@ -60,6 +69,7 @@ public class NetworkMisc implements Parcelable {
public void writeToParcel(Parcel out, int flags) {
out.writeInt(allowBypass ? 1 : 0);
out.writeInt(explicitlySelected ? 1 : 0);
+ out.writeString(subscriberId);
}
public static final Creator<NetworkMisc> CREATOR = new Creator<NetworkMisc>() {
@@ -68,6 +78,7 @@ public class NetworkMisc implements Parcelable {
NetworkMisc networkMisc = new NetworkMisc();
networkMisc.allowBypass = in.readInt() != 0;
networkMisc.explicitlySelected = in.readInt() != 0;
+ networkMisc.subscriberId = in.readString();
return networkMisc;
}
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index 10c686b..e88bc26 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -35,7 +35,7 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
public static final long LIMIT_DISABLED = -1;
public static final long SNOOZE_NEVER = -1;
- public final NetworkTemplate template;
+ public NetworkTemplate template;
public int cycleDay;
public String cycleTimezone;
public long warningBytes;
diff --git a/core/java/android/net/NetworkState.java b/core/java/android/net/NetworkState.java
index d26c70d..933287f 100644
--- a/core/java/android/net/NetworkState.java
+++ b/core/java/android/net/NetworkState.java
@@ -30,16 +30,10 @@ public class NetworkState implements Parcelable {
public final LinkProperties linkProperties;
public final NetworkCapabilities networkCapabilities;
public final Network network;
- /** Currently only used by testing. */
public final String subscriberId;
public final String networkId;
public NetworkState(NetworkInfo networkInfo, LinkProperties linkProperties,
- NetworkCapabilities networkCapabilities, Network network) {
- this(networkInfo, linkProperties, networkCapabilities, network, null, null);
- }
-
- public NetworkState(NetworkInfo networkInfo, LinkProperties linkProperties,
NetworkCapabilities networkCapabilities, Network network, String subscriberId,
String networkId) {
this.networkInfo = networkInfo;
@@ -85,5 +79,4 @@ public class NetworkState implements Parcelable {
return new NetworkState[size];
}
};
-
}
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index b839e0a..57eef83 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -22,7 +22,6 @@ import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
import static android.net.ConnectivityManager.TYPE_WIMAX;
import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED;
-import static android.net.NetworkIdentity.scrubSubscriberId;
import static android.net.wifi.WifiInfo.removeDoubleQuotes;
import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G;
import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G;
@@ -36,7 +35,9 @@ import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
+import java.util.Arrays;
import java.util.Objects;
/**
@@ -48,7 +49,9 @@ import java.util.Objects;
public class NetworkTemplate implements Parcelable {
public static final int MATCH_MOBILE_ALL = 1;
+ @Deprecated
public static final int MATCH_MOBILE_3G_LOWER = 2;
+ @Deprecated
public static final int MATCH_MOBILE_4G = 3;
public static final int MATCH_WIFI = 4;
public static final int MATCH_ETHERNET = 5;
@@ -146,17 +149,35 @@ public class NetworkTemplate implements Parcelable {
private final int mMatchRule;
private final String mSubscriberId;
+
+ /**
+ * Ugh, templates are designed to target a single subscriber, but we might
+ * need to match several "merged" subscribers. These are the subscribers
+ * that should be considered to match this template.
+ * <p>
+ * Since the merge set is dynamic, it should <em>not</em> be persisted or
+ * used for determining equality.
+ */
+ private final String[] mMatchSubscriberIds;
+
private final String mNetworkId;
public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
+ this(matchRule, subscriberId, new String[] { subscriberId }, networkId);
+ }
+
+ public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
+ String networkId) {
mMatchRule = matchRule;
mSubscriberId = subscriberId;
+ mMatchSubscriberIds = matchSubscriberIds;
mNetworkId = networkId;
}
private NetworkTemplate(Parcel in) {
mMatchRule = in.readInt();
mSubscriberId = in.readString();
+ mMatchSubscriberIds = in.createStringArray();
mNetworkId = in.readString();
}
@@ -164,6 +185,7 @@ public class NetworkTemplate implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mMatchRule);
dest.writeString(mSubscriberId);
+ dest.writeStringArray(mMatchSubscriberIds);
dest.writeString(mNetworkId);
}
@@ -177,7 +199,12 @@ public class NetworkTemplate implements Parcelable {
final StringBuilder builder = new StringBuilder("NetworkTemplate: ");
builder.append("matchRule=").append(getMatchRuleName(mMatchRule));
if (mSubscriberId != null) {
- builder.append(", subscriberId=").append(scrubSubscriberId(mSubscriberId));
+ builder.append(", subscriberId=").append(
+ NetworkIdentity.scrubSubscriberId(mSubscriberId));
+ }
+ if (mMatchSubscriberIds != null) {
+ builder.append(", matchSubscriberIds=").append(
+ Arrays.toString(NetworkIdentity.scrubSubscriberId(mMatchSubscriberIds)));
}
if (mNetworkId != null) {
builder.append(", networkId=").append(mNetworkId);
@@ -201,6 +228,18 @@ public class NetworkTemplate implements Parcelable {
return false;
}
+ public boolean isMatchRuleMobile() {
+ switch (mMatchRule) {
+ case MATCH_MOBILE_3G_LOWER:
+ case MATCH_MOBILE_4G:
+ case MATCH_MOBILE_ALL:
+ case MATCH_MOBILE_WILDCARD:
+ return true;
+ default:
+ return false;
+ }
+ }
+
public int getMatchRule() {
return mMatchRule;
}
@@ -247,14 +286,16 @@ public class NetworkTemplate implements Parcelable {
// TODO: consider matching against WiMAX subscriber identity
return true;
} else {
- return ((sForceAllNetworkTypes || contains(DATA_USAGE_NETWORK_TYPES, ident.mType))
- && Objects.equals(mSubscriberId, ident.mSubscriberId));
+ final boolean matchesType = (sForceAllNetworkTypes
+ || contains(DATA_USAGE_NETWORK_TYPES, ident.mType));
+ return matchesType && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId);
}
}
/**
* Check if mobile network classified 3G or lower with matching IMSI.
*/
+ @Deprecated
private boolean matchesMobile3gLower(NetworkIdentity ident) {
ensureSubtypeAvailable();
if (ident.mType == TYPE_WIMAX) {
@@ -273,6 +314,7 @@ public class NetworkTemplate implements Parcelable {
/**
* Check if mobile network classified 4G with matching IMSI.
*/
+ @Deprecated
private boolean matchesMobile4g(NetworkIdentity ident) {
ensureSubtypeAvailable();
if (ident.mType == TYPE_WIMAX) {
@@ -368,6 +410,27 @@ public class NetworkTemplate implements Parcelable {
}
}
+ /**
+ * Examine the given template and normalize if it refers to a "merged"
+ * mobile subscriber. We pick the "lowest" merged subscriber as the primary
+ * for key purposes, and expand the template to match all other merged
+ * subscribers.
+ * <p>
+ * For example, given an incoming template matching B, and the currently
+ * active merge set [A,B], we'd return a new template that primarily matches
+ * A, but also matches B.
+ */
+ public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) {
+ if (template.isMatchRuleMobile() && ArrayUtils.contains(merged, template.mSubscriberId)) {
+ // Requested template subscriber is part of the merge group; return
+ // a template that matches all merged subscribers.
+ return new NetworkTemplate(template.mMatchRule, merged[0], merged,
+ template.mNetworkId);
+ } else {
+ return template;
+ }
+ }
+
public static final Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
@Override
public NetworkTemplate createFromParcel(Parcel in) {
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 9589aac..1b02141 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -329,7 +329,7 @@ public class BaseBundle {
* @param key a String, or null
* @param value a Boolean, or null
*/
- void putBoolean(String key, boolean value) {
+ public void putBoolean(String key, boolean value) {
unparcel();
mMap.put(key, value);
}
@@ -497,7 +497,7 @@ public class BaseBundle {
* @param key a String, or null
* @param value a boolean array object, or null
*/
- void putBooleanArray(String key, boolean[] value) {
+ public void putBooleanArray(String key, boolean[] value) {
unparcel();
mMap.put(key, value);
}
@@ -617,7 +617,7 @@ public class BaseBundle {
* @param key a String
* @return a boolean value
*/
- boolean getBoolean(String key) {
+ public boolean getBoolean(String key) {
unparcel();
if (DEBUG) Log.d(TAG, "Getting boolean in "
+ Integer.toHexString(System.identityHashCode(this)));
@@ -654,7 +654,7 @@ public class BaseBundle {
* @param defaultValue Value to return if key does not exist
* @return a boolean value
*/
- boolean getBoolean(String key, boolean defaultValue) {
+ public boolean getBoolean(String key, boolean defaultValue) {
unparcel();
Object o = mMap.get(key);
if (o == null) {
@@ -1072,7 +1072,7 @@ public class BaseBundle {
* @param key a String, or null
* @return a boolean[] value, or null
*/
- boolean[] getBooleanArray(String key) {
+ public boolean[] getBooleanArray(String key) {
unparcel();
Object o = mMap.get(key);
if (o == null) {
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index a9aa570..c5c5372 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -252,18 +252,6 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
}
/**
- * Inserts a Boolean value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value a Boolean, or null
- */
- @Override
- public void putBoolean(String key, boolean value) {
- super.putBoolean(key, value);
- }
-
- /**
* Inserts a byte value into the mapping of this Bundle, replacing
* any existing value for the given key.
*
@@ -460,18 +448,6 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
}
/**
- * Inserts a boolean array value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value a boolean array object, or null
- */
- @Override
- public void putBooleanArray(String key, boolean[] value) {
- super.putBooleanArray(key, value);
- }
-
- /**
* Inserts a byte array value into the mapping of this Bundle, replacing
* any existing value for the given key. Either key or value may be null.
*
@@ -579,31 +555,6 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
}
/**
- * Returns the value associated with the given key, or false if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @return a boolean value
- */
- @Override
- public boolean getBoolean(String key) {
- return super.getBoolean(key);
- }
-
- /**
- * Returns the value associated with the given key, or defaultValue if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @param defaultValue Value to return if key does not exist
- * @return a boolean value
- */
- @Override
- public boolean getBoolean(String key, boolean defaultValue) {
- return super.getBoolean(key, defaultValue);
- }
-
- /**
* Returns the value associated with the given key, or (byte) 0 if
* no mapping of the desired type exists for the given key.
*
@@ -939,19 +890,6 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
* value is explicitly associated with the key.
*
* @param key a String, or null
- * @return a boolean[] value, or null
- */
- @Override
- public boolean[] getBooleanArray(String key) {
- return super.getBooleanArray(key);
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
* @return a byte[] value, or null
*/
@Override
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 3f42d25..a9deaf3 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -168,7 +168,7 @@ public final class Debug
public static final int NUM_OTHER_STATS = 17;
/** @hide */
- public static final int NUM_DVK_STATS = 5;
+ public static final int NUM_DVK_STATS = 8;
/** @hide */
public static final int NUM_CATEGORIES = 7;
@@ -314,6 +314,9 @@ public final class Debug
case 19: return ".LinearAlloc";
case 20: return ".GC";
case 21: return ".JITCache";
+ case 22: return ".Zygote";
+ case 23: return ".NonMoving";
+ case 24: return ".IndirectRef";
default: return "????";
}
}
@@ -1071,9 +1074,10 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo
/**
* Retrieves the PSS memory used by the process as given by the
* smaps. Optionally supply a long array of 1 entry to also
- * receive the uss of the process. @hide
+ * receive the uss of the process, and another array to also
+ * retrieve the separate memtrack size. @hide
*/
- public static native long getPss(int pid, long[] outUss);
+ public static native long getPss(int pid, long[] outUss, long[] outMemtrack);
/** @hide */
public static final int MEMINFO_TOTAL = 0;
diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java
index c01f688..3a44428 100644
--- a/core/java/android/os/PersistableBundle.java
+++ b/core/java/android/os/PersistableBundle.java
@@ -96,7 +96,8 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa
!(value instanceof Double) && !(value instanceof String) &&
!(value instanceof int[]) && !(value instanceof long[]) &&
!(value instanceof double[]) && !(value instanceof String[]) &&
- !(value instanceof PersistableBundle) && (value != null)) {
+ !(value instanceof PersistableBundle) && (value != null) &&
+ !(value instanceof Boolean) && !(value instanceof boolean[])) {
throw new IllegalArgumentException("Bad value in PersistableBundle key=" + key +
" value=" + value);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0062eb2..555f64c 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6128,7 +6128,7 @@ public final class Settings {
/**
* The number of milliseconds to delay before sending out
- * {@link ConnectivityManager#CONNECTIVITY_ACTION} broadcasts.
+ * {@link ConnectivityManager#CONNECTIVITY_ACTION} broadcasts. Ignored.
*
* @hide
*/
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index ce28d0a..979a01b 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -64,7 +64,7 @@ public class ZenModeConfig implements Parcelable {
public static final int[] MINUTE_BUCKETS = new int[] { 15, 30, 45, 60, 120, 180, 240, 480 };
private static final int SECONDS_MS = 1000;
private static final int MINUTES_MS = 60 * SECONDS_MS;
- private static final int ZERO_VALUE_MS = 20 * SECONDS_MS;
+ private static final int ZERO_VALUE_MS = 10 * SECONDS_MS;
private static final boolean DEFAULT_ALLOW_EVENTS = true;
@@ -471,6 +471,8 @@ public class ZenModeConfig implements Parcelable {
downtime.startMinute = sleepStartMinute;
downtime.endHour = sleepEndHour;
downtime.endMinute = sleepEndMinute;
+ downtime.mode = sleepMode;
+ downtime.none = sleepNone;
return downtime;
}
@@ -510,7 +512,7 @@ public class ZenModeConfig implements Parcelable {
public static final String SYSTEM_AUTHORITY = "android";
// Built-in countdown conditions, e.g. condition://android/countdown/1399917958951
- private static final String COUNTDOWN_PATH = "countdown";
+ public static final String COUNTDOWN_PATH = "countdown";
public static Uri toCountdownConditionId(long time) {
return new Uri.Builder().scheme(Condition.SCHEME)
@@ -536,8 +538,9 @@ public class ZenModeConfig implements Parcelable {
return tryParseCountdownConditionId(conditionId) != 0;
}
- // Built-in downtime conditions, e.g. condition://android/downtime?start=10.00&end=7.00
- private static final String DOWNTIME_PATH = "downtime";
+ // Built-in downtime conditions
+ // e.g. condition://android/downtime?start=10.00&end=7.00&mode=days%3A5%2C6&none=false
+ public static final String DOWNTIME_PATH = "downtime";
public static Uri toDowntimeConditionId(DowntimeInfo downtime) {
return new Uri.Builder().scheme(Condition.SCHEME)
@@ -545,6 +548,8 @@ public class ZenModeConfig implements Parcelable {
.appendPath(DOWNTIME_PATH)
.appendQueryParameter("start", downtime.startHour + "." + downtime.startMinute)
.appendQueryParameter("end", downtime.endHour + "." + downtime.endMinute)
+ .appendQueryParameter("mode", downtime.mode)
+ .appendQueryParameter("none", Boolean.toString(downtime.none))
.build();
}
@@ -562,6 +567,8 @@ public class ZenModeConfig implements Parcelable {
downtime.startMinute = start[1];
downtime.endHour = end[0];
downtime.endMinute = end[1];
+ downtime.mode = conditionId.getQueryParameter("mode");
+ downtime.none = Boolean.toString(true).equals(conditionId.getQueryParameter("none"));
return downtime;
}
@@ -583,6 +590,8 @@ public class ZenModeConfig implements Parcelable {
public int startMinute; // 0-59
public int endHour;
public int endMinute;
+ public String mode;
+ public boolean none;
@Override
public int hashCode() {
@@ -596,7 +605,12 @@ public class ZenModeConfig implements Parcelable {
return startHour == other.startHour
&& startMinute == other.startMinute
&& endHour == other.endHour
- && endMinute == other.endMinute;
+ && endMinute == other.endMinute
+ && Objects.equals(mode, other.mode)
+ && none == other.none;
}
}
+
+ // built-in next alarm conditions
+ public static final String NEXT_ALARM_PATH = "next_alarm";
}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 67f632f..9496b53 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -691,8 +691,8 @@ public abstract class WallpaperService extends Service {
if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface
+ ", frame=" + mWinFrame);
- int w = mWinFrame.width() + mOverscanInsets.left + mOverscanInsets.right;
- int h = mWinFrame.height() + mOverscanInsets.top + mOverscanInsets.bottom;
+ int w = mWinFrame.width();
+ int h = mWinFrame.height();
if (!fixedSize) {
final Rect padding = mIWallpaperEngine.mDisplayPadding;
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index 7feca30..7b35a3b 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -148,6 +148,10 @@ public class RenderNodeAnimator extends Animator {
if (mState != STATE_PREPARE) {
throw new IllegalStateException("Animator has already started, cannot change it now!");
}
+ if (mNativePtr == null) {
+ throw new IllegalStateException("Animator's target has been destroyed "
+ + "(trying to modify an animation after activity destroy?)");
+ }
}
static boolean isNativeInterpolator(TimeInterpolator interpolator) {
@@ -180,7 +184,10 @@ public class RenderNodeAnimator extends Animator {
mState = STATE_DELAYED;
applyInterpolator();
- if (mStartDelay <= 0 || !mUiThreadHandlesDelay) {
+ if (mNativePtr == null) {
+ // It's dead, immediately cancel
+ cancel();
+ } else if (mStartDelay <= 0 || !mUiThreadHandlesDelay) {
nSetStartDelay(mNativePtr.get(), mStartDelay);
doStart();
} else {
@@ -208,7 +215,9 @@ public class RenderNodeAnimator extends Animator {
private void moveToRunningState() {
mState = STATE_RUNNING;
- nStart(mNativePtr.get(), this);
+ if (mNativePtr != null) {
+ nStart(mNativePtr.get());
+ }
notifyStartListeners();
}
@@ -227,7 +236,6 @@ public class RenderNodeAnimator extends Animator {
getHelper().removeDelayedAnimation(this);
moveToRunningState();
}
- nEnd(mNativePtr.get());
final ArrayList<AnimatorListener> listeners = cloneListeners();
final int numListeners = listeners == null ? 0 : listeners.size();
@@ -235,10 +243,7 @@ public class RenderNodeAnimator extends Animator {
listeners.get(i).onAnimationCancel(this);
}
- if (mViewTarget != null) {
- // Kick off a frame to flush the state change
- mViewTarget.invalidateViewProperty(true, false);
- }
+ end();
}
}
@@ -249,10 +254,15 @@ public class RenderNodeAnimator extends Animator {
getHelper().removeDelayedAnimation(this);
doStart();
}
- nEnd(mNativePtr.get());
- if (mViewTarget != null) {
- // Kick off a frame to flush the state change
- mViewTarget.invalidateViewProperty(true, false);
+ if (mNativePtr != null) {
+ nEnd(mNativePtr.get());
+ if (mViewTarget != null) {
+ // Kick off a frame to flush the state change
+ mViewTarget.invalidateViewProperty(true, false);
+ }
+ } else {
+ // It's already dead, jump to onFinish
+ onFinished();
}
}
}
@@ -281,9 +291,11 @@ public class RenderNodeAnimator extends Animator {
}
private void setTarget(RenderNode node) {
+ checkMutable();
if (mTarget != null) {
throw new IllegalStateException("Target already set!");
}
+ nSetListener(mNativePtr.get(), this);
mTarget = node;
mTarget.addAnimator(this);
}
@@ -346,6 +358,12 @@ public class RenderNodeAnimator extends Animator {
}
protected void onFinished() {
+ if (mState == STATE_PREPARE) {
+ // Unlikely but possible, the native side has been destroyed
+ // before we have started.
+ releaseNativePtr();
+ return;
+ }
if (mState == STATE_DELAYED) {
getHelper().removeDelayedAnimation(this);
notifyStartListeners();
@@ -361,8 +379,14 @@ public class RenderNodeAnimator extends Animator {
// Release the native object, as it has a global reference to us. This
// breaks the cyclic reference chain, and allows this object to be
// GC'd
- mNativePtr.release();
- mNativePtr = null;
+ releaseNativePtr();
+ }
+
+ private void releaseNativePtr() {
+ if (mNativePtr != null) {
+ mNativePtr.release();
+ mNativePtr = null;
+ }
}
@SuppressWarnings("unchecked")
@@ -484,7 +508,8 @@ public class RenderNodeAnimator extends Animator {
private static native void nSetStartDelay(long nativePtr, long startDelay);
private static native void nSetInterpolator(long animPtr, long interpolatorPtr);
private static native void nSetAllowRunningAsync(long animPtr, boolean mayRunAsync);
+ private static native void nSetListener(long animPtr, RenderNodeAnimator listener);
- private static native void nStart(long animPtr, RenderNodeAnimator finishListener);
+ private static native void nStart(long animPtr);
private static native void nEnd(long animPtr);
}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 14b950f..ad4a048 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -37,6 +37,7 @@ import android.view.View.AttachInfo;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.HashSet;
/**
@@ -465,11 +466,13 @@ public class ThreadedRenderer extends HardwareRenderer {
final LongSparseArray<Drawable.ConstantState> drawables = resources.getPreloadedDrawables();
final int count = drawables.size();
+ ArrayList<Bitmap> tmpList = new ArrayList<Bitmap>();
for (int i = 0; i < count; i++) {
- final Bitmap bitmap = drawables.valueAt(i).getBitmap();
- if (bitmap != null && bitmap.getConfig() == Bitmap.Config.ARGB_8888) {
- preloadedPointers.add(bitmap.mNativeBitmap);
+ drawables.valueAt(i).addAtlasableBitmaps(tmpList);
+ for (int j = 0; j < tmpList.size(); j++) {
+ preloadedPointers.add(tmpList.get(j).mNativeBitmap);
}
+ tmpList.clear();
}
for (int i = 0; i < map.length; i += 4) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b54d462..2bb1ebc 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5938,9 +5938,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* layer.
*
* @param outRects List to which to add clickable areas.
+ *
+ * @hide
*/
- void addClickableRectsForAccessibility(List<RectF> outRects) {
- if (isClickable() || isLongClickable()) {
+ public void addClickableRectsForAccessibility(List<RectF> outRects) {
+ if (isClickable() || isLongClickable()
+ || (mListenerInfo != null && mListenerInfo.mOnTouchListener != null)) {
RectF bounds = new RectF();
bounds.set(0, 0, getWidth(), getHeight());
outRects.add(bounds);
@@ -16059,7 +16062,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* This function is called whenever the view hotspot changes and needs to
- * be propagated to drawables managed by the view.
+ * be propagated to drawables or child views managed by the view.
+ * <p>
+ * Dispatching to child views is handled by
+ * {@link #dispatchDrawableHotspotChanged(float, float)}.
* <p>
* Be sure to call through to the superclass when overriding this function.
*
@@ -16070,6 +16076,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mBackground != null) {
mBackground.setHotspot(x, y);
}
+
+ dispatchDrawableHotspotChanged(x, y);
+ }
+
+ /**
+ * Dispatches drawableHotspotChanged to all of this View's children.
+ *
+ * @param x hotspot x coordinate
+ * @param y hotspot y coordinate
+ * @see #drawableHotspotChanged(float, float)
+ */
+ public void dispatchDrawableHotspotChanged(float x, float y) {
}
/**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 1551504..25a70eb 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -161,6 +161,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
// Used during drag dispatch
private PointF mLocalPoint;
+ // Lazily-created holder for point computations.
+ private float[] mTempPoint;
+
// Layout animation
private LayoutAnimationController mLayoutAnimationController;
private Animation.AnimationListener mAnimationListener;
@@ -880,8 +883,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
return true;
}
+ /**
+ * @hide
+ */
@Override
- void addClickableRectsForAccessibility(List<RectF> outRects) {
+ public void addClickableRectsForAccessibility(List<RectF> outRects) {
int sizeBefore = outRects.size();
super.addClickableRectsForAccessibility(outRects);
@@ -2442,6 +2448,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|| child.getAnimation() != null;
}
+ private float[] getTempPoint() {
+ if (mTempPoint == null) {
+ mTempPoint = new float[2];
+ }
+ return mTempPoint;
+ }
+
/**
* Returns true if a child view contains the specified point when transformed
* into its coordinate space.
@@ -2450,24 +2463,30 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*/
protected boolean isTransformedTouchPointInView(float x, float y, View child,
PointF outLocalPoint) {
- float localX = x + mScrollX - child.mLeft;
- float localY = y + mScrollY - child.mTop;
- if (! child.hasIdentityMatrix() && mAttachInfo != null) {
- final float[] localXY = mAttachInfo.mTmpTransformLocation;
- localXY[0] = localX;
- localXY[1] = localY;
- child.getInverseMatrix().mapPoints(localXY);
- localX = localXY[0];
- localY = localXY[1];
- }
- final boolean isInView = child.pointInView(localX, localY);
+ final float[] point = getTempPoint();
+ point[0] = x;
+ point[1] = y;
+ transformPointToViewLocal(point, child);
+ final boolean isInView = child.pointInView(point[0], point[1]);
if (isInView && outLocalPoint != null) {
- outLocalPoint.set(localX, localY);
+ outLocalPoint.set(point[0], point[1]);
}
return isInView;
}
/**
+ * @hide
+ */
+ public void transformPointToViewLocal(float[] point, View child) {
+ point[0] += mScrollX - child.mLeft;
+ point[1] += mScrollY - child.mTop;
+
+ if (!child.hasIdentityMatrix()) {
+ child.getInverseMatrix().mapPoints(point);
+ }
+ }
+
+ /**
* Transforms a motion event into the coordinate space of a particular child view,
* filters out irrelevant pointer ids, and overrides its action if necessary.
* If child is null, assumes the MotionEvent will be sent to this ViewGroup instead.
@@ -3606,6 +3625,44 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
}
+ /**
+ * Dispatches drawable hotspot changes to child views that meet at least
+ * one of the following criteria:
+ * <ul>
+ * <li>Returns {@code false} from both {@link View#isClickable()} and
+ * {@link View#isLongClickable()}</li>
+ * <li>Requests duplication of parent state via
+ * {@link View#setDuplicateParentStateEnabled(boolean)}</li>
+ * </ul>
+ *
+ * @param x hotspot x coordinate
+ * @param y hotspot y coordinate
+ * @see #drawableHotspotChanged(float, float)
+ */
+ @Override
+ public void dispatchDrawableHotspotChanged(float x, float y) {
+ final int count = mChildrenCount;
+ if (count == 0) {
+ return;
+ }
+
+ final View[] children = mChildren;
+ for (int i = 0; i < count; i++) {
+ final View child = children[i];
+ // Children that are clickable on their own should not
+ // receive hotspots when their parent view does.
+ final boolean nonActionable = !child.isClickable() && !child.isLongClickable();
+ final boolean duplicatesState = (child.mViewFlags & DUPLICATE_PARENT_STATE) != 0;
+ if (nonActionable || duplicatesState) {
+ final float[] point = getTempPoint();
+ point[0] = x;
+ point[1] = y;
+ transformPointToViewLocal(point, child);
+ child.drawableHotspotChanged(point[0], point[1]);
+ }
+ }
+ }
+
@Override
void dispatchCancelPendingInputEvents() {
super.dispatchCancelPendingInputEvents();
@@ -5961,28 +6018,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
@Override
- public void drawableHotspotChanged(float x, float y) {
- super.drawableHotspotChanged(x, y);
-
- if ((mGroupFlags & FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE) != 0) {
- if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) != 0) {
- throw new IllegalStateException("addStateFromChildren cannot be enabled if a"
- + " child has duplicateParentState set to true");
- }
-
- final View[] children = mChildren;
- final int count = mChildrenCount;
-
- for (int i = 0; i < count; i++) {
- final View child = children[i];
- if ((child.mViewFlags & DUPLICATE_PARENT_STATE) != 0) {
- child.drawableHotspotChanged(x, y);
- }
- }
- }
- }
-
- @Override
protected int[] onCreateDrawableState(int extraSpace) {
if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) == 0) {
return super.onCreateDrawableState(extraSpace);
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index a218e4d..52912b1 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -78,6 +78,7 @@ final class AccessibilityCache {
case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED:
case AccessibilityEvent.TYPE_VIEW_SELECTED:
case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED:
+ case AccessibilityEvent.TYPE_VIEW_CLICKED:
case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
refreshCachedNodeLocked(event.getWindowId(), event.getSourceNodeId());
} break;
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 6927660..d80ad6a 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Canvas;
+import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
@@ -611,6 +612,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
private final int[] mScrollOffset = new int[2];
private final int[] mScrollConsumed = new int[2];
+ private final float[] mTmpPoint = new float[2];
+
// Used for offsetting MotionEvents that we feed to the VelocityTracker.
// In the future it would be nice to be able to give this to the VelocityTracker
// directly, or alternatively put a VT into absolute-positioning mode that only
@@ -2509,38 +2512,29 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
* Positions the selector in a way that mimics touch.
*/
void positionSelectorLikeTouch(int position, View sel, float x, float y) {
- positionSelectorLikeFocus(position, sel);
-
- if (mSelector != null && position != INVALID_POSITION) {
- mSelector.setHotspot(x, y);
- }
+ positionSelector(position, sel, true, x, y);
}
/**
* Positions the selector in a way that mimics keyboard focus.
*/
void positionSelectorLikeFocus(int position, View sel) {
- // If we're changing position, update the visibility since the selector
- // is technically being detached from the previous selection.
- final Drawable selector = mSelector;
- final boolean manageState = selector != null && mSelectorPosition != position
- && position != INVALID_POSITION;
- if (manageState) {
- selector.setVisible(false, false);
- }
-
- positionSelector(position, sel);
-
- if (manageState) {
+ if (mSelector != null && mSelectorPosition != position && position != INVALID_POSITION) {
final Rect bounds = mSelectorRect;
final float x = bounds.exactCenterX();
final float y = bounds.exactCenterY();
- selector.setVisible(getVisibility() == VISIBLE, false);
- selector.setHotspot(x, y);
+ positionSelector(position, sel, true, x, y);
+ } else {
+ positionSelector(position, sel);
}
}
void positionSelector(int position, View sel) {
+ positionSelector(position, sel, false, -1, -1);
+ }
+
+ private void positionSelector(int position, View sel, boolean manageHotspot, float x, float y) {
+ final boolean positionChanged = position != mSelectorPosition;
if (position != INVALID_POSITION) {
mSelectorPosition = position;
}
@@ -2560,7 +2554,22 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
// Update the selector drawable.
final Drawable selector = mSelector;
if (selector != null) {
+ if (positionChanged) {
+ // Wipe out the current selector state so that we can start
+ // over in the new position with a fresh state.
+ selector.setVisible(false, false);
+ selector.setState(StateSet.NOTHING);
+ }
selector.setBounds(selectorRect);
+ if (positionChanged) {
+ if (getVisibility() == VISIBLE) {
+ selector.setVisible(true, false);
+ }
+ selector.setState(getDrawableState());
+ }
+ if (manageHotspot) {
+ selector.setHotspot(x, y);
+ }
}
final boolean isChildViewEnabled = mIsChildViewEnabled;
@@ -3198,6 +3207,12 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
// get the selector in the right state, but we don't want to press each child.
}
+ @Override
+ public void dispatchDrawableHotspotChanged(float x, float y) {
+ // Don't dispatch hotspot changes to children. We'll manually handle
+ // calling drawableHotspotChanged on the correct child.
+ }
+
/**
* Maps a point to a position in the list.
*
@@ -3256,6 +3271,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mLayoutMode = LAYOUT_NORMAL;
if (!mDataChanged) {
+ final float[] point = mTmpPoint;
+ point[0] = x;
+ point[1] = y;
+ transformPointToViewLocal(point, child);
+ child.drawableHotspotChanged(point[0], point[1]);
child.setPressed(true);
setPressed(true);
layoutChildren();
@@ -3756,10 +3776,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
// Otherwise, check containment within list bounds. If we're
// outside bounds, cancel any active presses.
+ final View motionView = getChildAt(mMotionPosition - mFirstPosition);
final float x = ev.getX(pointerIndex);
if (!pointInView(x, y, mTouchSlop)) {
setPressed(false);
- final View motionView = getChildAt(mMotionPosition - mFirstPosition);
if (motionView != null) {
motionView.setPressed(false);
}
@@ -3767,6 +3787,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mPendingCheckForTap : mPendingCheckForLongPress);
mTouchMode = TOUCH_MODE_DONE_WAITING;
updateSelectorState();
+ } else if (motionView != null) {
+ // Still within bounds, update the hotspot.
+ final float[] point = mTmpPoint;
+ point[0] = x;
+ point[1] = y;
+ transformPointToViewLocal(point, motionView);
+ motionView.drawableHotspotChanged(point[0], point[1]);
}
break;
case TOUCH_MODE_SCROLL:
@@ -6416,6 +6443,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
// Note: We do place AdapterView.ITEM_VIEW_TYPE_IGNORE in active views.
// However, we will NOT place them into scrap views.
activeViews[i] = child;
+ // Remember the position so that setupChild() doesn't reset state.
+ lp.scrappedFromPosition = firstActivePosition + i;
}
}
}
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 0c65c50..371b480 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
@@ -757,10 +758,22 @@ public class HorizontalScrollView extends FrameLayout {
} else {
super.scrollTo(scrollX, scrollY);
}
-
+
awakenScrollBars();
}
+ /**
+ * @hide
+ */
+ @Override
+ public void addClickableRectsForAccessibility(List<RectF> outRects) {
+ // This class always consumes touch events, therefore if it
+ // covers a view we do not want to send a click over it.
+ RectF bounds = new RectF();
+ bounds.set(0, 0, getWidth(), getHeight());
+ outRects.add(bounds);
+ }
+
@Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
if (super.performAccessibilityAction(action, arguments)) {
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index a31d37e..fe8b08b 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -1385,7 +1385,9 @@ public class ListPopupWindow {
clearCallbacks();
final View src = mSrc;
- if (!src.isEnabled()) {
+ if (!src.isEnabled() || src.isLongClickable()) {
+ // Ignore long-press if the view is disabled or has its own
+ // handler.
return;
}
@@ -1394,12 +1396,12 @@ public class ListPopupWindow {
}
// Don't let the parent intercept our events.
- mSrc.getParent().requestDisallowInterceptTouchEvent(true);
+ src.getParent().requestDisallowInterceptTouchEvent(true);
// Make sure we cancel any ongoing source event stream.
final long now = SystemClock.uptimeMillis();
final MotionEvent e = MotionEvent.obtain(now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0);
- mSrc.onTouchEvent(e);
+ src.onTouchEvent(e);
e.recycle();
mForwarding = true;
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index 04b5616..75c6184 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -1246,37 +1246,40 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
}
final int[] selectionDegrees = mSelectionDegrees;
- int type = -1;
- int newValue = -1;
+ final int type;
+ final int newValue;
+ final boolean valueChanged;
if (mShowHours) {
final int snapDegrees = snapOnly30s(degrees, 0) % 360;
- if (forceSelection
- || selectionDegrees[HOURS] != snapDegrees
+ valueChanged = selectionDegrees[HOURS] != snapDegrees
|| selectionDegrees[HOURS_INNER] != snapDegrees
- || wasOnInnerCircle != mIsOnInnerCircle) {
- selectionDegrees[HOURS] = snapDegrees;
- selectionDegrees[HOURS_INNER] = snapDegrees;
+ || wasOnInnerCircle != mIsOnInnerCircle;
- type = HOURS;
- newValue = getCurrentHour();
- }
+ selectionDegrees[HOURS] = snapDegrees;
+ selectionDegrees[HOURS_INNER] = snapDegrees;
+ type = HOURS;
+ newValue = getCurrentHour();
} else {
final int snapDegrees = snapPrefer30s(degrees) % 360;
- if (forceSelection || selectionDegrees[MINUTES] != snapDegrees) {
- selectionDegrees[MINUTES] = snapDegrees;
+ valueChanged = selectionDegrees[MINUTES] != snapDegrees;
- type = MINUTES;
- newValue = getCurrentMinute();
- }
+ selectionDegrees[MINUTES] = snapDegrees;
+ type = MINUTES;
+ newValue = getCurrentMinute();
}
- if (newValue != -1) {
+ if (valueChanged || forceSelection || autoAdvance) {
+ // Fire the listener even if we just need to auto-advance.
if (mListener != null) {
mListener.onValueSelected(type, newValue, autoAdvance);
}
- performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
- invalidate();
+
+ // Only provide feedback if the value actually changed.
+ if (valueChanged || forceSelection) {
+ performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
+ invalidate();
+ }
return true;
}
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 4c8aa51..7a22224 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -689,6 +689,10 @@ public class Switch extends CompoundButton {
* @return true if (x, y) is within the target area of the switch thumb
*/
private boolean hitThumb(float x, float y) {
+ if (mThumbDrawable == null) {
+ return false;
+ }
+
// Relies on mTempRect, MUST be called first!
final int thumbOffset = getThumbOffset();