Merge "Fix issue #15828903: Intent.parseUri allows call to FLAG_GRANT_*_URI_PERMISSION" into lmp-mr1-dev
diff --git a/Android.mk b/Android.mk
index a596ee7..ea22d0f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -174,6 +174,7 @@
core/java/android/hardware/usb/IUsbManager.aidl \
core/java/android/net/IConnectivityManager.aidl \
core/java/android/net/IEthernetManager.aidl \
+ core/java/android/net/IEthernetServiceListener.aidl \
core/java/android/net/INetworkManagementEventObserver.aidl \
core/java/android/net/INetworkPolicyListener.aidl \
core/java/android/net/INetworkPolicyManager.aidl \
diff --git a/api/current.txt b/api/current.txt
index 553a30c..d25ae96 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2012,6 +2012,7 @@
field public static final int Theme_DeviceDefault_Dialog = 16974126; // 0x103012e
field public static final int Theme_DeviceDefault_DialogWhenLarge = 16974134; // 0x1030136
field public static final int Theme_DeviceDefault_DialogWhenLarge_NoActionBar = 16974135; // 0x1030137
+ field public static final int Theme_DeviceDefault_Dialog_Alert = 16974545; // 0x10302d1
field public static final int Theme_DeviceDefault_Dialog_MinWidth = 16974127; // 0x103012f
field public static final int Theme_DeviceDefault_Dialog_NoActionBar = 16974128; // 0x1030130
field public static final int Theme_DeviceDefault_Dialog_NoActionBar_MinWidth = 16974129; // 0x1030131
@@ -2021,6 +2022,7 @@
field public static final int Theme_DeviceDefault_Light_Dialog = 16974130; // 0x1030132
field public static final int Theme_DeviceDefault_Light_DialogWhenLarge = 16974136; // 0x1030138
field public static final int Theme_DeviceDefault_Light_DialogWhenLarge_NoActionBar = 16974137; // 0x1030139
+ field public static final int Theme_DeviceDefault_Light_Dialog_Alert = 16974546; // 0x10302d2
field public static final int Theme_DeviceDefault_Light_Dialog_MinWidth = 16974131; // 0x1030133
field public static final int Theme_DeviceDefault_Light_Dialog_NoActionBar = 16974132; // 0x1030134
field public static final int Theme_DeviceDefault_Light_Dialog_NoActionBar_MinWidth = 16974133; // 0x1030135
@@ -4414,7 +4416,7 @@
method public android.content.Intent createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence);
method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult);
method public boolean inKeyguardRestrictedInputMode();
- method public boolean isKeyguardInTrustedState();
+ method public boolean isDeviceLocked();
method public boolean isKeyguardLocked();
method public boolean isKeyguardSecure();
method public deprecated android.app.KeyguardManager.KeyguardLock newKeyguardLock(java.lang.String);
@@ -16931,8 +16933,8 @@
field public static final java.lang.String EXTRA_EXTRA_INFO = "extraInfo";
field public static final java.lang.String EXTRA_IS_FAILOVER = "isFailover";
field public static final deprecated java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
- field public static final java.lang.String EXTRA_NETWORK_REQUEST_NETWORK = "networkRequestNetwork";
- field public static final java.lang.String EXTRA_NETWORK_REQUEST_NETWORK_REQUEST = "networkRequestNetworkRequest";
+ field public static final java.lang.String EXTRA_NETWORK = "android.net.extra.NETWORK";
+ field public static final java.lang.String EXTRA_NETWORK_REQUEST = "android.net.extra.NETWORK_REQUEST";
field public static final java.lang.String EXTRA_NETWORK_TYPE = "networkType";
field public static final java.lang.String EXTRA_NO_CONNECTIVITY = "noConnectivity";
field public static final java.lang.String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index a9eaf29..3f1845a 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -16,6 +16,7 @@
package android.accessibilityservice;
+import android.annotation.NonNull;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
@@ -27,6 +28,7 @@
import android.view.KeyEvent;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.view.WindowManagerImpl;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityInteractionClient;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -618,6 +620,23 @@
}
}
+ @Override
+ public Object getSystemService(@ServiceName @NonNull String name) {
+ if (getBaseContext() == null) {
+ throw new IllegalStateException(
+ "System services not available to Activities before onCreate()");
+ }
+
+ // Guarantee that we always return the same window manager instance.
+ if (WINDOW_SERVICE.equals(name)) {
+ if (mWindowManager == null) {
+ mWindowManager = (WindowManager) getBaseContext().getSystemService(name);
+ }
+ return mWindowManager;
+ }
+ return super.getSystemService(name);
+ }
+
/**
* Implement to return the implementation of the internal accessibility
* service interface.
@@ -645,8 +664,10 @@
mConnectionId = connectionId;
mWindowToken = windowToken;
- // Let the window manager know about our shiny new token.
- WindowManagerGlobal.getInstance().setDefaultToken(mWindowToken);
+ // The client may have already obtained the window manager, so
+ // update the default token on whatever manager we gave them.
+ final WindowManagerImpl wm = (WindowManagerImpl) getSystemService(WINDOW_SERVICE);
+ wm.setDefaultToken(windowToken);
}
@Override
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 5038df9..ddd21e6 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -225,28 +225,28 @@
}
/**
- * Return whether unlocking the device is currently not requiring a password
- * because of a trust agent.
+ * Returns whether the device is currently locked and requires a PIN, pattern or
+ * password to unlock.
*
- * @return true if the keyguard can currently be unlocked without entering credentials
- * because the device is in a trusted environment.
+ * @return true if unlocking the device currently requires a PIN, pattern or
+ * password.
*/
- public boolean isKeyguardInTrustedState() {
- return isKeyguardInTrustedState(UserHandle.getCallingUserId());
+ public boolean isDeviceLocked() {
+ return isDeviceLocked(UserHandle.getCallingUserId());
}
/**
- * Return whether unlocking the device is currently not requiring a password
- * because of a trust agent.
+ * Returns whether the device is currently locked and requires a PIN, pattern or
+ * password to unlock.
*
- * @param userId the user for which the trusted state should be reported.
- * @return true if the keyguard can currently be unlocked without entering credentials
- * because the device is in a trusted environment.
+ * @param userId the user for which the locked state should be reported.
+ * @return true if unlocking the device currently requires a PIN, pattern or
+ * password.
* @hide
*/
- public boolean isKeyguardInTrustedState(int userId) {
+ public boolean isDeviceLocked(int userId) {
try {
- return mTrustManager.isTrusted(userId);
+ return mTrustManager.isDeviceLocked(userId);
} catch (RemoteException e) {
return false;
}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index aa98e97..ece2a33 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -632,55 +632,60 @@
public void removeContextRegistrations(Context context,
String who, String what) {
final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
- ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
- mReceivers.remove(context);
- if (rmap != null) {
- for (int i=0; i<rmap.size(); i++) {
- LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
- IntentReceiverLeaked leak = new IntentReceiverLeaked(
- what + " " + who + " has leaked IntentReceiver "
- + rd.getIntentReceiver() + " that was " +
- "originally registered here. Are you missing a " +
- "call to unregisterReceiver()?");
- leak.setStackTrace(rd.getLocation().getStackTrace());
- Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
- if (reportRegistrationLeaks) {
- StrictMode.onIntentReceiverLeaked(leak);
- }
- try {
- ActivityManagerNative.getDefault().unregisterReceiver(
- rd.getIIntentReceiver());
- } catch (RemoteException e) {
- // system crashed, nothing we can do
+ synchronized (mReceivers) {
+ ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
+ mReceivers.remove(context);
+ if (rmap != null) {
+ for (int i = 0; i < rmap.size(); i++) {
+ LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
+ IntentReceiverLeaked leak = new IntentReceiverLeaked(
+ what + " " + who + " has leaked IntentReceiver "
+ + rd.getIntentReceiver() + " that was " +
+ "originally registered here. Are you missing a " +
+ "call to unregisterReceiver()?");
+ leak.setStackTrace(rd.getLocation().getStackTrace());
+ Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
+ if (reportRegistrationLeaks) {
+ StrictMode.onIntentReceiverLeaked(leak);
+ }
+ try {
+ ActivityManagerNative.getDefault().unregisterReceiver(
+ rd.getIIntentReceiver());
+ } catch (RemoteException e) {
+ // system crashed, nothing we can do
+ }
}
}
+ mUnregisteredReceivers.remove(context);
}
- mUnregisteredReceivers.remove(context);
- //Slog.i(TAG, "Receiver registrations: " + mReceivers);
- ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
- mServices.remove(context);
- if (smap != null) {
- for (int i=0; i<smap.size(); i++) {
- LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
- ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
- what + " " + who + " has leaked ServiceConnection "
- + sd.getServiceConnection() + " that was originally bound here");
- leak.setStackTrace(sd.getLocation().getStackTrace());
- Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
- if (reportRegistrationLeaks) {
- StrictMode.onServiceConnectionLeaked(leak);
+
+ synchronized (mServices) {
+ //Slog.i(TAG, "Receiver registrations: " + mReceivers);
+ ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
+ mServices.remove(context);
+ if (smap != null) {
+ for (int i = 0; i < smap.size(); i++) {
+ LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
+ ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
+ what + " " + who + " has leaked ServiceConnection "
+ + sd.getServiceConnection() + " that was originally bound here");
+ leak.setStackTrace(sd.getLocation().getStackTrace());
+ Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
+ if (reportRegistrationLeaks) {
+ StrictMode.onServiceConnectionLeaked(leak);
+ }
+ try {
+ ActivityManagerNative.getDefault().unbindService(
+ sd.getIServiceConnection());
+ } catch (RemoteException e) {
+ // system crashed, nothing we can do
+ }
+ sd.doForget();
}
- try {
- ActivityManagerNative.getDefault().unbindService(
- sd.getIServiceConnection());
- } catch (RemoteException e) {
- // system crashed, nothing we can do
- }
- sd.doForget();
}
+ mUnboundServices.remove(context);
+ //Slog.i(TAG, "Service registrations: " + mServices);
}
- mUnboundServices.remove(context);
- //Slog.i(TAG, "Service registrations: " + mServices);
}
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl
index 0193711..68ea0aa 100644
--- a/core/java/android/app/trust/ITrustManager.aidl
+++ b/core/java/android/app/trust/ITrustManager.aidl
@@ -29,5 +29,6 @@
void reportRequireCredentialEntry(int userId);
void registerTrustListener(in ITrustListener trustListener);
void unregisterTrustListener(in ITrustListener trustListener);
- boolean isTrusted(int userId);
+ void reportKeyguardShowingChanged();
+ boolean isDeviceLocked(int userId);
}
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index 3d262b1..705a144 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -88,6 +88,19 @@
}
/**
+ * Reports that the visibility of the keyguard has changed.
+ *
+ * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+ */
+ public void reportKeyguardShowingChanged() {
+ try {
+ mService.reportKeyguardShowingChanged();
+ } catch (RemoteException e) {
+ onError(e);
+ }
+ }
+
+ /**
* Registers a listener for trust events.
*
* Requires the {@link android.Manifest.permission#TRUST_LISTENER} permission.
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 271fc30..895ae04 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -490,12 +490,16 @@
* <p>More specifically, this means that a size matching the
* camera device's active array size is listed as a
* supported size for the YUV_420_888 format in
- * {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap}, and the
- * minimum frame duration for that format and size is <=
- * 1/20 s.</p>
+ * {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap}, the minimum frame
+ * duration for that format and size is <= 1/20 s, and
+ * the {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES android.control.aeAvailableTargetFpsRanges} entry
+ * lists at least one FPS range where the minimum FPS
+ * is >= 1 / minimumFrameDuration for the maximum-size
+ * YUV_420_888 format.</p>
* <p>In addition, the {@link CameraCharacteristics#SYNC_MAX_LATENCY android.sync.maxLatency} field is
* guaranted to have a value between 0 and 4, inclusive.</p>
*
+ * @see CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES
* @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP
* @see CameraCharacteristics#SYNC_MAX_LATENCY
* @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 1c9f4c68..ec24ded 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2381,15 +2381,14 @@
* successfully finding a network for the applications request. Retrieve it with
* {@link android.content.Intent#getParcelableExtra(String)}.
*/
- public static final String EXTRA_NETWORK_REQUEST_NETWORK = "networkRequestNetwork";
+ public static final String EXTRA_NETWORK = "android.net.extra.NETWORK";
/**
* The lookup key for a {@link NetworkRequest} object included with the intent after
* successfully finding a network for the applications request. Retrieve it with
* {@link android.content.Intent#getParcelableExtra(String)}.
*/
- public static final String EXTRA_NETWORK_REQUEST_NETWORK_REQUEST =
- "networkRequestNetworkRequest";
+ public static final String EXTRA_NETWORK_REQUEST = "android.net.extra.NETWORK_REQUEST";
/**
@@ -2405,8 +2404,8 @@
* <receiver> tag in an AndroidManifest.xml file
* <p>
* The operation Intent is delivered with two extras, a {@link Network} typed
- * extra called {@link #EXTRA_NETWORK_REQUEST_NETWORK} and a {@link NetworkRequest}
- * typed extra called {@link #EXTRA_NETWORK_REQUEST_NETWORK_REQUEST} containing
+ * extra called {@link #EXTRA_NETWORK} and a {@link NetworkRequest}
+ * typed extra called {@link #EXTRA_NETWORK_REQUEST} containing
* the original requests parameters. It is important to create a new,
* {@link NetworkCallback} based request before completing the processing of the
* Intent to reserve the network or it will be released shortly after the Intent
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index d965f27..f45737a 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -18,11 +18,14 @@
import android.content.Context;
import android.net.IEthernetManager;
+import android.net.IEthernetServiceListener;
import android.net.IpConfiguration;
-import android.net.IpConfiguration.IpAssignment;
-import android.net.IpConfiguration.ProxySettings;
+import android.os.Handler;
+import android.os.Message;
import android.os.RemoteException;
+import java.util.ArrayList;
+
/**
* A class representing the IP configuration of the Ethernet network.
*
@@ -30,9 +33,41 @@
*/
public class EthernetManager {
private static final String TAG = "EthernetManager";
+ private static final int MSG_AVAILABILITY_CHANGED = 1000;
private final Context mContext;
private final IEthernetManager mService;
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_AVAILABILITY_CHANGED) {
+ boolean isAvailable = (msg.arg1 == 1);
+ for (Listener listener : mListeners) {
+ listener.onAvailabilityChanged(isAvailable);
+ }
+ }
+ }
+ };
+ private final ArrayList<Listener> mListeners = new ArrayList<Listener>();
+ private final IEthernetServiceListener.Stub mServiceListener =
+ new IEthernetServiceListener.Stub() {
+ @Override
+ public void onAvailabilityChanged(boolean isAvailable) {
+ mHandler.obtainMessage(
+ MSG_AVAILABILITY_CHANGED, isAvailable ? 1 : 0, 0, null).sendToTarget();
+ }
+ };
+
+ /**
+ * A listener interface to receive notification on changes in Ethernet.
+ */
+ public interface Listener {
+ /**
+ * Called when Ethernet port's availability is changed.
+ * @param isAvailable {@code true} if one or more Ethernet port exists.
+ */
+ public void onAvailabilityChanged(boolean isAvailable);
+ }
/**
* Create a new EthernetManager instance.
@@ -50,12 +85,9 @@
* @return the Ethernet Configuration, contained in {@link IpConfiguration}.
*/
public IpConfiguration getConfiguration() {
- if (mService == null) {
- return new IpConfiguration();
- }
try {
return mService.getConfiguration();
- } catch (RemoteException e) {
+ } catch (NullPointerException | RemoteException e) {
return new IpConfiguration();
}
}
@@ -64,12 +96,57 @@
* Set Ethernet configuration.
*/
public void setConfiguration(IpConfiguration config) {
- if (mService == null) {
- return;
- }
try {
mService.setConfiguration(config);
- } catch (RemoteException e) {
+ } catch (NullPointerException | RemoteException e) {
+ }
+ }
+
+ /**
+ * Indicates whether the system currently has one or more
+ * Ethernet interfaces.
+ */
+ public boolean isAvailable() {
+ try {
+ return mService.isAvailable();
+ } catch (NullPointerException | RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Adds a listener.
+ * @param listener A {@link Listener} to add.
+ * @throws IllegalArgumentException If the listener is null.
+ */
+ public void addListener(Listener listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+ mListeners.add(listener);
+ if (mListeners.size() == 1) {
+ try {
+ mService.addListener(mServiceListener);
+ } catch (NullPointerException | RemoteException e) {
+ }
+ }
+ }
+
+ /**
+ * Removes a listener.
+ * @param listener A {@link Listener} to remove.
+ * @throws IllegalArgumentException If the listener is null.
+ */
+ public void removeListener(Listener listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+ mListeners.remove(listener);
+ if (mListeners.isEmpty()) {
+ try {
+ mService.removeListener(mServiceListener);
+ } catch (NullPointerException | RemoteException e) {
+ }
}
}
}
diff --git a/core/java/android/net/IEthernetManager.aidl b/core/java/android/net/IEthernetManager.aidl
index 3fa08f8..7a92eb9 100644
--- a/core/java/android/net/IEthernetManager.aidl
+++ b/core/java/android/net/IEthernetManager.aidl
@@ -17,6 +17,7 @@
package android.net;
import android.net.IpConfiguration;
+import android.net.IEthernetServiceListener;
/**
* Interface that answers queries about, and allows changing
@@ -27,4 +28,7 @@
{
IpConfiguration getConfiguration();
void setConfiguration(in IpConfiguration config);
+ boolean isAvailable();
+ void addListener(in IEthernetServiceListener listener);
+ void removeListener(in IEthernetServiceListener listener);
}
diff --git a/core/java/android/net/IEthernetServiceListener.aidl b/core/java/android/net/IEthernetServiceListener.aidl
new file mode 100644
index 0000000..356690e8
--- /dev/null
+++ b/core/java/android/net/IEthernetServiceListener.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+/** @hide */
+oneway interface IEthernetServiceListener
+{
+ void onAvailabilityChanged(boolean isAvailable);
+}
diff --git a/core/java/android/service/trust/ITrustAgentService.aidl b/core/java/android/service/trust/ITrustAgentService.aidl
index bb0c2b2..f07d0d0 100644
--- a/core/java/android/service/trust/ITrustAgentService.aidl
+++ b/core/java/android/service/trust/ITrustAgentService.aidl
@@ -25,6 +25,8 @@
interface ITrustAgentService {
oneway void onUnlockAttempt(boolean successful);
oneway void onTrustTimeout();
+ oneway void onDeviceLocked();
+ oneway void onDeviceUnlocked();
oneway void onConfigure(in List<PersistableBundle> options, IBinder token);
oneway void setCallback(ITrustAgentServiceCallback callback);
}
diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java
index d6c997f..62fa978 100644
--- a/core/java/android/service/trust/TrustAgentService.java
+++ b/core/java/android/service/trust/TrustAgentService.java
@@ -92,6 +92,8 @@
private static final int MSG_UNLOCK_ATTEMPT = 1;
private static final int MSG_CONFIGURE = 2;
private static final int MSG_TRUST_TIMEOUT = 3;
+ private static final int MSG_DEVICE_LOCKED = 4;
+ private static final int MSG_DEVICE_UNLOCKED = 5;
/**
* Class containing raw data for a given configuration request.
@@ -134,6 +136,12 @@
case MSG_TRUST_TIMEOUT:
onTrustTimeout();
break;
+ case MSG_DEVICE_LOCKED:
+ onDeviceLocked();
+ break;
+ case MSG_DEVICE_UNLOCKED:
+ onDeviceUnlocked();
+ break;
}
}
};
@@ -173,6 +181,20 @@
public void onTrustTimeout() {
}
+ /**
+ * Called when the device enters a state where a PIN, pattern or
+ * password must be entered to unlock it.
+ */
+ public void onDeviceLocked() {
+ }
+
+ /**
+ * Called when the device leaves a state where a PIN, pattern or
+ * password must be entered to unlock it.
+ */
+ public void onDeviceUnlocked() {
+ }
+
private void onError(String msg) {
Slog.v(TAG, "Remote exception while " + msg);
}
@@ -300,6 +322,16 @@
.sendToTarget();
}
+ @Override
+ public void onDeviceLocked() throws RemoteException {
+ mHandler.obtainMessage(MSG_DEVICE_LOCKED).sendToTarget();
+ }
+
+ @Override
+ public void onDeviceUnlocked() throws RemoteException {
+ mHandler.obtainMessage(MSG_DEVICE_UNLOCKED).sendToTarget();
+ }
+
@Override /* Binder API */
public void setCallback(ITrustAgentServiceCallback callback) {
synchronized (mLock) {
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index d120d79..dbd580d 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -216,7 +216,7 @@
///////////////////////////////////////////////////////////////////////////
@Override
- public int callDrawGLFunction(long drawGLFunction) {
+ public int callDrawGLFunction2(long drawGLFunction) {
return nCallDrawGLFunction(mRenderer, drawGLFunction);
}
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index e3eee71..18accb8 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -105,10 +105,7 @@
*
* @hide
*/
- public int callDrawGLFunction(long drawGLFunction) {
- // Noop - this is done in the display list recorder subclass
- return RenderNode.STATUS_DONE;
- }
+ public abstract int callDrawGLFunction2(long drawGLFunction);
public abstract void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
CanvasProperty<Float> radius, CanvasProperty<Paint> paint);
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 2c8a499..131c039 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -340,6 +340,7 @@
recordDuration, view.getResources().getDisplayMetrics().density);
if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
setEnabled(false);
+ attachInfo.mViewRootImpl.mSurface.release();
// Invalidate since we failed to draw. This should fetch a Surface
// if it is still needed or do nothing if we are no longer drawing
attachInfo.mViewRootImpl.invalidate();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index fe17417..b12c747 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -245,7 +245,7 @@
// These can be accessed by any thread, must be protected with a lock.
// Surface can never be reassigned or cleared (use Surface.clear()).
- private final Surface mSurface = new Surface();
+ final Surface mSurface = new Surface();
boolean mAdded;
boolean mAddedTouchMode;
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 8e27834..0d82087 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -118,9 +118,6 @@
private Runnable mSystemPropertyUpdater;
- /** Default token to apply to added views. */
- private IBinder mDefaultToken;
-
private WindowManagerGlobal() {
}
@@ -181,17 +178,6 @@
}
}
- /**
- * Sets the default token to use in {@link #addView} when no parent window
- * token is available and no token has been explicitly set in the view's
- * layout params.
- *
- * @param token Default window token to apply to added views.
- */
- public void setDefaultToken(IBinder token) {
- mDefaultToken = token;
- }
-
public String[] getViewRootNames() {
synchronized (mLock) {
final int numRoots = mRoots.size();
@@ -239,10 +225,6 @@
}
}
- if (wparams.token == null && mDefaultToken != null) {
- wparams.token = mDefaultToken;
- }
-
ViewRootImpl root;
View panelParentView = null;
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 52d79f8..98e9f54 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -16,6 +16,9 @@
package android.view;
+import android.annotation.NonNull;
+import android.os.IBinder;
+
/**
* Provides low-level communication with the system window manager for
* operations that are bound to a particular context, display or parent window.
@@ -47,6 +50,8 @@
private final Display mDisplay;
private final Window mParentWindow;
+ private IBinder mDefaultToken;
+
public WindowManagerImpl(Display display) {
this(display, null);
}
@@ -64,16 +69,43 @@
return new WindowManagerImpl(display, mParentWindow);
}
+ /**
+ * Sets the window token to assign when none is specified by the client or
+ * available from the parent window.
+ *
+ * @param token The default token to assign.
+ */
+ public void setDefaultToken(IBinder token) {
+ mDefaultToken = token;
+ }
+
@Override
- public void addView(View view, ViewGroup.LayoutParams params) {
+ public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
+ applyDefaultToken(params);
mGlobal.addView(view, params, mDisplay, mParentWindow);
}
@Override
- public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
+ public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
+ applyDefaultToken(params);
mGlobal.updateViewLayout(view, params);
}
+ private void applyDefaultToken(@NonNull ViewGroup.LayoutParams params) {
+ // Only use the default token if we don't have a parent window.
+ if (mDefaultToken != null && mParentWindow == null) {
+ if (!(params instanceof WindowManager.LayoutParams)) {
+ throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
+ }
+
+ // Only use the default token if we don't already have a token.
+ final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
+ if (wparams.token == null) {
+ wparams.token = mDefaultToken;
+ }
+ }
+ }
+
@Override
public void removeView(View view) {
mGlobal.removeView(view, false);
diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java
index 3dcfda3..e03445e 100644
--- a/core/java/android/webkit/WebViewDelegate.java
+++ b/core/java/android/webkit/WebViewDelegate.java
@@ -107,7 +107,7 @@
throw new IllegalArgumentException(canvas.getClass().getName()
+ " is not hardware accelerated");
}
- ((HardwareCanvas) canvas).callDrawGLFunction(nativeDrawGLFunctor);
+ ((HardwareCanvas) canvas).callDrawGLFunction2(nativeDrawGLFunctor);
}
/**
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 3ccced5..8d3db5b 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -384,8 +384,16 @@
* @return Whether a saved pattern exists.
*/
public boolean savedPatternExists() {
+ return savedPatternExists(getCurrentOrCallingUserId());
+ }
+
+ /**
+ * Check to see if the user has stored a lock pattern.
+ * @return Whether a saved pattern exists.
+ */
+ public boolean savedPatternExists(int userId) {
try {
- return getLockSettings().havePattern(getCurrentOrCallingUserId());
+ return getLockSettings().havePattern(userId);
} catch (RemoteException re) {
return false;
}
@@ -396,8 +404,16 @@
* @return Whether a saved pattern exists.
*/
public boolean savedPasswordExists() {
+ return savedPasswordExists(getCurrentOrCallingUserId());
+ }
+
+ /**
+ * Check to see if the user has stored a lock pattern.
+ * @return Whether a saved pattern exists.
+ */
+ public boolean savedPasswordExists(int userId) {
try {
- return getLockSettings().havePassword(getCurrentOrCallingUserId());
+ return getLockSettings().havePassword(userId);
} catch (RemoteException re) {
return false;
}
@@ -955,8 +971,15 @@
* @return true if the lockscreen method is set to biometric weak
*/
public boolean usingBiometricWeak() {
- int quality =
- (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
+ return usingBiometricWeak(getCurrentOrCallingUserId());
+ }
+
+ /**
+ * @return true if the lockscreen method is set to biometric weak
+ */
+ public boolean usingBiometricWeak(int userId) {
+ int quality = (int) getLong(
+ PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
return quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
}
@@ -1096,15 +1119,22 @@
* @return Whether the lock pattern is enabled, or if it is set as a backup for biometric weak
*/
public boolean isLockPatternEnabled() {
+ return isLockPatternEnabled(getCurrentOrCallingUserId());
+ }
+
+ /**
+ * @return Whether the lock pattern is enabled, or if it is set as a backup for biometric weak
+ */
+ public boolean isLockPatternEnabled(int userId) {
final boolean backupEnabled =
getLong(PASSWORD_TYPE_ALTERNATE_KEY,
- DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)
+ DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId)
== DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
- return getBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, false)
- && (getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)
- == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING ||
- (usingBiometricWeak() && backupEnabled));
+ return getBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, false, userId)
+ && (getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
+ userId) == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
+ || (usingBiometricWeak(userId) && backupEnabled));
}
/**
@@ -1485,15 +1515,20 @@
}
public boolean isSecure() {
- long mode = getKeyguardStoredPasswordQuality();
+ return isSecure(getCurrentOrCallingUserId());
+ }
+
+ public boolean isSecure(int userId) {
+ long mode = getKeyguardStoredPasswordQuality(userId);
final boolean isPattern = mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
final boolean isPassword = mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
|| mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
- final boolean secure = isPattern && isLockPatternEnabled() && savedPatternExists()
- || isPassword && savedPasswordExists();
+ final boolean secure =
+ isPattern && isLockPatternEnabled(userId) && savedPatternExists(userId)
+ || isPassword && savedPasswordExists(userId);
return secure;
}
diff --git a/core/res/res/layout/select_dialog_material.xml b/core/res/res/layout/select_dialog_material.xml
index ee04039..19ad407 100644
--- a/core/res/res/layout/select_dialog_material.xml
+++ b/core/res/res/layout/select_dialog_material.xml
@@ -22,11 +22,14 @@
-->
<view class="com.android.internal.app.AlertController$RecycleListView"
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+android:id/select_dialog_listview"
+ android:id="@id/select_dialog_listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="@null"
- android:divider="?android:attr/listDividerAlertDialog"
+ android:divider="?attr/listDividerAlertDialog"
android:scrollbars="vertical"
android:overScrollMode="ifContentScrolls"
- android:textAlignment="viewStart" />
+ android:textAlignment="viewStart"
+ android:paddingTop="@dimen/dialog_list_padding_vertical_material"
+ android:paddingBottom="@dimen/dialog_list_padding_vertical_material"
+ android:clipToPadding="false" />
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index e3672c8..54f483d 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -97,4 +97,7 @@
<dimen name="dialog_padding_material">24dp</dimen>
<dimen name="dialog_padding_top_material">18dp</dimen>
+
+ <!-- Padding above and below selection dialog lists. -->
+ <dimen name="dialog_list_padding_vertical_material">8dp</dimen>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index c01d406..1123813 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2602,4 +2602,7 @@
<public type="attr" name="dialogPreferredPadding" />
<public type="attr" name="searchHintIcon" />
+ <public type="style" name="Theme.DeviceDefault.Dialog.Alert" />
+ <public type="style" name="Theme.DeviceDefault.Light.Dialog.Alert" />
+
</resources>
diff --git a/core/tests/ConnectivityManagerTest/AndroidManifest.xml b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
index 1649268..6bd8f6e 100644
--- a/core/tests/ConnectivityManagerTest/AndroidManifest.xml
+++ b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
@@ -68,8 +68,9 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<!-- This permission is added for API call setAirplaneMode() in ConnectivityManager -->
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
index f3d5c87..e04c214 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -199,7 +199,7 @@
Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0);
// set wifi sleep policy to never on while in sleep
Settings.Global.putInt(mRunner.getContext().getContentResolver(),
- Settings.Global.WIFI_SLEEP_POLICY, Settings.Global.WIFI_SLEEP_POLICY_NEVER);
+ Settings.Global.WIFI_SLEEP_POLICY, Settings.Global.WIFI_SLEEP_POLICY_DEFAULT);
// set idle timeout for wifi to 15s
Settings.Global.putLong(mRunner.getContext().getContentResolver(),
Settings.Global.WIFI_IDLE_MS, WIFI_IDLE_MS);
diff --git a/graphics/java/android/graphics/ColorMatrix.java b/graphics/java/android/graphics/ColorMatrix.java
index 1242eb5..64f0c05 100644
--- a/graphics/java/android/graphics/ColorMatrix.java
+++ b/graphics/java/android/graphics/ColorMatrix.java
@@ -21,23 +21,43 @@
import java.util.Arrays;
/**
- * 4x5 matrix for transforming the color+alpha components of a Bitmap.
- * The matrix is stored in a single array, and its treated as follows:
+ * 4x5 matrix for transforming the color and alpha components of a Bitmap.
+ * The matrix can be passed as single array, and is treated as follows:
+ *
* <pre>
* [ a, b, c, d, e,
* f, g, h, i, j,
* k, l, m, n, o,
- * p, q, r, s, t ]
- * </pre>
+ * p, q, r, s, t ]</pre>
*
- * When applied to a color <code>[r, g, b, a]</code>, the resulting color
- * is computed as (after clamping):
+ * <p>
+ * When applied to a color <code>[R, G, B, A]</code>, the resulting color
+ * is computed as:
+ * </p>
+ *
* <pre>
- * R' = a*R + b*G + c*B + d*A + e;
- * G' = f*R + g*G + h*B + i*A + j;
- * B' = k*R + l*G + m*B + n*A + o;
- * A' = p*R + q*G + r*B + s*A + t;
- * </pre>
+ * R’ = a*R + b*G + c*B + d*A + e;
+ * G’ = f*R + g*G + h*B + i*A + j;
+ * B’ = k*R + l*G + m*B + n*A + o;
+ * A’ = p*R + q*G + r*B + s*A + t;</pre>
+ *
+ * <p>
+ * That resulting color <code>[R’, G’, B’, A’]</code>
+ * then has each channel clamped to the <code>0</code> to <code>255</code>
+ * range.
+ * </p>
+ *
+ * <p>
+ * The sample ColorMatrix below inverts incoming colors by scaling each
+ * channel by <code>-1</code>, and then shifting the result up by
+ * <code>255</code> to remain in the standard color space.
+ * </p>
+ *
+ * <pre>
+ * [ -1, 0, 0, 0, 255,
+ * 0, -1, 0, 0, 255,
+ * 0, 0, -1, 0, 255,
+ * 0, 0, 0, 1, 0 ]</pre>
*/
@SuppressWarnings({ "MismatchedReadAndWriteOfArray", "PointlessArithmeticExpression" })
public class ColorMatrix {
@@ -52,24 +72,24 @@
}
/**
- * Create a new colormatrix initialized with the specified array of values.
+ * Create a new colormatrix initialized with the specified array of values.
*/
public ColorMatrix(float[] src) {
System.arraycopy(src, 0, mArray, 0, 20);
}
-
+
/**
* Create a new colormatrix initialized with the specified colormatrix.
*/
public ColorMatrix(ColorMatrix src) {
System.arraycopy(src.mArray, 0, mArray, 0, 20);
}
-
+
/**
* Return the array of floats representing this colormatrix.
*/
public final float[] getArray() { return mArray; }
-
+
/**
* Set this colormatrix to identity:
* <pre>
@@ -84,7 +104,7 @@
Arrays.fill(a, 0);
a[0] = a[6] = a[12] = a[18] = 1;
}
-
+
/**
* Assign the src colormatrix into this matrix, copying all of its values.
*/
@@ -98,7 +118,7 @@
public void set(float[] src) {
System.arraycopy(src, 0, mArray, 0, 20);
}
-
+
/**
* Set this colormatrix to scale by the specified values.
*/
@@ -114,12 +134,14 @@
a[12] = bScale;
a[18] = aScale;
}
-
+
/**
* Set the rotation on a color axis by the specified values.
+ * <p>
* <code>axis=0</code> correspond to a rotation around the RED color
* <code>axis=1</code> correspond to a rotation around the GREEN color
* <code>axis=2</code> correspond to a rotation around the BLUE color
+ * </p>
*/
public void setRotate(int axis, float degrees) {
reset();
@@ -153,8 +175,10 @@
/**
* Set this colormatrix to the concatenation of the two specified
* colormatrices, such that the resulting colormatrix has the same effect
- * as applying matB and then applying matA. It is legal for either matA or
- * matB to be the same colormatrix as this.
+ * as applying matB and then applying matA.
+ * <p>
+ * It is legal for either matA or matB to be the same colormatrix as this.
+ * </p>
*/
public void setConcat(ColorMatrix matA, ColorMatrix matB) {
float[] tmp;
@@ -163,7 +187,7 @@
} else {
tmp = mArray;
}
-
+
final float[] a = matA.mArray;
final float[] b = matB.mArray;
int index = 0;
@@ -176,38 +200,43 @@
a[j + 2] * b[14] + a[j + 3] * b[19] +
a[j + 4];
}
-
+
if (tmp != mArray) {
System.arraycopy(tmp, 0, mArray, 0, 20);
}
}
/**
- * Concat this colormatrix with the specified prematrix. This is logically
- * the same as calling setConcat(this, prematrix);
+ * Concat this colormatrix with the specified prematrix.
+ * <p>
+ * This is logically the same as calling setConcat(this, prematrix);
+ * </p>
*/
public void preConcat(ColorMatrix prematrix) {
setConcat(this, prematrix);
}
/**
- * Concat this colormatrix with the specified postmatrix. This is logically
- * the same as calling setConcat(postmatrix, this);
+ * Concat this colormatrix with the specified postmatrix.
+ * <p>
+ * This is logically the same as calling setConcat(postmatrix, this);
+ * </p>
*/
public void postConcat(ColorMatrix postmatrix) {
setConcat(postmatrix, this);
}
///////////////////////////////////////////////////////////////////////////
-
+
/**
- * Set the matrix to affect the saturation of colors. A value of 0 maps the
- * color to gray-scale. 1 is identity.
+ * Set the matrix to affect the saturation of colors.
+ *
+ * @param sat A value of 0 maps the color to gray-scale. 1 is identity.
*/
public void setSaturation(float sat) {
reset();
float[] m = mArray;
-
+
final float invSat = 1 - sat;
final float R = 0.213f * invSat;
final float G = 0.715f * invSat;
@@ -217,7 +246,7 @@
m[5] = R; m[6] = G + sat; m[7] = B;
m[10] = R; m[11] = G; m[12] = B + sat;
}
-
+
/**
* Set the matrix to convert RGB to YUV
*/
@@ -229,7 +258,7 @@
m[5] = -0.16874f; m[6] = -0.33126f; m[7] = 0.5f;
m[10] = 0.5f; m[11] = -0.41869f; m[12] = -0.08131f;
}
-
+
/**
* Set the matrix to convert from YUV to RGB
*/
@@ -242,4 +271,3 @@
m[10] = 1; m[11] = 1.772f; m[12] = 0;
}
}
-
diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
index 6d23634..f58a765 100644
--- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
@@ -199,6 +199,8 @@
return false;
}
+ boolean hasReversibleFlag = state.transitionHasReversibleFlag(fromId, toId);
+
// This may fail if we're already on the transition, but that's okay!
selectDrawable(transitionIndex);
@@ -206,10 +208,14 @@
final Drawable d = getCurrent();
if (d instanceof AnimationDrawable) {
final boolean reversed = state.isTransitionReversed(fromId, toId);
- transition = new AnimationDrawableTransition((AnimationDrawable) d, reversed);
+
+ transition = new AnimationDrawableTransition((AnimationDrawable) d,
+ reversed, hasReversibleFlag);
} else if (d instanceof AnimatedVectorDrawable) {
final boolean reversed = state.isTransitionReversed(fromId, toId);
- transition = new AnimatedVectorDrawableTransition((AnimatedVectorDrawable) d, reversed);
+
+ transition = new AnimatedVectorDrawableTransition((AnimatedVectorDrawable) d,
+ reversed, hasReversibleFlag);
} else if (d instanceof Animatable) {
transition = new AnimatableTransition((Animatable) d);
} else {
@@ -260,7 +266,12 @@
private static class AnimationDrawableTransition extends Transition {
private final ObjectAnimator mAnim;
- public AnimationDrawableTransition(AnimationDrawable ad, boolean reversed) {
+ // Even AnimationDrawable is always reversible technically, but
+ // we should obey the XML's android:reversible flag.
+ private final boolean mHasReversibleFlag;
+
+ public AnimationDrawableTransition(AnimationDrawable ad,
+ boolean reversed, boolean hasReversibleFlag) {
final int frameCount = ad.getNumberOfFrames();
final int fromFrame = reversed ? frameCount - 1 : 0;
final int toFrame = reversed ? 0 : frameCount - 1;
@@ -269,13 +280,13 @@
anim.setAutoCancel(true);
anim.setDuration(interp.getTotalDuration());
anim.setInterpolator(interp);
-
+ mHasReversibleFlag = hasReversibleFlag;
mAnim = anim;
}
@Override
public boolean canReverse() {
- return true;
+ return mHasReversibleFlag;
}
@Override
@@ -296,16 +307,28 @@
private static class AnimatedVectorDrawableTransition extends Transition {
private final AnimatedVectorDrawable mAvd;
+
+ // mReversed is indicating the current transition's direction.
private final boolean mReversed;
- public AnimatedVectorDrawableTransition(AnimatedVectorDrawable avd, boolean reversed) {
+ // mHasReversibleFlag is indicating whether the whole transition has
+ // reversible flag set to true.
+ // If mHasReversibleFlag is false, then mReversed is always false.
+ private final boolean mHasReversibleFlag;
+
+ public AnimatedVectorDrawableTransition(AnimatedVectorDrawable avd,
+ boolean reversed, boolean hasReversibleFlag) {
mAvd = avd;
mReversed = reversed;
+ mHasReversibleFlag = hasReversibleFlag;
}
@Override
public boolean canReverse() {
- return mAvd.canReverse();
+ // When the transition's XML says it is not reversible, then we obey
+ // it, even if the AVD itself is reversible.
+ // This will help the single direction transition.
+ return mAvd.canReverse() && mHasReversibleFlag;
}
@Override
@@ -322,7 +345,8 @@
if (canReverse()) {
mAvd.reverse();
} else {
- Log.w(LOGTAG, "Reverse() is called on a drawable can't reverse");
+ Log.w(LOGTAG, "Can't reverse, either the reversible is set to false,"
+ + " or the AnimatedVectorDrawable can't reverse");
}
}
@@ -520,8 +544,12 @@
}
static class AnimatedStateListState extends StateListState {
- private static final int REVERSE_SHIFT = 32;
- private static final int REVERSE_MASK = 0x1;
+ // REVERSED_BIT is indicating the current transition's direction.
+ private static final long REVERSED_BIT = 0x100000000l;
+
+ // REVERSIBLE_FLAG_BIT is indicating whether the whole transition has
+ // reversible flag set to true.
+ private static final long REVERSIBLE_FLAG_BIT = 0x200000000l;
int[] mAnimThemeAttrs;
@@ -545,11 +573,15 @@
int addTransition(int fromId, int toId, @NonNull Drawable anim, boolean reversible) {
final int pos = super.addChild(anim);
final long keyFromTo = generateTransitionKey(fromId, toId);
- mTransitions.append(keyFromTo, pos);
+ long reversibleBit = 0;
+ if (reversible) {
+ reversibleBit = REVERSIBLE_FLAG_BIT;
+ }
+ mTransitions.append(keyFromTo, pos | reversibleBit);
if (reversible) {
final long keyToFrom = generateTransitionKey(toId, fromId);
- mTransitions.append(keyToFrom, pos | (1L << REVERSE_SHIFT));
+ mTransitions.append(keyToFrom, pos | REVERSED_BIT | reversibleBit);
}
return addChild(anim);
@@ -581,7 +613,12 @@
boolean isTransitionReversed(int fromId, int toId) {
final long keyFromTo = generateTransitionKey(fromId, toId);
- return (mTransitions.get(keyFromTo, -1) >> REVERSE_SHIFT & REVERSE_MASK) == 1;
+ return (mTransitions.get(keyFromTo, -1) & REVERSED_BIT) != 0;
+ }
+
+ boolean transitionHasReversibleFlag(int fromId, int toId) {
+ final long keyFromTo = generateTransitionKey(fromId, toId);
+ return (mTransitions.get(keyFromTo, -1) & REVERSIBLE_FLAG_BIT) != 0;
}
@Override
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index d0edeba..e9c8c2a 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -462,19 +462,22 @@
/**
* Reverses ongoing animations or starts pending animations in reverse.
* <p>
- * NOTE: Only works of all animations are ValueAnimators.
+ * NOTE: Only works if all animations support reverse. Otherwise, this will
+ * do nothing.
* @hide
*/
public void reverse() {
+ // Only reverse when all the animators can be reverse. Otherwise, partially
+ // reverse is confusing.
+ if (!canReverse()) {
+ Log.w(LOGTAG, "AnimatedVectorDrawable can't reverse()");
+ return;
+ }
final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
final int size = animators.size();
for (int i = 0; i < size; i++) {
final Animator animator = animators.get(i);
- if (animator.canReverse()) {
- animator.reverse();
- } else {
- Log.w(LOGTAG, "AnimatedVectorDrawable can't reverse()");
- }
+ animator.reverse();
}
}
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 58ed4f8..9a0266d 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -128,6 +128,29 @@
/**
* @hide
+ * Return the input channel mask corresponding to an output channel mask.
+ * This can be used for submix rerouting for the mask of the recorder to map to that of the mix.
+ * @param outMask a combination of the CHANNEL_OUT_* definitions, but not CHANNEL_OUT_DEFAULT
+ * @return a combination of CHANNEL_IN_* definitions matching an output channel mask
+ * @throws IllegalArgumentException
+ */
+ public static int inChannelMaskFromOutChannelMask(int outMask) throws IllegalArgumentException {
+ if (outMask == CHANNEL_OUT_DEFAULT) {
+ throw new IllegalArgumentException(
+ "Illegal CHANNEL_OUT_DEFAULT channel mask for input.");
+ }
+ switch (channelCountFromOutChannelMask(outMask)) {
+ case 1:
+ return CHANNEL_IN_MONO;
+ case 2:
+ return CHANNEL_IN_STEREO;
+ default:
+ throw new IllegalArgumentException("Unsupported channel configuration for input.");
+ }
+ }
+
+ /**
+ * @hide
* Return the number of channels from an input channel mask
* @param mask a combination of the CHANNEL_IN_* definitions, even CHANNEL_IN_DEFAULT
* @return number of channels for the mask
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 255d828..e9dc3af 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -155,6 +155,7 @@
{
throw new IllegalArgumentException("Invalid AudioMix: not defined for loop back");
}
+ // TODO also check mix is defined for playback or recording, and matches forTrack argument
}
/**
@@ -175,13 +176,19 @@
return null;
}
checkMixReadyToUse(mix, false/*not for an AudioTrack*/);
+ // create an AudioFormat from the mix format compatible with recording, as the mix
+ // was defined for playback
+ AudioFormat mixFormat = new AudioFormat.Builder(mix.getFormat())
+ .setChannelMask(AudioFormat.inChannelMaskFromOutChannelMask(
+ mix.getFormat().getChannelMask()))
+ .build();
// create the AudioRecord, configured for loop back, using the same format as the mix
AudioRecord ar = new AudioRecord(
new AudioAttributes.Builder()
.setInternalCapturePreset(MediaRecorder.AudioSource.REMOTE_SUBMIX)
.addTag(mix.getRegistration())
.build(),
- mix.getFormat(),
+ mixFormat,
AudioRecord.getMinBufferSize(mix.getFormat().getSampleRate(),
// using stereo for buffer size to avoid the current poor support for masks
AudioFormat.CHANNEL_IN_STEREO, mix.getFormat().getEncoding()),
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 51bd205..de9d54f 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -1012,6 +1012,12 @@
/**
* Returns the TvStreamConfig list of the given TV input.
*
+ * If you are using {@link Hardware} object from {@link
+ * #acquireTvInputHardware}, you should get the list of available streams
+ * from {@link HardwareCallback#onStreamConfigChanged} method, not from
+ * here. This method is designed to be used with {@link #captureFrame} in
+ * capture scenarios specifically and not suitable for any other use.
+ *
* @param inputId the id of the TV input.
* @return List of {@link TvStreamConfig} which is available for capturing
* of the given TV input.
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index f9d84c1..6fc1b82 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -18,7 +18,10 @@
import android.annotation.SystemApi;
import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.PorterDuff;
import android.graphics.Rect;
+import android.graphics.Region;
import android.media.tv.TvInputManager.Session;
import android.media.tv.TvInputManager.Session.FinishedInputEventCallback;
import android.media.tv.TvInputManager.SessionCallback;
@@ -593,6 +596,42 @@
}
@Override
+ public boolean gatherTransparentRegion(Region region) {
+ if (mWindowZOrder != ZORDER_ON_TOP) {
+ if (region != null) {
+ int width = getWidth();
+ int height = getHeight();
+ if (width > 0 && height > 0) {
+ int location[] = new int[2];
+ getLocationInWindow(location);
+ int left = location[0];
+ int top = location[1];
+ region.op(left, top, left + width, top + height, Region.Op.UNION);
+ }
+ }
+ }
+ return super.gatherTransparentRegion(region);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ if (mWindowZOrder != ZORDER_ON_TOP) {
+ // Punch a hole so that the underlying overlay view and surface can be shown.
+ canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+ }
+ super.draw(canvas);
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ if (mWindowZOrder != ZORDER_ON_TOP) {
+ // Punch a hole so that the underlying overlay view and surface can be shown.
+ canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+ }
+ super.dispatchDraw(canvas);
+ }
+
+ @Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
mSurfaceView.setVisibility(visibility);
diff --git a/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml b/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml
index 63694a8..00193ed 100644
--- a/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml
+++ b/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml
@@ -44,15 +44,21 @@
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:text="Report unlock attempts" />
+ <CheckBox android:id="@+id/report_device_locked"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:text="Report device locked or unlocked" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
- <Button android:id="@+id/check_trusted"
+ <Button android:id="@+id/check_device_locked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="Keyguard in trusted state?" />
- <TextView android:id="@+id/check_trusted_result"
+ android:text="Device locked?" />
+ <TextView android:id="@+id/check_device_locked_result"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
index f28d0e4..e6a0dd7 100644
--- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
@@ -56,6 +56,7 @@
= "preference.report_unlock_attempts";
private static final String PREFERENCE_MANAGING_TRUST
= "preference.managing_trust";
+ private static final String PREFERENCE_REPORT_DEVICE_LOCKED = "preference.report_device_locked";
private static final String TAG = "SampleTrustAgent";
@@ -80,17 +81,37 @@
@Override
public void onTrustTimeout() {
super.onTrustTimeout();
- Toast.makeText(this, "onTrustTimeout(): timeout expired", Toast.LENGTH_SHORT).show();
+ logAndShowToast("onTrustTimeout(): timeout expired");
+ }
+
+ @Override
+ public void onDeviceLocked() {
+ super.onDeviceLocked();
+ if (getReportDeviceLocked(this)) {
+ logAndShowToast("onDeviceLocked(): device is now locked");
+ }
+ }
+
+ @Override
+ public void onDeviceUnlocked() {
+ super.onDeviceUnlocked();
+ if (getReportDeviceLocked(this)) {
+ logAndShowToast("onDeviceUnlocked(): device is now unlocked");
+ }
}
@Override
public void onUnlockAttempt(boolean successful) {
if (getReportUnlockAttempts(this)) {
- Toast.makeText(this, "onUnlockAttempt(successful=" + successful + ")",
- Toast.LENGTH_SHORT).show();
+ logAndShowToast("onUnlockAttempt(successful=" + successful + ")");
}
}
+ private void logAndShowToast(String text) {
+ Log.i(TAG, text);
+ Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
+ }
+
@Override
public boolean onConfigure(List<PersistableBundle> options) {
if (options != null) {
@@ -125,8 +146,7 @@
intent.getLongExtra(EXTRA_DURATION, 0),
intent.getBooleanExtra(EXTRA_INITIATED_BY_USER, false));
} catch (IllegalStateException e) {
- Toast.makeText(context,
- "IllegalStateException: " + e.getMessage(), Toast.LENGTH_SHORT).show();
+ logAndShowToast("IllegalStateException: " + e.getMessage());
}
} else if (ACTION_REVOKE_TRUST.equals(action)) {
revokeTrust();
@@ -160,6 +180,18 @@
return sharedPreferences.getBoolean(PREFERENCE_REPORT_UNLOCK_ATTEMPTS, false);
}
+ public static void setReportDeviceLocked(Context context, boolean enabled) {
+ SharedPreferences sharedPreferences = PreferenceManager
+ .getDefaultSharedPreferences(context);
+ sharedPreferences.edit().putBoolean(PREFERENCE_REPORT_DEVICE_LOCKED, enabled).apply();
+ }
+
+ public static boolean getReportDeviceLocked(Context context) {
+ SharedPreferences sharedPreferences = PreferenceManager
+ .getDefaultSharedPreferences(context);
+ return sharedPreferences.getBoolean(PREFERENCE_REPORT_DEVICE_LOCKED, false);
+ }
+
public static void setIsManagingTrust(Context context, boolean enabled) {
SharedPreferences sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(context);
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
index 39a599e..29b15cb 100644
--- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
@@ -31,8 +31,9 @@
private static final int TRUST_DURATION_MS = 30 * 1000;
private CheckBox mReportUnlockAttempts;
+ private CheckBox mReportDeviceLocked;
private CheckBox mManagingTrust;
- private TextView mCheckTrustedStateResult;
+ private TextView mCheckDeviceLockedResult;
private KeyguardManager mKeyguardManager;
@@ -48,15 +49,18 @@
findViewById(R.id.enable_trust).setOnClickListener(this);
findViewById(R.id.revoke_trust).setOnClickListener(this);
findViewById(R.id.crash).setOnClickListener(this);
- findViewById(R.id.check_trusted).setOnClickListener(this);
+ findViewById(R.id.check_device_locked).setOnClickListener(this);
mReportUnlockAttempts = (CheckBox) findViewById(R.id.report_unlock_attempts);
mReportUnlockAttempts.setOnCheckedChangeListener(this);
+ mReportDeviceLocked = (CheckBox) findViewById(R.id.report_device_locked);
+ mReportDeviceLocked.setOnCheckedChangeListener(this);
+
mManagingTrust = (CheckBox) findViewById(R.id.managing_trust);
mManagingTrust.setOnCheckedChangeListener(this);
- mCheckTrustedStateResult = (TextView) findViewById(R.id.check_trusted_result);
+ mCheckDeviceLockedResult = (TextView) findViewById(R.id.check_device_locked_result);
}
@Override
@@ -77,7 +81,7 @@
SampleTrustAgent.sendRevokeTrust(this);
} else if (id == R.id.crash) {
throw new RuntimeException("crash");
- } else if (id == R.id.check_trusted) {
+ } else if (id == R.id.check_device_locked) {
updateTrustedState();
}
}
@@ -88,11 +92,13 @@
SampleTrustAgent.setReportUnlockAttempts(this, isChecked);
} else if (buttonView == mManagingTrust) {
SampleTrustAgent.setIsManagingTrust(this, isChecked);
+ } else if (buttonView == mReportDeviceLocked) {
+ SampleTrustAgent.setReportDeviceLocked(this, isChecked);
}
}
private void updateTrustedState() {
- mCheckTrustedStateResult.setText(Boolean.toString(
- mKeyguardManager.isKeyguardInTrustedState()));
+ mCheckDeviceLockedResult.setText(Boolean.toString(
+ mKeyguardManager.isDeviceLocked()));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 20e418c..5f92dc6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -23,6 +23,7 @@
import android.app.PendingIntent;
import android.app.SearchManager;
import android.app.StatusBarManager;
+import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -187,8 +188,9 @@
/** High level access to the window manager for dismissing keyguard animation */
private IWindowManager mWM;
- /** UserManager for querying number of users */
- private UserManager mUserManager;
+
+ /** TrustManager for letting it know when we change visibility */
+ private TrustManager mTrustManager;
/** SearchManager for determining whether or not search assistant is available */
private SearchManager mSearchManager;
@@ -484,7 +486,8 @@
private void setup() {
mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mWM = WindowManagerGlobal.getWindowManagerService();
- mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mTrustManager = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
+
mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
mShowKeyguardWakeLock.setReferenceCounted(false);
@@ -501,6 +504,7 @@
// Assume keyguard is showing (unless it's disabled) until we know for sure...
mShowing = !shouldWaitForProvisioning() && !mLockPatternUtils.isLockScreenDisabled();
+ mTrustManager.reportKeyguardShowingChanged();
mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(mContext,
mViewMediatorCallback, mLockPatternUtils);
@@ -931,7 +935,7 @@
if (mLockPatternUtils.checkVoldPassword()) {
if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
// Without this, settings is not enabled until the lock screen first appears
- mShowing = false;
+ setShowing(false);
hideLocked();
return;
}
@@ -1249,7 +1253,7 @@
mStatusBarKeyguardViewManager.show(options);
mHiding = false;
- mShowing = true;
+ setShowing(true);
resetKeyguardDonePendingLocked();
mHideAnimationRun = false;
updateActivityLockScreenState();
@@ -1328,7 +1332,7 @@
}
mStatusBarKeyguardViewManager.hide(startTime, fadeoutDuration);
- mShowing = false;
+ setShowing(false);
resetKeyguardDonePendingLocked();
mHideAnimationRun = false;
updateActivityLockScreenState();
@@ -1389,7 +1393,7 @@
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
mStatusBarKeyguardViewManager.verifyUnlock();
- mShowing = true;
+ setShowing(true);
updateActivityLockScreenState();
}
}
@@ -1471,4 +1475,12 @@
this.fadeoutDuration = fadeoutDuration;
}
}
+
+ private void setShowing(boolean showing) {
+ boolean changed = (showing != mShowing);
+ mShowing = showing;
+ if (changed) {
+ mTrustManager.reportKeyguardShowingChanged();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index bb9a105..38ce467 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -32,6 +32,7 @@
import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.Handler;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Pair;
import android.view.LayoutInflater;
@@ -361,8 +362,7 @@
// If the user has toggled it too quickly, then just eat up the event here (it's better than
// showing a janky screenshot).
// NOTE: Ideally, the screenshot mechanism would take the window transform into account
- long currentTime = System.currentTimeMillis();
- if ((currentTime > mLastToggleTime) && (currentTime - mLastToggleTime) < sMinToggleDelay) {
+ if ((SystemClock.elapsedRealtime() - mLastToggleTime) < sMinToggleDelay) {
return;
}
@@ -377,7 +377,7 @@
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
- mLastToggleTime = System.currentTimeMillis();
+ mLastToggleTime = SystemClock.elapsedRealtime();
return;
} else {
// Otherwise, start the recents activity
@@ -559,7 +559,7 @@
startAlternateRecentsActivity(topTask, opts, EXTRA_FROM_HOME, stackVr);
}
}
- mLastToggleTime = System.currentTimeMillis();
+ mLastToggleTime = SystemClock.elapsedRealtime();
}
/** Starts the recents activity */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 676f1ab..6dc2edb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -28,6 +28,7 @@
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Bundle;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Pair;
import android.view.KeyEvent;
@@ -564,13 +565,13 @@
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_TAB: {
- boolean hasRepKeyTimeElapsed = (System.currentTimeMillis() -
+ boolean hasRepKeyTimeElapsed = (SystemClock.elapsedRealtime() -
mLastTabKeyEventTime) > mConfig.altTabKeyDelay;
if (event.getRepeatCount() <= 0 || hasRepKeyTimeElapsed) {
// Focus the next task in the stack
final boolean backward = event.isShiftPressed();
mRecentsView.focusNextTask(!backward);
- mLastTabKeyEventTime = System.currentTimeMillis();
+ mLastTabKeyEventTime = SystemClock.elapsedRealtime();
}
return true;
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 17889ea..c26df02 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3839,9 +3839,8 @@
int notificationType) {
if (notificationType == ConnectivityManager.CALLBACK_AVAILABLE) {
Intent intent = new Intent();
- intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST_NETWORK, nri.request);
- intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST_NETWORK_REQUEST,
- networkAgent.network);
+ intent.putExtra(ConnectivityManager.EXTRA_NETWORK, nri.request);
+ intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST, networkAgent.network);
sendIntent(nri.mPendingIntent, intent);
}
// else not handled
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index 4906bd1..57b204d 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -232,6 +232,12 @@
mTrustManagerService.mArchive.logAgentConnected(mUserId, name);
setCallback(mCallback);
updateDevicePolicyFeatures();
+
+ if (mTrustManagerService.isDeviceLockedInner(mUserId)) {
+ onDeviceLocked();
+ } else {
+ onDeviceUnlocked();
+ }
}
@Override
@@ -287,6 +293,7 @@
onError(e);
}
}
+
/**
* @see android.service.trust.TrustAgentService#onUnlockAttempt(boolean)
*/
@@ -298,6 +305,28 @@
}
}
+ /**
+ * @see android.service.trust.TrustAgentService#onDeviceLocked()
+ */
+ public void onDeviceLocked() {
+ try {
+ if (mTrustAgentService != null) mTrustAgentService.onDeviceLocked();
+ } catch (RemoteException e) {
+ onError(e);
+ }
+ }
+
+ /**
+ * @see android.service.trust.TrustAgentService#onDeviceUnlocked()
+ */
+ public void onDeviceUnlocked() {
+ try {
+ if (mTrustAgentService != null) mTrustAgentService.onDeviceUnlocked();
+ } catch (RemoteException e) {
+ onError(e);
+ }
+ }
+
private void setCallback(ITrustAgentServiceCallback callback) {
try {
if (mTrustAgentService != null) {
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 2388c85..a2ea1c8 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -26,7 +26,6 @@
import android.Manifest;
import android.app.ActivityManager;
-import android.app.ActivityManagerNative;
import android.app.admin.DevicePolicyManager;
import android.app.trust.ITrustListener;
import android.app.trust.ITrustManager;
@@ -61,6 +60,8 @@
import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.Xml;
+import android.view.IWindowManager;
+import android.view.WindowManagerGlobal;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -96,6 +97,10 @@
private static final int MSG_DISPATCH_UNLOCK_ATTEMPT = 3;
private static final int MSG_ENABLED_AGENTS_CHANGED = 4;
private static final int MSG_REQUIRE_CREDENTIAL_ENTRY = 5;
+ private static final int MSG_KEYGUARD_SHOWING_CHANGED = 6;
+ private static final int MSG_START_USER = 7;
+ private static final int MSG_CLEANUP_USER = 8;
+ private static final int MSG_SWITCH_USER = 9;
private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>();
private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>();
@@ -110,7 +115,11 @@
@GuardedBy("mUserIsTrusted")
private final SparseBooleanArray mUserIsTrusted = new SparseBooleanArray();
+ @GuardedBy("mDeviceLockedForUser")
+ private final SparseBooleanArray mDeviceLockedForUser = new SparseBooleanArray();
+
private boolean mTrustAgentsCanRun = false;
+ private int mCurrentUser = UserHandle.USER_OWNER;
public TrustManagerService(Context context) {
super(context);
@@ -177,10 +186,15 @@
public void updateTrust(int userId, boolean initiatedByUser) {
dispatchOnTrustManagedChanged(aggregateIsTrustManaged(userId), userId);
boolean trusted = aggregateIsTrusted(userId);
+ boolean changed;
synchronized (mUserIsTrusted) {
+ changed = mUserIsTrusted.get(userId) != trusted;
mUserIsTrusted.put(userId, trusted);
}
dispatchOnTrustChanged(trusted, userId, initiatedByUser);
+ if (changed) {
+ refreshDeviceLockedForUser(userId);
+ }
}
void refreshAgentList(int userId) {
@@ -212,8 +226,7 @@
|| userInfo.guestToRemove) continue;
if (!userInfo.supportsSwitchTo()) continue;
if (!mActivityManager.isUserRunning(userInfo.id)) continue;
- if (lockPatternUtils.getKeyguardStoredPasswordQuality(userInfo.id)
- == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) continue;
+ if (!lockPatternUtils.isSecure(userInfo.id)) continue;
if (!mUserHasAuthenticatedSinceBoot.get(userInfo.id)) continue;
DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
@@ -273,6 +286,73 @@
}
}
+ boolean isDeviceLockedInner(int userId) {
+ synchronized (mDeviceLockedForUser) {
+ return mDeviceLockedForUser.get(userId, true);
+ }
+ }
+
+ private void refreshDeviceLockedForUser(int userId) {
+ if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_OWNER) {
+ Log.e(TAG, "refreshAgentList(userId=" + userId + "): Invalid user handle,"
+ + " must be USER_ALL or a specific user.", new Throwable("here"));
+ userId = UserHandle.USER_ALL;
+ }
+
+ List<UserInfo> userInfos;
+ if (userId == UserHandle.USER_ALL) {
+ userInfos = mUserManager.getUsers(true /* excludeDying */);
+ } else {
+ userInfos = new ArrayList<>();
+ userInfos.add(mUserManager.getUserInfo(userId));
+ }
+
+ IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+
+ for (int i = 0; i < userInfos.size(); i++) {
+ UserInfo info = userInfos.get(i);
+
+ if (info == null || info.partial || !info.isEnabled() || info.guestToRemove
+ || !info.supportsSwitchTo()) {
+ continue;
+ }
+
+ int id = info.id;
+ boolean secure = mLockPatternUtils.isSecure(id);
+ boolean trusted = aggregateIsTrusted(id);
+ boolean showingKeyguard = true;
+ if (mCurrentUser == id) {
+ try {
+ showingKeyguard = wm.isKeyguardLocked();
+ } catch (RemoteException e) {
+ }
+ }
+ boolean deviceLocked = secure && showingKeyguard && !trusted;
+
+ boolean changed;
+ synchronized (mDeviceLockedForUser) {
+ changed = isDeviceLockedInner(id) != deviceLocked;
+ mDeviceLockedForUser.put(id, deviceLocked);
+ }
+ if (changed) {
+ dispatchDeviceLocked(id, deviceLocked);
+ }
+ }
+ }
+
+ private void dispatchDeviceLocked(int userId, boolean isLocked) {
+ for (int i = 0; i < mActiveAgents.size(); i++) {
+ AgentInfo agent = mActiveAgents.valueAt(i);
+ if (agent.userId == userId) {
+ if (isLocked) {
+ agent.agent.onDeviceLocked();
+ } else{
+ agent.agent.onDeviceUnlocked();
+ }
+ }
+ }
+ }
+
void updateDevicePolicyFeatures() {
for (int i = 0; i < mActiveAgents.size(); i++) {
AgentInfo info = mActiveAgents.valueAt(i);
@@ -540,12 +620,17 @@
@Override
public void onStartUser(int userId) {
- refreshAgentList(userId);
+ mHandler.obtainMessage(MSG_START_USER, userId, 0, null).sendToTarget();
}
@Override
public void onCleanupUser(int userId) {
- refreshAgentList(userId);
+ mHandler.obtainMessage(MSG_CLEANUP_USER, userId, 0, null).sendToTarget();
+ }
+
+ @Override
+ public void onSwitchUser(int userId) {
+ mHandler.obtainMessage(MSG_SWITCH_USER, userId, 0, null).sendToTarget();
}
// Plumbing
@@ -578,6 +663,14 @@
}
@Override
+ public void reportKeyguardShowingChanged() throws RemoteException {
+ enforceReportPermission();
+ // coalesce refresh messages.
+ mHandler.removeMessages(MSG_KEYGUARD_SHOWING_CHANGED);
+ mHandler.sendEmptyMessage(MSG_KEYGUARD_SHOWING_CHANGED);
+ }
+
+ @Override
public void registerTrustListener(ITrustListener trustListener) throws RemoteException {
enforceListenerPermission();
mHandler.obtainMessage(MSG_REGISTER_LISTENER, trustListener).sendToTarget();
@@ -590,13 +683,12 @@
}
@Override
- public boolean isTrusted(int userId) throws RemoteException {
+ public boolean isDeviceLocked(int userId) throws RemoteException {
userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
- false /* allowAll */, true /* requireFull */, "isTrusted", null);
+ false /* allowAll */, true /* requireFull */, "isDeviceLocked", null);
userId = resolveProfileParent(userId);
- synchronized (mUserIsTrusted) {
- return mUserIsTrusted.get(userId);
- }
+
+ return isDeviceLockedInner(userId);
}
private void enforceReportPermission() {
@@ -621,19 +713,13 @@
fout.println("disabled because the third-party apps can't run yet.");
return;
}
- final UserInfo currentUser;
final List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
- try {
- currentUser = ActivityManagerNative.getDefault().getCurrentUser();
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
mHandler.runWithScissors(new Runnable() {
@Override
public void run() {
fout.println("Trust manager state:");
for (UserInfo user : userInfos) {
- dumpUser(fout, user, user.id == currentUser.id);
+ dumpUser(fout, user, user.id == mCurrentUser);
}
}
}, 1500);
@@ -642,11 +728,17 @@
private void dumpUser(PrintWriter fout, UserInfo user, boolean isCurrent) {
fout.printf(" User \"%s\" (id=%d, flags=%#x)",
user.name, user.id, user.flags);
+ if (!user.supportsSwitchTo()) {
+ fout.println("(managed profile)");
+ fout.println(" disabled because switching to this user is not possible.");
+ return;
+ }
if (isCurrent) {
fout.print(" (current)");
}
fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id)));
fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id)));
+ fout.print(", deviceLocked=" + dumpBool(isDeviceLockedInner(user.id)));
fout.println();
fout.println(" Enabled agents:");
boolean duplicateSimpleNames = false;
@@ -711,10 +803,23 @@
break;
case MSG_ENABLED_AGENTS_CHANGED:
refreshAgentList(UserHandle.USER_ALL);
+ // This is also called when the security mode of a user changes.
+ refreshDeviceLockedForUser(UserHandle.USER_ALL);
break;
case MSG_REQUIRE_CREDENTIAL_ENTRY:
requireCredentialEntry(msg.arg1);
break;
+ case MSG_KEYGUARD_SHOWING_CHANGED:
+ refreshDeviceLockedForUser(UserHandle.USER_CURRENT);
+ break;
+ case MSG_START_USER:
+ case MSG_CLEANUP_USER:
+ refreshAgentList(msg.arg1);
+ break;
+ case MSG_SWITCH_USER:
+ mCurrentUser = msg.arg1;
+ refreshDeviceLockedForUser(UserHandle.USER_ALL);
+ break;
}
}
};
@@ -756,8 +861,14 @@
int userId = getUserId(intent);
if (userId > 0) {
mUserHasAuthenticatedSinceBoot.delete(userId);
- mUserIsTrusted.delete(userId);
+ synchronized (mUserIsTrusted) {
+ mUserIsTrusted.delete(userId);
+ }
+ synchronized (mDeviceLockedForUser) {
+ mDeviceLockedForUser.delete(userId);
+ }
refreshAgentList(userId);
+ refreshDeviceLockedForUser(userId);
}
}
}
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index c3cbbd3..716487c 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -681,7 +681,7 @@
throw new IllegalStateException("Device already released.");
}
- int result = TvInputHal.ERROR_UNKNOWN;
+ int result = TvInputHal.SUCCESS;
if (surface == null) {
// The value of config is ignored when surface == null.
if (mActiveConfig != null) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 1086eb2..f859fd2 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -254,15 +254,18 @@
@Override
void removeAllWindows() {
- int winNdx;
- while ((winNdx = allAppWindows.size()) > 0) {
- WindowState win = allAppWindows.get(winNdx - 1);
+ for (int winNdx = allAppWindows.size() - 1; winNdx >= 0;
+ // removeWindowLocked at bottom of loop may remove multiple entries from
+ // allAppWindows if the window to be removed has child windows. It also may
+ // not remove any windows from allAppWindows at all if win is exiting and
+ // currently animating away. This ensures that winNdx is monotonically decreasing
+ // and never beyond allAppWindows bounds.
+ winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) {
+ WindowState win = allAppWindows.get(winNdx);
if (WindowManagerService.DEBUG_WINDOW_MOVEMENT) {
Slog.w(WindowManagerService.TAG, "removeAllWindows: removing win=" + win);
}
- // {@link WindowManagerService.removeWindowLocked} may remove multiple entries from
- // {@link #allAppWindows} if the window to be removed has child windows.
win.mService.removeWindowLocked(win.mSession, win);
}
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index c63eb18..23ba3b6 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -209,8 +209,13 @@
mUseUsbNotification = !massStorageSupported;
// make sure the ADB_ENABLED setting value matches the current state
- Settings.Global.putInt(mContentResolver, Settings.Global.ADB_ENABLED, mAdbEnabled ? 1 : 0);
-
+ try {
+ Settings.Global.putInt(mContentResolver,
+ Settings.Global.ADB_ENABLED, mAdbEnabled ? 1 : 0);
+ } catch (SecurityException e) {
+ // If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't be changed.
+ Slog.d(TAG, "ADB_ENABLED is restricted.");
+ }
mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
}
diff --git a/tests/VectorDrawableTest/res/anim/animation_grouping_1_01.xml b/tests/VectorDrawableTest/res/anim/animation_grouping_1_01.xml
index 8d82d05..8ab79a5 100644
--- a/tests/VectorDrawableTest/res/anim/animation_grouping_1_01.xml
+++ b/tests/VectorDrawableTest/res/anim/animation_grouping_1_01.xml
@@ -15,12 +15,8 @@
limitations under the License.
-->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-
- <objectAnimator
- android:duration="3300"
- android:propertyName="rotation"
- android:valueFrom="0"
- android:valueTo="360"
- android:repeatCount="-1" />
-</set>
\ No newline at end of file
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:duration="3300"
+ android:propertyName="rotation"
+ android:valueFrom="0"
+ android:valueTo="450" />
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_drawable04.xml b/tests/VectorDrawableTest/res/drawable/state_animation_drawable04.xml
new file mode 100644
index 0000000..a0a801c
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_drawable04.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+
+<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/on" android:state_checked="true"
+ android:drawable="@drawable/vector_drawable_favorite" />
+ <item android:id="@+id/off"
+ android:drawable="@drawable/vector_drawable_favorite" />
+ <transition android:fromId="@+id/off" android:toId="@+id/on"
+ android:drawable="@drawable/animation_drawable_vector"
+ android:reversible="true">
+ </transition>
+</animated-selector>
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_drawable04_false.xml b/tests/VectorDrawableTest/res/drawable/state_animation_drawable04_false.xml
new file mode 100644
index 0000000..3cf8e48
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_drawable04_false.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+
+<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/on" android:state_checked="true"
+ android:drawable="@drawable/vector_drawable_favorite" />
+ <item android:id="@+id/off" android:state_checked="false"
+ android:drawable="@drawable/vector_drawable_favorite" />
+ <transition android:fromId="@+id/off" android:toId="@+id/on"
+ android:drawable="@drawable/animation_drawable_vector"
+ android:reversible="false">
+ </transition>
+</animated-selector>
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml
index 18d7755..768fe39 100644
--- a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml
@@ -17,7 +17,7 @@
<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/on" android:state_checked="true"
android:drawable="@drawable/vector_drawable12" />
- <item android:id="@+id/off"
+ <item android:id="@+id/off" android:state_checked="false"
android:drawable="@drawable/vector_drawable12" />
<transition android:fromId="@+id/off" android:toId="@+id/on" android:reversible="true">
<animated-vector android:drawable="@drawable/vector_drawable12">
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01_false.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01_false.xml
new file mode 100644
index 0000000..96d378c
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01_false.xml
@@ -0,0 +1,47 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+
+<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/on" android:state_checked="true"
+ android:drawable="@drawable/vector_drawable12" />
+ <item android:id="@+id/off" android:state_checked="false"
+ android:drawable="@drawable/vector_drawable12" />
+ <transition android:fromId="@+id/off" android:toId="@+id/on" android:reversible="false">
+ <animated-vector android:drawable="@drawable/vector_drawable12">
+ <target
+ android:name="pie1"
+ android:animation="@anim/trim_path_animation01" />
+ <target
+ android:name="v"
+ android:animation="@anim/trim_path_animation02" />
+ <target
+ android:name="v"
+ android:animation="@anim/trim_path_animation05" />
+ <target
+ android:name="rotationGroup"
+ android:animation="@anim/trim_path_animation03" />
+ <target
+ android:name="rotationGroup3"
+ android:animation="@anim/trim_path_animation03" />
+ <target
+ android:name="rotationGroupBlue"
+ android:animation="@anim/trim_path_animation03" />
+ <target
+ android:name="rotationGroup"
+ android:animation="@anim/trim_path_animation04" />
+ </animated-vector>
+ </transition>
+</animated-selector>
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02_false.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02_false.xml
new file mode 100644
index 0000000..b722da1
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02_false.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+
+<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/on" android:state_checked="true"
+ android:drawable="@drawable/vector_drawable_grouping_1" />
+ <item android:id="@+id/off" android:state_checked="false"
+ android:drawable="@drawable/vector_drawable_grouping_1" />
+ <transition android:fromId="@+id/off" android:toId="@+id/on"
+ android:drawable="@drawable/animation_vector_drawable_grouping_1"
+ android:reversible="false">
+ </transition>
+</animated-selector>
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml
index 65cf25b..e24dd1f 100644
--- a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml
@@ -17,7 +17,7 @@
<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/on" android:state_checked="true"
android:drawable="@drawable/vector_drawable_favorite" />
- <item android:id="@+id/off"
+ <item android:id="@+id/off" android:state_checked="false"
android:drawable="@drawable/vector_drawable_favorite" />
<transition android:fromId="@+id/off" android:toId="@+id/on"
android:drawable="@drawable/animation_vector_drawable_favorite"
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03_false.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03_false.xml
new file mode 100644
index 0000000..e788bc2
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03_false.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+
+<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/on" android:state_checked="true"
+ android:drawable="@drawable/vector_drawable_favorite" />
+ <item android:id="@+id/off" android:state_checked="false"
+ android:drawable="@drawable/vector_drawable_favorite" />
+ <transition android:fromId="@+id/off" android:toId="@+id/on"
+ android:drawable="@drawable/animation_vector_drawable_favorite"
+ android:reversible="false">
+ </transition>
+</animated-selector>
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java
index 566cc4b..5386555 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java
@@ -27,9 +27,16 @@
private static final String LOGCAT = "AnimatedStateVectorDrawableTest";
protected int[] icon = {
+ // These shows pairs of ASLD , the left side set the reversible to true.
+ // the right side set to false.
R.drawable.state_animation_vector_drawable01,
+ R.drawable.state_animation_vector_drawable01_false,
R.drawable.state_animation_vector_drawable02,
+ R.drawable.state_animation_vector_drawable02_false,
R.drawable.state_animation_vector_drawable03,
+ R.drawable.state_animation_vector_drawable03_false,
+ R.drawable.state_animation_drawable04,
+ R.drawable.state_animation_drawable04_false,
};
@Override
@@ -39,7 +46,7 @@
ScrollView scrollView = new ScrollView(this);
GridLayout container = new GridLayout(this);
scrollView.addView(container);
- container.setColumnCount(5);
+ container.setColumnCount(2);
for (int i = 0; i < icon.length; i++) {
CheckBox button = new CheckBox(this);