diff options
Diffstat (limited to 'core')
27 files changed, 417 insertions, 118 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 1ed709b..cf06cb7 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -2933,9 +2933,9 @@ public class DevicePolicyManager { * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageNames List of input method package names. - * @return true if setting the restriction succeeded. It will fail if there is - * one or more input method enabled, that are not in the list or user if the foreground - * user. + * @return true if setting the restriction succeeded. It will fail if there are + * one or more non-system input methods currently enabled that are not in + * the packageNames list. */ public boolean setPermittedInputMethods(ComponentName admin, List<String> packageNames) { if (mService != null) { diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index c262bae..b8f4bf8 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -1429,14 +1429,16 @@ public final class BluetoothAdapter { if (VDBG) Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService); synchronized (mManagerCallback) { mService = bluetoothService; - for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){ - try { - if (cb != null) { - cb.onBluetoothServiceUp(bluetoothService); - } else { - Log.d(TAG, "onBluetoothServiceUp: cb is null!!!"); - } - } catch (Exception e) { Log.e(TAG,"",e);} + synchronized (mProxyServiceStateCallbacks) { + for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){ + try { + if (cb != null) { + cb.onBluetoothServiceUp(bluetoothService); + } else { + Log.d(TAG, "onBluetoothServiceUp: cb is null!!!"); + } + } catch (Exception e) { Log.e(TAG,"",e);} + } } } } @@ -1448,14 +1450,16 @@ public final class BluetoothAdapter { if (mLeScanClients != null) mLeScanClients.clear(); if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup(); if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup(); - for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){ - try { - if (cb != null) { - cb.onBluetoothServiceDown(); - } else { - Log.d(TAG, "onBluetoothServiceDown: cb is null!!!"); - } - } catch (Exception e) { Log.e(TAG,"",e);} + synchronized (mProxyServiceStateCallbacks) { + for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){ + try { + if (cb != null) { + cb.onBluetoothServiceDown(); + } else { + Log.d(TAG, "onBluetoothServiceDown: cb is null!!!"); + } + } catch (Exception e) { Log.e(TAG,"",e);} + } } } } @@ -1596,10 +1600,10 @@ public final class BluetoothAdapter { return mManagerService; } - private ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks = new ArrayList<IBluetoothManagerCallback>(); + final private ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks = new ArrayList<IBluetoothManagerCallback>(); /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) { - synchronized (mManagerCallback) { + synchronized (mProxyServiceStateCallbacks) { if (cb == null) { Log.w(TAG, "getBluetoothService() called with no BluetoothManagerCallback"); } else if (!mProxyServiceStateCallbacks.contains(cb)) { @@ -1610,7 +1614,7 @@ public final class BluetoothAdapter { } /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) { - synchronized (mManagerCallback) { + synchronized (mProxyServiceStateCallbacks) { mProxyServiceStateCallbacks.remove(cb); } } diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index 5e50b69..bb0d0a3 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -18,6 +18,7 @@ package android.bluetooth; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SystemApi; import android.content.Context; import android.os.Parcel; import android.os.Parcelable; @@ -67,6 +68,14 @@ public final class BluetoothDevice implements Parcelable { private static final boolean DBG = false; /** + * Connection state bitmask as returned by getConnectionState. + */ + private static final int CONNECTION_STATE_DISCONNECTED = 0; + private static final int CONNECTION_STATE_CONNECTED = 1; + private static final int CONNECTION_STATE_ENCRYPTED_BREDR = 2; + private static final int CONNECTION_STATE_ENCRYPTED_LE = 4; + + /** * Sentinel error value for this class. Guaranteed to not equal any other * integer constant in this class. Provided as a convenience for functions * that require a sentinel error value, for example: @@ -940,13 +949,36 @@ public final class BluetoothDevice implements Parcelable { * @return True if there is at least one open connection to this device. * @hide */ + @SystemApi public boolean isConnected() { if (sService == null) { // BT is not enabled, we cannot be connected. return false; } try { - return sService.isConnected(this); + return sService.getConnectionState(this) != CONNECTION_STATE_DISCONNECTED; + } catch (RemoteException e) { + Log.e(TAG, "", e); + return false; + } + } + + /** + * Returns whether there is an open connection to this device + * that has been encrypted. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. + * + * @return True if there is at least one encrypted connection to this device. + * @hide + */ + @SystemApi + public boolean isEncrypted() { + if (sService == null) { + // BT is not enabled, we cannot be connected. + return false; + } + try { + return sService.getConnectionState(this) > CONNECTION_STATE_CONNECTED; } catch (RemoteException e) { Log.e(TAG, "", e); return false; diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl index cd4535a..dabb1ce 100644 --- a/core/java/android/bluetooth/IBluetooth.aidl +++ b/core/java/android/bluetooth/IBluetooth.aidl @@ -59,7 +59,7 @@ interface IBluetooth boolean cancelBondProcess(in BluetoothDevice device); boolean removeBond(in BluetoothDevice device); int getBondState(in BluetoothDevice device); - boolean isConnected(in BluetoothDevice device); + int getConnectionState(in BluetoothDevice device); String getRemoteName(in BluetoothDevice device); int getRemoteType(in BluetoothDevice device); diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java index 4a743a5..391ef22 100644 --- a/core/java/android/content/pm/RegisteredServicesCache.java +++ b/core/java/android/content/pm/RegisteredServicesCache.java @@ -35,6 +35,7 @@ import android.util.SparseArray; import android.util.Xml; import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastXmlSerializer; import com.google.android.collect.Lists; import com.google.android.collect.Maps; @@ -155,9 +156,19 @@ public abstract class RegisteredServicesCache<V> { // package is going away, but it's the middle of an upgrade: keep the current // state and do nothing here. This clause is intentionally empty. } else { + int[] uids = null; // either we're adding/changing, or it's a removal without replacement, so - // we need to recalculate the set of available services - generateServicesMap(userId); + // we need to update the set of available services + if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action) + || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) { + uids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST); + } else { + int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); + if (uid > 0) { + uids = new int[] { uid }; + } + } + generateServicesMap(uids, userId); } } @@ -270,7 +281,7 @@ public abstract class RegisteredServicesCache<V> { // Find user and lazily populate cache final UserServices<V> user = findOrCreateUserLocked(userId); if (user.services == null) { - generateServicesMap(userId); + generateServicesMap(null, userId); } return user.services.get(type); } @@ -285,7 +296,7 @@ public abstract class RegisteredServicesCache<V> { // Find user and lazily populate cache final UserServices<V> user = findOrCreateUserLocked(userId); if (user.services == null) { - generateServicesMap(userId); + generateServicesMap(null, userId); } return Collections.unmodifiableCollection( new ArrayList<ServiceInfo<V>>(user.services.values())); @@ -311,10 +322,13 @@ public abstract class RegisteredServicesCache<V> { /** * Populate {@link UserServices#services} by scanning installed packages for * given {@link UserHandle}. + * @param changedUids the array of uids that have been affected, as mentioned in the broadcast + * or null to assume that everything is affected. + * @param userId the user for whom to update the services map. */ - private void generateServicesMap(int userId) { + private void generateServicesMap(int[] changedUids, int userId) { if (DEBUG) { - Slog.d(TAG, "generateServicesMap() for " + userId); + Slog.d(TAG, "generateServicesMap() for " + userId + ", changed UIDs = " + changedUids); } final PackageManager pm = mContext.getPackageManager(); @@ -341,8 +355,6 @@ public abstract class RegisteredServicesCache<V> { final boolean firstScan = user.services == null; if (firstScan) { user.services = Maps.newHashMap(); - } else { - user.services.clear(); } StringBuilder changes = new StringBuilder(); @@ -399,7 +411,10 @@ public abstract class RegisteredServicesCache<V> { ArrayList<V> toBeRemoved = Lists.newArrayList(); for (V v1 : user.persistentServices.keySet()) { - if (!containsType(serviceInfos, v1)) { + // Remove a persisted service that's not in the currently available services list. + // And only if it is in the list of changedUids. + if (!containsType(serviceInfos, v1) + && containsUid(changedUids, user.persistentServices.get(v1))) { toBeRemoved.add(v1); } } @@ -409,9 +424,20 @@ public abstract class RegisteredServicesCache<V> { } changed = true; user.persistentServices.remove(v1); + user.services.remove(v1); notifyListener(v1, userId, true /* removed */); } if (DEBUG) { + Log.d(TAG, "user.services="); + for (V v : user.services.keySet()) { + Log.d(TAG, " " + v + " " + user.services.get(v)); + } + Log.d(TAG, "user.persistentServices="); + for (V v : user.persistentServices.keySet()) { + Log.d(TAG, " " + v + " " + user.persistentServices.get(v)); + } + } + if (DEBUG) { if (changes.length() > 0) { Log.d(TAG, "generateServicesMap(" + mInterfaceName + "): " + serviceInfos.size() + " services:\n" + changes); @@ -426,6 +452,14 @@ public abstract class RegisteredServicesCache<V> { } } + /** + * Returns true if the list of changed uids is null (wildcard) or the specified uid + * is contained in the list of changed uids. + */ + private boolean containsUid(int[] changedUids, int uid) { + return changedUids == null || ArrayUtils.contains(changedUids, uid); + } + private boolean containsType(ArrayList<ServiceInfo<V>> serviceInfos, V type) { for (int i = 0, N = serviceInfos.size(); i < N; i++) { if (serviceInfos.get(i).type.equals(type)) { diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 1b621d1..7cf8fb0 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -391,10 +391,12 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * {@link CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION android.control.aeExposureCompensation}, in counts of {@link CameraCharacteristics#CONTROL_AE_COMPENSATION_STEP android.control.aeCompensationStep}, * that are supported by this camera device.</p> * <p><b>Range of valid values:</b><br></p> + * <p>Range [0,0] indicates that exposure compensation is not supported.</p> + * <p>For LIMITED and FULL devices, range must follow below requirements if exposure + * compensation is supported (<code>range != [0, 0]</code>):</p> * <p><code>Min.exposure compensation * {@link CameraCharacteristics#CONTROL_AE_COMPENSATION_STEP android.control.aeCompensationStep} <= -2 EV</code></p> * <p><code>Max.exposure compensation * {@link CameraCharacteristics#CONTROL_AE_COMPENSATION_STEP android.control.aeCompensationStep} >= 2 EV</code></p> - * <p>LEGACY devices may support a smaller range than this, including the range [0,0], which - * indicates that changing the exposure compensation is not supported.</p> + * <p>LEGACY devices may support a smaller range than this.</p> * <p>This key is available on all devices.</p> * * @see CameraCharacteristics#CONTROL_AE_COMPENSATION_STEP diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index 0849df8..b417496 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -867,9 +867,9 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * metering sequence when it processes this request.</p> * <p>This entry is normally set to IDLE, or is not * included at all in the request settings. When included and - * set to START, the camera device will trigger the autoexposure + * set to START, the camera device will trigger the auto-exposure (AE) * precapture metering sequence.</p> - * <p>The precapture sequence should triggered before starting a + * <p>The precapture sequence should be triggered before starting a * high-quality still capture for final metering decisions to * be made, and for firing pre-capture flash pulses to estimate * scene brightness and required final capture flash power, when @@ -877,6 +877,14 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <p>Normally, this entry should be set to START for only a * single request, and the application should wait until the * sequence completes before starting a new one.</p> + * <p>When a precapture metering sequence is finished, the camera device + * may lock the auto-exposure routine internally to be able to accurately expose the + * subsequent still capture image (<code>{@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent} == STILL_CAPTURE</code>). + * For this case, the AE may not resume normal scan if no subsequent still capture is + * submitted. To ensure that the AE routine restarts normal scan, the application should + * submit a request with <code>{@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock} == true</code>, followed by a request + * with <code>{@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock} == false</code>, if the application decides not to submit a + * still capture request after the precapture sequence completes.</p> * <p>The exact effect of auto-exposure (AE) precapture trigger * depends on the current AE mode and state; see * {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE precapture state transition @@ -895,7 +903,9 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p> * + * @see CaptureRequest#CONTROL_AE_LOCK * @see CaptureResult#CONTROL_AE_STATE + * @see CaptureRequest#CONTROL_CAPTURE_INTENT * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL * @see #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE * @see #CONTROL_AE_PRECAPTURE_TRIGGER_START diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index 1396940..f17100d 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -718,9 +718,9 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * metering sequence when it processes this request.</p> * <p>This entry is normally set to IDLE, or is not * included at all in the request settings. When included and - * set to START, the camera device will trigger the autoexposure + * set to START, the camera device will trigger the auto-exposure (AE) * precapture metering sequence.</p> - * <p>The precapture sequence should triggered before starting a + * <p>The precapture sequence should be triggered before starting a * high-quality still capture for final metering decisions to * be made, and for firing pre-capture flash pulses to estimate * scene brightness and required final capture flash power, when @@ -728,6 +728,14 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p>Normally, this entry should be set to START for only a * single request, and the application should wait until the * sequence completes before starting a new one.</p> + * <p>When a precapture metering sequence is finished, the camera device + * may lock the auto-exposure routine internally to be able to accurately expose the + * subsequent still capture image (<code>{@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent} == STILL_CAPTURE</code>). + * For this case, the AE may not resume normal scan if no subsequent still capture is + * submitted. To ensure that the AE routine restarts normal scan, the application should + * submit a request with <code>{@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock} == true</code>, followed by a request + * with <code>{@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock} == false</code>, if the application decides not to submit a + * still capture request after the precapture sequence completes.</p> * <p>The exact effect of auto-exposure (AE) precapture trigger * depends on the current AE mode and state; see * {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE precapture state transition @@ -746,7 +754,9 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p> * + * @see CaptureRequest#CONTROL_AE_LOCK * @see CaptureResult#CONTROL_AE_STATE + * @see CaptureRequest#CONTROL_CAPTURE_INTENT * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL * @see #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE * @see #CONTROL_AE_PRECAPTURE_TRIGGER_START diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java index 6535a4e..f1f2f0c 100644 --- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java +++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java @@ -44,6 +44,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import static com.android.internal.util.Preconditions.*; @@ -68,7 +69,7 @@ public class RequestThreadManager { // For slightly more spammy messages that will get repeated every frame private static final boolean VERBOSE = Log.isLoggable(LegacyCameraDevice.DEBUG_PROP, Log.VERBOSE); - private final Camera mCamera; + private Camera mCamera; private final CameraCharacteristics mCharacteristics; private final CameraDeviceState mDeviceState; @@ -83,8 +84,8 @@ public class RequestThreadManager { private static final int MAX_IN_FLIGHT_REQUESTS = 2; private static final int PREVIEW_FRAME_TIMEOUT = 1000; // ms - private static final int JPEG_FRAME_TIMEOUT = 3000; // ms (same as CTS for API2) - private static final int REQUEST_COMPLETE_TIMEOUT = 3000; // ms (same as JPEG timeout) + private static final int JPEG_FRAME_TIMEOUT = 4000; // ms (same as CTS for API2) + private static final int REQUEST_COMPLETE_TIMEOUT = JPEG_FRAME_TIMEOUT; // ms (same as JPEG timeout) private static final float ASPECT_RATIO_TOLERANCE = 0.01f; private boolean mPreviewRunning = false; @@ -108,6 +109,8 @@ public class RequestThreadManager { private final FpsCounter mPrevCounter = new FpsCounter("Incoming Preview"); private final FpsCounter mRequestCounter = new FpsCounter("Incoming Requests"); + private final AtomicBoolean mQuit = new AtomicBoolean(false); + // Stuff JPEGs into HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers to get around SW write // limitations for (b/17379185). private static final boolean USE_BLOB_FORMAT_OVERRIDE = true; @@ -325,7 +328,15 @@ public class RequestThreadManager { Log.d(TAG, "configureOutputs with " + outputsStr); } - stopPreview(); + try { + stopPreview(); + } catch (RuntimeException e) { + Log.e(TAG, "Received device exception in configure call: ", e); + mDeviceState.setError( + CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); + return; + } + /* * Try to release the previous preview's surface texture earlier if we end up * using a different one; this also reduces the likelihood of getting into a deadlock @@ -335,6 +346,11 @@ public class RequestThreadManager { mCamera.setPreviewTexture(/*surfaceTexture*/null); } catch (IOException e) { Log.w(TAG, "Failed to clear prior SurfaceTexture, may cause GL deadlock: ", e); + } catch (RuntimeException e) { + Log.e(TAG, "Received device exception in configure call: ", e); + mDeviceState.setError( + CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); + return; } if (mGLThreadManager != null) { @@ -470,7 +486,14 @@ public class RequestThreadManager { mPreviewTexture.setOnFrameAvailableListener(mPreviewCallback); } - mCamera.setParameters(mParams); + try { + mCamera.setParameters(mParams); + } catch (RuntimeException e) { + Log.e(TAG, "Received device exception while configuring: ", e); + mDeviceState.setError( + CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); + + } } private void resetJpegSurfaceFormats(Collection<Surface> surfaces) { @@ -793,7 +816,7 @@ public class RequestThreadManager { } } catch (IOException e) { - Log.e(TAG, "Received device exception: ", e); + Log.e(TAG, "Received device exception during capture call: ", e); mDeviceState.setError( CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); break; @@ -802,6 +825,11 @@ public class RequestThreadManager { mDeviceState.setError( CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); break; + } catch (RuntimeException e) { + Log.e(TAG, "Received device exception during capture call: ", e); + mDeviceState.setError( + CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); + break; } if (paramsChanged) { @@ -878,9 +906,11 @@ public class RequestThreadManager { } if (mGLThreadManager != null) { mGLThreadManager.quit(); + mGLThreadManager = null; } if (mCamera != null) { mCamera.release(); + mCamera = null; } resetJpegSurfaceFormats(mCallbackOutputs); break; @@ -942,14 +972,16 @@ public class RequestThreadManager { * Quit the request thread, and clean up everything. */ public void quit() { - Handler handler = mRequestThread.waitAndGetHandler(); - handler.sendMessageAtFrontOfQueue(handler.obtainMessage(MSG_CLEANUP)); - mRequestThread.quitSafely(); - try { - mRequestThread.join(); - } catch (InterruptedException e) { - Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.", - mRequestThread.getName(), mRequestThread.getId())); + if (!mQuit.getAndSet(true)) { // Avoid sending messages on dead thread's handler. + Handler handler = mRequestThread.waitAndGetHandler(); + handler.sendMessageAtFrontOfQueue(handler.obtainMessage(MSG_CLEANUP)); + mRequestThread.quitSafely(); + try { + mRequestThread.join(); + } catch (InterruptedException e) { + Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.", + mRequestThread.getName(), mRequestThread.getId())); + } } } diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index bedc695..3d5215b 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -276,7 +276,7 @@ public final class Parcel { private static native byte[] nativeMarshall(long nativePtr); private static native void nativeUnmarshall( - long nativePtr, byte[] data, int offest, int length); + long nativePtr, byte[] data, int offset, int length); private static native void nativeAppendFrom( long thisNativePtr, long otherNativePtr, int offset, int length); private static native boolean nativeHasFileDescriptors(long nativePtr); @@ -438,8 +438,8 @@ public final class Parcel { /** * Set the bytes in data to be the raw bytes of this Parcel. */ - public final void unmarshall(byte[] data, int offest, int length) { - nativeUnmarshall(mNativePtr, data, offest, length); + public final void unmarshall(byte[] data, int offset, int length) { + nativeUnmarshall(mNativePtr, data, offset, length); } public final void appendFrom(Parcel parcel, int offset, int length) { diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java index 2b53c48..b84c3aa 100644 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -1754,8 +1754,8 @@ public abstract class Layout { private char getEllipsisChar(TextUtils.TruncateAt method) { return (method == TextUtils.TruncateAt.END_SMALL) ? - ELLIPSIS_TWO_DOTS[0] : - ELLIPSIS_NORMAL[0]; + TextUtils.ELLIPSIS_TWO_DOTS[0] : + TextUtils.ELLIPSIS_NORMAL[0]; } private void ellipsize(int start, int end, int line, @@ -1952,6 +1952,4 @@ public abstract class Layout { /* package */ static final Directions DIRS_ALL_RIGHT_TO_LEFT = new Directions(new int[] { 0, RUN_LENGTH_MASK | RUN_RTL_FLAG }); - /* package */ static final char[] ELLIPSIS_NORMAL = { '\u2026' }; // this is "..." - /* package */ static final char[] ELLIPSIS_TWO_DOTS = { '\u2025' }; // this is ".." } diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index 74b7b69..07505a9 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -652,7 +652,7 @@ public class StaticLayout extends Layout { float ellipsisWidth = paint.measureText( (where == TextUtils.TruncateAt.END_SMALL) ? - ELLIPSIS_TWO_DOTS : ELLIPSIS_NORMAL, 0, 1); + TextUtils.ELLIPSIS_TWO_DOTS : TextUtils.ELLIPSIS_NORMAL, 0, 1); int ellipsisStart = 0; int ellipsisCount = 0; int len = lineEnd - lineStart; diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java index 8a8c6d8..48bb5dd 100644 --- a/core/java/android/text/TextUtils.java +++ b/core/java/android/text/TextUtils.java @@ -63,9 +63,12 @@ import java.util.regex.Pattern; public class TextUtils { private static final String TAG = "TextUtils"; - private static final String ELLIPSIS = new String(Layout.ELLIPSIS_NORMAL); - private static final String ELLIPSIS_TWO_DOTS = new String(Layout.ELLIPSIS_TWO_DOTS); + /* package */ static final char[] ELLIPSIS_NORMAL = { '\u2026' }; // this is "..." + private static final String ELLIPSIS_STRING = new String(ELLIPSIS_NORMAL); + + /* package */ static final char[] ELLIPSIS_TWO_DOTS = { '\u2025' }; // this is ".." + private static final String ELLIPSIS_TWO_DOTS_STRING = new String(ELLIPSIS_TWO_DOTS); private TextUtils() { /* cannot be instantiated */ } @@ -1085,7 +1088,7 @@ public class TextUtils { EllipsizeCallback callback) { return ellipsize(text, paint, avail, where, preserveLength, callback, TextDirectionHeuristics.FIRSTSTRONG_LTR, - (where == TruncateAt.END_SMALL) ? ELLIPSIS_TWO_DOTS : ELLIPSIS); + (where == TruncateAt.END_SMALL) ? ELLIPSIS_TWO_DOTS_STRING : ELLIPSIS_STRING); } /** diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java index 7c9861f..6ed3885 100644 --- a/core/java/android/util/ArrayMap.java +++ b/core/java/android/util/ArrayMap.java @@ -255,7 +255,10 @@ public final class ArrayMap<K, V> implements Map<K, V> { } private ArrayMap(boolean immutable) { - mHashes = EmptyArray.INT; + // If this is immutable, use the sentinal EMPTY_IMMUTABLE_INTS + // instance instead of the usual EmptyArray.INT. The reference + // is checked later to see if the array is allowed to grow. + mHashes = immutable ? EMPTY_IMMUTABLE_INTS : EmptyArray.INT; mArray = EmptyArray.OBJECT; mSize = 0; } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 6928b2c..3c05872 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -8440,8 +8440,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // If the event should be handled by accessibility focus first. if (event.isTargetAccessibilityFocus()) { // We don't have focus or no virtual descendant has it, do not handle the event. - if (!isAccessibilityFocused() && !(getViewRootImpl() != null && getViewRootImpl() - .getAccessibilityFocusedHost() == this)) { + if (!isAccessibilityFocusedViewOrHost()) { return false; } // We have focus and got the event, then use normal event dispatch. @@ -8490,6 +8489,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return result; } + boolean isAccessibilityFocusedViewOrHost() { + return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl() + .getAccessibilityFocusedHost() == this); + } + /** * Filter the touch event to apply security policies. * @@ -12872,7 +12876,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Interpolator.Result.FREEZE_END) { cache.state = ScrollabilityCache.OFF; } else { - cache.scrollBar.setAlpha(Math.round(values[0])); + cache.scrollBar.mutate().setAlpha(Math.round(values[0])); } // This will make the scroll bars inval themselves after @@ -12882,7 +12886,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } else { // We're just on -- but we may have been fading before so // reset alpha - cache.scrollBar.setAlpha(255); + cache.scrollBar.mutate().setAlpha(255); } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index fd50c4d..c4b689f 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -1931,8 +1931,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager mInputEventConsistencyVerifier.onTouchEvent(ev, 1); } - // Whether this event should be handled by the accessibility focus first. - final boolean targetAccessibilityFocus = ev.isTargetAccessibilityFocus(); + // If the event targets the accessibility focused view and this is it, start + // normal event dispatch. Maybe a descendant is what will handle the click. + if (ev.isTargetAccessibilityFocus() && isAccessibilityFocusedViewOrHost()) { + ev.setTargetAccessibilityFocus(false); + } boolean handled = false; if (onFilterTouchEventForSecurity(ev)) { @@ -1950,24 +1953,25 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager // Check for interception. final boolean intercepted; - if (!targetAccessibilityFocus) { - if (actionMasked == MotionEvent.ACTION_DOWN - || mFirstTouchTarget != null) { - final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0; - if (!disallowIntercept) { - intercepted = onInterceptTouchEvent(ev); - ev.setAction(action); // restore action in case it was changed - } else { - intercepted = false; - } + if (actionMasked == MotionEvent.ACTION_DOWN + || mFirstTouchTarget != null) { + final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0; + if (!disallowIntercept) { + intercepted = onInterceptTouchEvent(ev); + ev.setAction(action); // restore action in case it was changed } else { - // There are no touch targets and this action is not an initial down - // so this view group continues to intercept touches. - intercepted = true; + intercepted = false; } } else { - // If event should reach the accessibility focus first, do not intercept it. - intercepted = false; + // There are no touch targets and this action is not an initial down + // so this view group continues to intercept touches. + intercepted = true; + } + + // If intercepted, start normal event dispatch. Also if there is already + // a view that is handling the gesture, do normal event dispatch. + if (intercepted || mFirstTouchTarget != null) { + ev.setTargetAccessibilityFocus(false); } // Check for cancelation. @@ -1979,10 +1983,18 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager TouchTarget newTouchTarget = null; boolean alreadyDispatchedToNewTouchTarget = false; if (!canceled && !intercepted) { + + // If the event is targeting accessiiblity focus we give it to the + // view that has accessibility focus and if it does not handle it + // we clear the flag and dispatch the event to all children as usual. + // We are looking up the accessibility focused host to avoid keeping + // state since these events are very rare. + View childWithAccessibilityFocus = ev.isTargetAccessibilityFocus() + ? findChildWithAccessibilityFocus() : null; + if (actionMasked == MotionEvent.ACTION_DOWN || (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN) - || actionMasked == MotionEvent.ACTION_HOVER_MOVE - || targetAccessibilityFocus) { + || actionMasked == MotionEvent.ACTION_HOVER_MOVE) { final int actionIndex = ev.getActionIndex(); // always 0 for down final int idBitsToAssign = split ? 1 << ev.getPointerId(actionIndex) : TouchTarget.ALL_POINTER_IDS; @@ -2006,8 +2018,22 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager ? getChildDrawingOrder(childrenCount, i) : i; final View child = (preorderedList == null) ? children[childIndex] : preorderedList.get(childIndex); + + // If there is a view that has accessibility focus we want it + // to get the event first and if not handled we will perform a + // normal dispatch. We may do a double iteration but this is + // safer given the timeframe. + if (childWithAccessibilityFocus != null) { + if (childWithAccessibilityFocus != child) { + continue; + } + childWithAccessibilityFocus = null; + i = childrenCount - 1; + } + if (!canViewReceivePointerEvents(child) || !isTransformedTouchPointInView(x, y, child, null)) { + ev.setTargetAccessibilityFocus(false); continue; } @@ -2040,6 +2066,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager alreadyDispatchedToNewTouchTarget = true; break; } + + // The accessibility focus didn't handle the event, so clear + // the flag and do a normal dispatch to all children. + ev.setTargetAccessibilityFocus(false); } if (preorderedList != null) preorderedList.clear(); } @@ -2112,6 +2142,34 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } /** + * Finds the child which has accessibility focus. + * + * @return The child that has focus. + */ + private View findChildWithAccessibilityFocus() { + ViewRootImpl viewRoot = getViewRootImpl(); + if (viewRoot == null) { + return null; + } + + View current = viewRoot.getAccessibilityFocusedHost(); + if (current == null) { + return null; + } + + ViewParent parent = current.getParent(); + while (parent instanceof View) { + if (parent == this) { + return current; + } + current = (View) parent; + parent = current.getParent(); + } + + return null; + } + + /** * Resets all touch state in preparation for a new cycle. */ private void resetTouchState() { @@ -2681,6 +2739,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager @Override void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfoInternal(info); + if (getAccessibilityNodeProvider() != null) { + return; + } if (mAttachInfo != null) { final ArrayList<View> childrenForAccessibility = mAttachInfo.mTempArrayList; childrenForAccessibility.clear(); diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 3f2f3a5..8704356 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -102,10 +102,12 @@ public abstract class Window { */ public static final int FEATURE_SWIPE_TO_DISMISS = 11; /** - * Flag for requesting that window content changes should be represented - * with scenes and transitions. + * Flag for requesting that window content changes should be animated using a + * TransitionManager. * - * TODO Add docs + * <p>The TransitionManager is set using + * {@link #setTransitionManager(android.transition.TransitionManager)}. If none is set, + * a default TransitionManager will be used.</p> * * @see #setContentView */ @@ -1019,10 +1021,16 @@ public abstract class Window { * <p>Note that calling this function "locks in" various characteristics * of the window that can not, from this point forward, be changed: the * features that have been requested with {@link #requestFeature(int)}, - * and certain window flags as described in {@link #setFlags(int, int)}. + * and certain window flags as described in {@link #setFlags(int, int)}.</p> + * + * <p>If {@link #FEATURE_CONTENT_TRANSITIONS} is set, the window's + * TransitionManager will be used to animate content from the current + * content View to view.</p> * * @param view The desired content to display. * @param params Layout parameters for the view. + * @see #getTransitionManager() + * @see #setTransitionManager(android.transition.TransitionManager) */ public abstract void setContentView(View view, ViewGroup.LayoutParams params); @@ -1467,6 +1475,7 @@ public abstract class Window { * {@link #setContentView}) if {@link #FEATURE_CONTENT_TRANSITIONS} has been granted.</p> * * @return This window's content TransitionManager or null if none is set. + * @attr ref android.R.styleable#Window_windowContentTransitionManager */ public TransitionManager getTransitionManager() { return null; @@ -1477,6 +1486,7 @@ public abstract class Window { * Requires {@link #FEATURE_CONTENT_TRANSITIONS}. * * @param tm The TransitionManager to use for scene changes. + * @attr ref android.R.styleable#Window_windowContentTransitionManager */ public void setTransitionManager(TransitionManager tm) { throw new UnsupportedOperationException(); diff --git a/core/java/android/widget/ScrollBarDrawable.java b/core/java/android/widget/ScrollBarDrawable.java index 10e9ff4..8eff1aa 100644 --- a/core/java/android/widget/ScrollBarDrawable.java +++ b/core/java/android/widget/ScrollBarDrawable.java @@ -44,6 +44,7 @@ public class ScrollBarDrawable extends Drawable { private final Rect mTempBounds = new Rect(); private boolean mAlwaysDrawHorizontalTrack; private boolean mAlwaysDrawVerticalTrack; + private boolean mMutated; public ScrollBarDrawable() { } @@ -191,6 +192,9 @@ public class ScrollBarDrawable extends Drawable { public void setVerticalThumbDrawable(Drawable thumb) { if (thumb != null) { + if (mMutated) { + thumb.mutate(); + } thumb.setState(STATE_ENABLED); mVerticalThumb = thumb; } @@ -198,6 +202,9 @@ public class ScrollBarDrawable extends Drawable { public void setVerticalTrackDrawable(Drawable track) { if (track != null) { + if (mMutated) { + track.mutate(); + } track.setState(STATE_ENABLED); } mVerticalTrack = track; @@ -205,6 +212,9 @@ public class ScrollBarDrawable extends Drawable { public void setHorizontalThumbDrawable(Drawable thumb) { if (thumb != null) { + if (mMutated) { + thumb.mutate(); + } thumb.setState(STATE_ENABLED); mHorizontalThumb = thumb; } @@ -212,6 +222,9 @@ public class ScrollBarDrawable extends Drawable { public void setHorizontalTrackDrawable(Drawable track) { if (track != null) { + if (mMutated) { + track.mutate(); + } track.setState(STATE_ENABLED); } mHorizontalTrack = track; @@ -228,6 +241,26 @@ public class ScrollBarDrawable extends Drawable { } @Override + public ScrollBarDrawable mutate() { + if (!mMutated && super.mutate() == this) { + if (mVerticalTrack != null) { + mVerticalTrack.mutate(); + } + if (mVerticalThumb != null) { + mVerticalThumb.mutate(); + } + if (mHorizontalTrack != null) { + mHorizontalTrack.mutate(); + } + if (mHorizontalThumb != null) { + mHorizontalThumb.mutate(); + } + mMutated = true; + } + return this; + } + + @Override public void setAlpha(int alpha) { if (mVerticalTrack != null) { mVerticalTrack.setAlpha(alpha); diff --git a/core/java/com/android/internal/widget/SubtitleView.java b/core/java/com/android/internal/widget/SubtitleView.java index 2f987e9..a206e7f 100644 --- a/core/java/com/android/internal/widget/SubtitleView.java +++ b/core/java/com/android/internal/widget/SubtitleView.java @@ -148,6 +148,7 @@ public class SubtitleView extends View { mHasMeasurements = false; requestLayout(); + invalidate(); } public void setForegroundColor(int color) { diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp index a51af40..3ea9b58 100644 --- a/core/jni/android/graphics/Graphics.cpp +++ b/core/jni/android/graphics/Graphics.cpp @@ -536,7 +536,12 @@ jbyteArray GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap, return NULL; } - const size_t size = bitmap->getSize(); + const int64_t size64 = bitmap->computeSize64(); + if (!sk_64_isS32(size64)) { + doThrowIAE(env, "bitmap size exceeds 32 bits"); + return NULL; + } + const size_t size = sk_64_asS32(size64); jbyteArray arrayObj = (jbyteArray) env->CallObjectMethod(gVMRuntime, gVMRuntime_newNonMovableArray, gByte_class, size); diff --git a/core/res/res/drawable-mdpi/ic_clear_mtrl_alpha.png b/core/res/res/drawable-mdpi/ic_clear_mtrl_alpha.png Binary files differdeleted file mode 100644 index d43e4d1..0000000 --- a/core/res/res/drawable-mdpi/ic_clear_mtrl_alpha.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/ic_clear_mtrl_alpha.png b/core/res/res/drawable-xhdpi/ic_clear_mtrl_alpha.png Binary files differdeleted file mode 100644 index ddacb59..0000000 --- a/core/res/res/drawable-xhdpi/ic_clear_mtrl_alpha.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/ic_clear_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/ic_clear_mtrl_alpha.png Binary files differdeleted file mode 100644 index 21ed914..0000000 --- a/core/res/res/drawable-xxhdpi/ic_clear_mtrl_alpha.png +++ /dev/null diff --git a/core/res/res/drawable/ic_clear_material.xml b/core/res/res/drawable/ic_clear_material.xml index 076c0a2..a21f47a 100644 --- a/core/res/res/drawable/ic_clear_material.xml +++ b/core/res/res/drawable/ic_clear_material.xml @@ -14,6 +14,13 @@ limitations under the License. --> -<bitmap xmlns:android="http://schemas.android.com/apk/res/android" - android:src="@drawable/ic_clear_mtrl_alpha" - android:tint="?attr/colorControlNormal" /> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?attr/colorControlNormal"> +<path + android:pathData="M19,6.41L17.59,5,12,10.59,6.41,5,5,6.41,10.59,12,5,17.59,6.41,19,12,13.41,17.59,19,19,17.59,13.41,12z" + android:fillColor="@color/white"/> +</vector> diff --git a/core/res/res/drawable/scrubber_progress_horizontal_material.xml b/core/res/res/drawable/scrubber_progress_horizontal_material.xml index f2ea30f..89a1787 100644 --- a/core/res/res/drawable/scrubber_progress_horizontal_material.xml +++ b/core/res/res/drawable/scrubber_progress_horizontal_material.xml @@ -14,29 +14,35 @@ limitations under the License. --> -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_enabled="false"> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@id/background"> <nine-patch android:src="@drawable/scrubber_track_mtrl_alpha" - android:tint="?attr/colorControlNormal" /> - </item> - <item> - <layer-list> - <item android:id="@id/background"> - <nine-patch android:src="@drawable/scrubber_track_mtrl_alpha" android:tint="?attr/colorControlNormal" /> - </item> - <item android:id="@id/secondaryProgress"> - <scale android:scaleWidth="100%"> + </item> + <item android:id="@id/secondaryProgress"> + <scale android:scaleWidth="100%"> + <selector> + <item android:state_enabled="false"> + <color android:color="@color/transparent" /> + </item> + <item> <nine-patch android:src="@drawable/scrubber_primary_mtrl_alpha" - android:tint="?attr/colorControlNormal" /> - </scale> - </item> - <item android:id="@id/progress"> - <scale android:scaleWidth="100%"> + android:tint="?attr/colorControlNormal" /> + </item> + </selector> + </scale> + </item> + <item android:id="@id/progress"> + <scale android:scaleWidth="100%"> + <selector> + <item android:state_enabled="false"> + <color android:color="@color/transparent" /> + </item> + <item> <nine-patch android:src="@drawable/scrubber_primary_mtrl_alpha" - android:tint="?attr/colorControlActivated" /> - </scale> - </item> - </layer-list> + android:tint="?attr/colorControlActivated" /> + </item> + </selector> + </scale> </item> -</selector> +</layer-list>
\ No newline at end of file diff --git a/core/res/res/layout/preference_dialog_edittext_material.xml b/core/res/res/layout/preference_dialog_edittext_material.xml new file mode 100644 index 0000000..df76f7f --- /dev/null +++ b/core/res/res/layout/preference_dialog_edittext_material.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- Layout used as the dialog's content View for EditTextPreference. --> +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginTop="48dp" + android:layout_marginBottom="48dp" + android:overScrollMode="ifContentScrolls"> + + <LinearLayout + android:id="@+id/edittext_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:padding="20dp" + android:orientation="vertical"> + + <TextView + android:id="@+id/message" + android:layout_marginBottom="48dp" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingStart="4dp" + android:paddingEnd="4dp" + android:textColor="?attr/textColorSecondary" + style="?attr/textAppearanceSmall" /> + + </LinearLayout> + +</ScrollView> diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml index 6220a1b..419beba 100644 --- a/core/res/res/values/styles_material.xml +++ b/core/res/res/values/styles_material.xml @@ -88,7 +88,7 @@ please see styles_device_defaults.xml. </style> <style name="Preference.Material.DialogPreference.EditTextPreference"> - <item name="dialogLayout">@layout/preference_dialog_edittext</item> + <item name="dialogLayout">@layout/preference_dialog_edittext_material</item> </style> <style name="Preference.Material.RingtonePreference"> |