diff options
74 files changed, 1272 insertions, 797 deletions
diff --git a/api/current.txt b/api/current.txt index e6bbdbe..2094c7c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4019,10 +4019,12 @@ package android.app { ctor public AssistContent(); method public android.content.ClipData getClipData(); method public android.os.Bundle getExtras(); + method public java.lang.String getStructuredData(); method public android.net.Uri getWebUri(); method public boolean isAppProvidedIntent(); method public void setClipData(android.content.ClipData); method public void setIntent(android.content.Intent); + method public void setStructuredData(java.lang.String); method public void setWebUri(android.net.Uri); } @@ -23674,6 +23676,7 @@ package android.os { field public static final java.lang.String DISALLOW_CROSS_PROFILE_COPY_PASTE = "no_cross_profile_copy_paste"; field public static final java.lang.String DISALLOW_DEBUGGING_FEATURES = "no_debugging_features"; field public static final java.lang.String DISALLOW_FACTORY_RESET = "no_factory_reset"; + field public static final java.lang.String DISALLOW_FUN = "no_fun"; field public static final java.lang.String DISALLOW_INSTALL_APPS = "no_install_apps"; field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources"; field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts"; @@ -26561,7 +26564,6 @@ package android.provider { field public static final java.lang.String DEBUG_APP = "debug_app"; field public static final java.lang.String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled"; field public static final java.lang.String DEVICE_PROVISIONED = "device_provisioned"; - field public static final java.lang.String HIDE_CARRIER_NETWORK_SETTINGS = "hide_carrier_network_settings"; field public static final java.lang.String HTTP_PROXY = "http_proxy"; field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps"; field public static final java.lang.String MODE_RINGER = "mode_ringer"; diff --git a/api/system-current.txt b/api/system-current.txt index fb3c874..9386c50 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4114,10 +4114,12 @@ package android.app { ctor public AssistContent(); method public android.content.ClipData getClipData(); method public android.os.Bundle getExtras(); + method public java.lang.String getStructuredData(); method public android.net.Uri getWebUri(); method public boolean isAppProvidedIntent(); method public void setClipData(android.content.ClipData); method public void setIntent(android.content.Intent); + method public void setStructuredData(java.lang.String); method public void setWebUri(android.net.Uri); } @@ -25608,6 +25610,7 @@ package android.os { field public static final java.lang.String DISALLOW_CROSS_PROFILE_COPY_PASTE = "no_cross_profile_copy_paste"; field public static final java.lang.String DISALLOW_DEBUGGING_FEATURES = "no_debugging_features"; field public static final java.lang.String DISALLOW_FACTORY_RESET = "no_factory_reset"; + field public static final java.lang.String DISALLOW_FUN = "no_fun"; field public static final java.lang.String DISALLOW_INSTALL_APPS = "no_install_apps"; field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources"; field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts"; @@ -28597,7 +28600,6 @@ package android.provider { field public static final java.lang.String DEBUG_APP = "debug_app"; field public static final java.lang.String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled"; field public static final java.lang.String DEVICE_PROVISIONED = "device_provisioned"; - field public static final java.lang.String HIDE_CARRIER_NETWORK_SETTINGS = "hide_carrier_network_settings"; field public static final java.lang.String HTTP_PROXY = "http_proxy"; field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps"; field public static final java.lang.String MODE_RINGER = "mode_ringer"; diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp index c5af992..449a4ab 100644 --- a/cmds/app_process/app_main.cpp +++ b/cmds/app_process/app_main.cpp @@ -90,9 +90,6 @@ public: virtual void onZygoteInit() { - // Re-enable tracing now that we're no longer in Zygote. - atrace_set_tracing_enabled(true); - sp<ProcessState> proc = ProcessState::self(); ALOGV("App process: starting thread pool.\n"); proc->startThreadPool(); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index e21c04a..828dc0a 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -5375,6 +5375,7 @@ public final class ActivityThread { } public static void main(String[] args) { + Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain"); SamplingProfilerIntegration.start(); // CloseGuard defaults to true and can be quite spammy. We @@ -5409,6 +5410,8 @@ public final class ActivityThread { LogPrinter(Log.DEBUG, "ActivityThread")); } + // End of event ActivityThreadMain. + Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); diff --git a/core/java/android/app/AssistContent.java b/core/java/android/app/AssistContent.java index 0df9ce5..ad2ba39 100644 --- a/core/java/android/app/AssistContent.java +++ b/core/java/android/app/AssistContent.java @@ -33,6 +33,7 @@ import android.os.Parcelable; public class AssistContent { private boolean mIsAppProvidedIntent = false; private Intent mIntent; + private String mStructuredData; private ClipData mClipData; private Uri mUri; private final Bundle mExtras; @@ -125,6 +126,22 @@ public class AssistContent { } /** + * Sets optional structured data regarding the content being viewed. The provided data + * must be a string represented with <a href="http://json-ld.org/">JSON-LD</a> using the + * <a href="http://schema.org/">schema.org</a> vocabulary. + */ + public void setStructuredData(String structuredData) { + mStructuredData = structuredData; + } + + /** + * Returns the current {@link #setStructuredData}. + */ + public String getStructuredData() { + return mStructuredData; + } + + /** * Set a web URI associated with the current data being shown to the user. * This URI could be opened in a web browser, or in the app as an * {@link Intent#ACTION_VIEW} Intent, to show the same data that is currently @@ -163,6 +180,9 @@ public class AssistContent { if (in.readInt() != 0) { mUri = Uri.CREATOR.createFromParcel(in); } + if (in.readInt() != 0) { + mStructuredData = in.readString(); + } mIsAppProvidedIntent = in.readInt() == 1; mExtras = in.readBundle(); } @@ -187,6 +207,12 @@ public class AssistContent { } else { dest.writeInt(0); } + if (mStructuredData != null) { + dest.writeInt(1); + dest.writeString(mStructuredData); + } else { + dest.writeInt(0); + } dest.writeInt(mIsAppProvidedIntent ? 1 : 0); dest.writeBundle(mExtras); } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 9f49154..ed20086 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -403,8 +403,9 @@ public class DevicePolicyManager { = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER"; /** - * A String extra holding the URL-safe base64 encoded SHA-1 checksum of the file at download - * location specified in {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}. + * A String extra holding the URL-safe base64 encoded SHA-256 or SHA-1 hash (see notes below) of + * the file at download location specified in + * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}. * * <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM} should be * present. The provided checksum should match the checksum of the file at the download @@ -413,12 +414,17 @@ public class DevicePolicyManager { * * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner * provisioning via an NFC bump. + * + * <p><strong>Note:</strong> for devices running {@link android.os.Build.VERSION_CODES#LOLLIPOP} + * and {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} only SHA-1 hash is supported. + * Starting from {@link android.os.Build.VERSION_CODES#MNC}, this parameter accepts SHA-256 in + * addition to SHA-1. Support for SHA-1 is likely to be removed in future OS releases. */ public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM"; /** - * A String extra holding the URL-safe base64 encoded SHA-1 checksum of any signature of the + * A String extra holding the URL-safe base64 encoded SHA-256 checksum of any signature of the * android package archive at the download location specified in {@link * #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}. * @@ -510,7 +516,7 @@ public class DevicePolicyManager { = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER"; /** - * A String extra holding the URL-safe base64 encoded SHA-1 checksum of the file at download + * A String extra holding the URL-safe base64 encoded SHA-256 checksum of the file at download * location specified in * {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}. * @@ -526,7 +532,7 @@ public class DevicePolicyManager { = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM"; /** - * A String extra holding the URL-safe base64 encoded SHA-1 checksum of any signature of the + * A String extra holding the URL-safe base64 encoded SHA-256 checksum of any signature of the * android package archive at the download location specified in {@link * #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}. * @@ -924,7 +930,7 @@ public class DevicePolicyManager { /** * Constant for {@link #setPasswordQuality}: the policy requires some kind - * of password, but doesn't care what it is. Note that quality constants + * of password or pattern, but doesn't care what it is. Note that quality constants * are ordered so that higher values are more restrictive. */ public static final int PASSWORD_QUALITY_SOMETHING = 0x10000; diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index c92c256..287e0c5 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -4024,7 +4024,7 @@ public class PackageParser { public static final PublicKey parsePublicKey(final String encodedPublicKey) { if (encodedPublicKey == null) { - Slog.i(TAG, "Could not parse null public key"); + Slog.w(TAG, "Could not parse null public key"); return null; } @@ -4033,7 +4033,7 @@ public class PackageParser { final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT); keySpec = new X509EncodedKeySpec(encoded); } catch (IllegalArgumentException e) { - Slog.i(TAG, "Could not parse verifier public key; invalid Base64"); + Slog.w(TAG, "Could not parse verifier public key; invalid Base64"); return null; } @@ -4042,23 +4042,32 @@ public class PackageParser { final KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePublic(keySpec); } catch (NoSuchAlgorithmException e) { - Log.wtf(TAG, "Could not parse public key because RSA isn't included in build"); - return null; + Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build"); } catch (InvalidKeySpecException e) { // Not a RSA public key. } + /* Now try it as a ECDSA key. */ + try { + final KeyFactory keyFactory = KeyFactory.getInstance("EC"); + return keyFactory.generatePublic(keySpec); + } catch (NoSuchAlgorithmException e) { + Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build"); + } catch (InvalidKeySpecException e) { + // Not a ECDSA public key. + } + /* Now try it as a DSA key. */ try { final KeyFactory keyFactory = KeyFactory.getInstance("DSA"); return keyFactory.generatePublic(keySpec); } catch (NoSuchAlgorithmException e) { - Log.wtf(TAG, "Could not parse public key because DSA isn't included in build"); - return null; + Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build"); } catch (InvalidKeySpecException e) { // Not a DSA public key. } + /* Not a supported key type */ return null; } diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 152bc22..27d14b3 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -1093,14 +1093,28 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <p>so <code>[x_s, y_s]</code> is the pixel coordinates of the world * point, <code>z_s = 1</code>, and <code>w_s</code> is a measurement of disparity * (depth) in pixel coordinates.</p> + * <p>Note that the coordinate system for this transform is the + * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} system, + * where <code>(0,0)</code> is the top-left of the + * preCorrectionActiveArraySize rectangle. Once the pose and + * intrinsic calibration transforms have been applied to a + * world point, then the android.lens.radialDistortion + * transform needs to be applied, and the result adjusted to + * be in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate + * system (where <code>(0, 0)</code> is the top-left of the + * activeArraySize rectangle), to determine the final pixel + * coordinate of the world point for processed (non-RAW) + * output buffers.</p> * <p><b>Units</b>: - * Pixels in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate - * system.</p> + * Pixels in the + * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} + * coordinate system.</p> * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> * * @see CameraCharacteristics#LENS_POSE_ROTATION * @see CameraCharacteristics#LENS_POSE_TRANSLATION * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE + * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE */ @PublicKey public static final Key<float[]> LENS_INTRINSIC_CALIBRATION = @@ -2006,19 +2020,19 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}:</p> * <ol> * <li>Choose a pixel (x', y') within the active array region of the raw buffer given in - * android.sensor.info.preCorrectedActiveArraySize, otherwise this pixel is considered + * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, otherwise this pixel is considered * to be outside of the FOV, and will not be shown in the processed output image.</li> * <li>Apply geometric distortion correction to get the post-distortion pixel coordinate, * (x_i, y_i). When applying geometric correction metadata, note that metadata for raw * buffers is defined relative to the top, left of the - * android.sensor.info.preCorrectedActiveArraySize rectangle.</li> + * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} rectangle.</li> * <li>If the resulting corrected pixel coordinate is within the region given in * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, then the position of this pixel in the * processed output image buffer is <code>(x_i - activeArray.left, y_i - activeArray.top)</code>, * when the top, left coordinate of that buffer is treated as (0, 0).</li> * </ol> * <p>Thus, for pixel x',y' = (25, 25) on a sensor where {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize} - * is (100,100), android.sensor.info.preCorrectedActiveArraySize is (10, 10, 100, 100), + * is (100,100), {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} is (10, 10, 100, 100), * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} is (20, 20, 80, 80), and the geometric distortion * correction doesn't change the pixel coordinate, the resulting pixel selected in * pixel coordinates would be x,y = (25, 25) relative to the top,left of the raw buffer @@ -2042,6 +2056,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE + * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE */ @PublicKey public static final Key<android.graphics.Rect> SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE = diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index 479583c..da216aa 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -2655,14 +2655,28 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p>so <code>[x_s, y_s]</code> is the pixel coordinates of the world * point, <code>z_s = 1</code>, and <code>w_s</code> is a measurement of disparity * (depth) in pixel coordinates.</p> + * <p>Note that the coordinate system for this transform is the + * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} system, + * where <code>(0,0)</code> is the top-left of the + * preCorrectionActiveArraySize rectangle. Once the pose and + * intrinsic calibration transforms have been applied to a + * world point, then the android.lens.radialDistortion + * transform needs to be applied, and the result adjusted to + * be in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate + * system (where <code>(0, 0)</code> is the top-left of the + * activeArraySize rectangle), to determine the final pixel + * coordinate of the world point for processed (non-RAW) + * output buffers.</p> * <p><b>Units</b>: - * Pixels in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate - * system.</p> + * Pixels in the + * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} + * coordinate system.</p> * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> * * @see CameraCharacteristics#LENS_POSE_ROTATION * @see CameraCharacteristics#LENS_POSE_TRANSLATION * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE + * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE */ @PublicKey public static final Key<float[]> LENS_INTRINSIC_CALIBRATION = diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 3a3c47d..a2ca41c 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -801,28 +801,6 @@ public class ConnectivityManager { } /** - * Returns details about the Provisioning or currently active default data network. When - * connected, this network is the default route for outgoing connections. - * You should always check {@link NetworkInfo#isConnected()} before initiating - * network traffic. This may return {@code null} when there is no default - * network. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. - * - * @return a {@link NetworkInfo} object for the current default network - * or {@code null} if no default network is currently active - * - * {@hide} - */ - public NetworkInfo getProvisioningOrActiveNetworkInfo() { - try { - return mService.getProvisioningOrActiveNetworkInfo(); - } catch (RemoteException e) { - return null; - } - } - - /** * Returns the IP information for the current default network. * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. @@ -2007,24 +1985,6 @@ public class ConnectivityManager { } /** - * Signal that the captive portal check on the indicated network - * is complete and whether its a captive portal or not. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL}. - * - * @param info the {@link NetworkInfo} object for the networkType - * in question. - * @param isCaptivePortal true/false. - * {@hide} - */ - public void captivePortalCheckCompleted(NetworkInfo info, boolean isCaptivePortal) { - try { - mService.captivePortalCheckCompleted(info, isCaptivePortal); - } catch (RemoteException e) { - } - } - - /** * Check mobile provisioning. * * @param suggestedTimeOutMs, timeout in milliseconds @@ -2056,18 +2016,6 @@ public class ConnectivityManager { } /** - * Get the mobile redirected provisioning url. - * {@hide} - */ - public String getMobileRedirectedProvisioningUrl() { - try { - return mService.getMobileRedirectedProvisioningUrl(); - } catch (RemoteException e) { - } - return null; - } - - /** * Set sign in error notification to visible or in visible * * @param visible diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 89d23a2..29557bb 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -53,8 +53,6 @@ interface IConnectivityManager Network[] getAllNetworks(); NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId); - NetworkInfo getProvisioningOrActiveNetworkInfo(); - boolean isNetworkSupported(int networkType); LinkProperties getActiveLinkProperties(); @@ -122,14 +120,10 @@ interface IConnectivityManager boolean updateLockdownVpn(); - void captivePortalCheckCompleted(in NetworkInfo info, boolean isCaptivePortal); - int checkMobileProvisioning(int suggestedTimeOutMs); String getMobileProvisioningUrl(); - String getMobileRedirectedProvisioningUrl(); - void setProvisioningNotificationVisible(boolean visible, int networkType, in String action); void setAirplaneMode(boolean enable); diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java index 9628bae..fe69320 100644 --- a/core/java/android/net/Network.java +++ b/core/java/android/net/Network.java @@ -378,6 +378,9 @@ public class Network implements Parcelable { // // The HANDLE_MAGIC value MUST be kept in sync with the corresponding // value in the native/android/net.c NDK implementation. + if (netId == 0) { + return 0L; // make this zero condition obvious for debugging + } final long HANDLE_MAGIC = 0xfacade; return (((long) netId) << 32) | HANDLE_MAGIC; } diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java index 393637e..af7a465 100644 --- a/core/java/android/net/NetworkInfo.java +++ b/core/java/android/net/NetworkInfo.java @@ -120,7 +120,6 @@ public class NetworkInfo implements Parcelable { private String mExtraInfo; private boolean mIsFailover; private boolean mIsRoaming; - private boolean mIsConnectedToProvisioningNetwork; /** * Indicates whether network connectivity is possible: @@ -142,7 +141,6 @@ public class NetworkInfo implements Parcelable { mState = State.UNKNOWN; mIsAvailable = false; // until we're told otherwise, assume unavailable mIsRoaming = false; - mIsConnectedToProvisioningNetwork = false; } /** {@hide} */ @@ -160,7 +158,6 @@ public class NetworkInfo implements Parcelable { mIsFailover = source.mIsFailover; mIsRoaming = source.mIsRoaming; mIsAvailable = source.mIsAvailable; - mIsConnectedToProvisioningNetwork = source.mIsConnectedToProvisioningNetwork; } } } @@ -332,22 +329,6 @@ public class NetworkInfo implements Parcelable { } } - /** {@hide} */ - @VisibleForTesting - public boolean isConnectedToProvisioningNetwork() { - synchronized (this) { - return mIsConnectedToProvisioningNetwork; - } - } - - /** {@hide} */ - @VisibleForTesting - public void setIsConnectedToProvisioningNetwork(boolean val) { - synchronized (this) { - mIsConnectedToProvisioningNetwork = val; - } - } - /** * Reports the current coarse-grained state of the network. * @return the coarse-grained state @@ -431,8 +412,6 @@ public class NetworkInfo implements Parcelable { append(", roaming: ").append(mIsRoaming). append(", failover: ").append(mIsFailover). append(", isAvailable: ").append(mIsAvailable). - append(", isConnectedToProvisioningNetwork: "). - append(mIsConnectedToProvisioningNetwork). append("]"); return builder.toString(); } @@ -461,7 +440,6 @@ public class NetworkInfo implements Parcelable { dest.writeInt(mIsFailover ? 1 : 0); dest.writeInt(mIsAvailable ? 1 : 0); dest.writeInt(mIsRoaming ? 1 : 0); - dest.writeInt(mIsConnectedToProvisioningNetwork ? 1 : 0); dest.writeString(mReason); dest.writeString(mExtraInfo); } @@ -484,7 +462,6 @@ public class NetworkInfo implements Parcelable { netInfo.mIsFailover = in.readInt() != 0; netInfo.mIsAvailable = in.readInt() != 0; netInfo.mIsRoaming = in.readInt() != 0; - netInfo.mIsConnectedToProvisioningNetwork = in.readInt() != 0; netInfo.mReason = in.readString(); netInfo.mExtraInfo = in.readString(); return netInfo; diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index ff3de2b..bb08be2 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -53,6 +53,8 @@ public class TrafficStats { public static final long GB_IN_BYTES = MB_IN_BYTES * 1024; /** @hide */ public static final long TB_IN_BYTES = GB_IN_BYTES * 1024; + /** @hide */ + public static final long PB_IN_BYTES = TB_IN_BYTES * 1024; /** * Special UID value used when collecting {@link NetworkStatsHistory} for diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index ef7e747..00350ec 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -362,6 +362,18 @@ public class UserManager { public static final String DISALLOW_SMS = "no_sms"; /** + * Specifies if the user is not allowed to have fun. In some cases, the + * device owner may wish to prevent the user from experiencing amusement or + * joy while using the device. The default value is <code>false</code>. + * + * <p/>Key for user restrictions. + * <p/>Type: Boolean + * @see #setUserRestrictions(Bundle) + * @see #getUserRestrictions() + */ + public static final String DISALLOW_FUN = "no_fun"; + + /** * Specifies that windows besides app windows should not be * created. This will block the creation of the following types of windows. * <li>{@link LayoutParams#TYPE_TOAST}</li> diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index dfd72c2..3e9c9de 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -7232,13 +7232,6 @@ public final class Settings { "preferred_network_mode"; /** - * Setting to 1 will hide carrier network settings. - * Default is 0. - */ - public static final String HIDE_CARRIER_NETWORK_SETTINGS = - "hide_carrier_network_settings"; - - /** * Name of an application package to be debugged. */ public static final String DEBUG_APP = "debug_app"; diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java index b467f5a..13a959e 100644 --- a/core/java/android/text/format/Formatter.java +++ b/core/java/android/text/format/Formatter.java @@ -17,7 +17,9 @@ package android.text.format; import android.content.Context; +import android.content.res.Resources; import android.net.NetworkUtils; +import android.net.TrafficStats; /** * Utility class to aid in formatting common values that are not covered @@ -25,63 +27,88 @@ import android.net.NetworkUtils; */ public final class Formatter { + /** {@hide} */ + public static final int FLAG_SHORTER = 1 << 0; + /** {@hide} */ + public static final int FLAG_CALCULATE_ROUNDED = 1 << 1; + + /** {@hide} */ + public static class BytesResult { + public final String value; + public final String units; + public final long roundedBytes; + + public BytesResult(String value, String units, long roundedBytes) { + this.value = value; + this.units = units; + this.roundedBytes = roundedBytes; + } + } + /** * Formats a content size to be in the form of bytes, kilobytes, megabytes, etc * * @param context Context to use to load the localized units - * @param number size value to be formatted + * @param sizeBytes size value to be formatted, in bytes * @return formatted string with the number */ - public static String formatFileSize(Context context, long number) { - return formatFileSize(context, number, false); + public static String formatFileSize(Context context, long sizeBytes) { + final BytesResult res = formatBytes(context.getResources(), sizeBytes, 0); + return context.getString(com.android.internal.R.string.fileSizeSuffix, + res.value, res.units); } /** * Like {@link #formatFileSize}, but trying to generate shorter numbers * (showing fewer digits of precision). */ - public static String formatShortFileSize(Context context, long number) { - return formatFileSize(context, number, true); + public static String formatShortFileSize(Context context, long sizeBytes) { + final BytesResult res = formatBytes(context.getResources(), sizeBytes, FLAG_SHORTER); + return context.getString(com.android.internal.R.string.fileSizeSuffix, + res.value, res.units); } - private static String formatFileSize(Context context, long number, boolean shorter) { - if (context == null) { - return ""; - } - - float result = number; + /** {@hide} */ + public static BytesResult formatBytes(Resources res, long sizeBytes, int flags) { + float result = sizeBytes; int suffix = com.android.internal.R.string.byteShort; + long mult = 1; if (result > 900) { suffix = com.android.internal.R.string.kilobyteShort; + mult = TrafficStats.KB_IN_BYTES; result = result / 1024; } if (result > 900) { suffix = com.android.internal.R.string.megabyteShort; + mult = TrafficStats.MB_IN_BYTES; result = result / 1024; } if (result > 900) { suffix = com.android.internal.R.string.gigabyteShort; + mult = TrafficStats.GB_IN_BYTES; result = result / 1024; } if (result > 900) { suffix = com.android.internal.R.string.terabyteShort; + mult = TrafficStats.TB_IN_BYTES; result = result / 1024; } if (result > 900) { suffix = com.android.internal.R.string.petabyteShort; + mult = TrafficStats.PB_IN_BYTES; result = result / 1024; } String value; if (result < 1) { value = String.format("%.2f", result); } else if (result < 10) { - if (shorter) { + if ((flags & FLAG_SHORTER) != 0) { value = String.format("%.1f", result); } else { value = String.format("%.2f", result); } } else if (result < 100) { - if (shorter) { + if ((flags & FLAG_SHORTER) != 0) { value = String.format("%.0f", result); } else { value = String.format("%.2f", result); @@ -89,9 +116,14 @@ public final class Formatter { } else { value = String.format("%.0f", result); } - return context.getResources(). - getString(com.android.internal.R.string.fileSizeSuffix, - value, context.getString(suffix)); + final String units = res.getString(suffix); + final long roundedBytes; + if ((flags & FLAG_CALCULATE_ROUNDED) != 0) { + roundedBytes = (long) (Double.parseDouble(value) * mult); + } else { + roundedBytes = 0; + } + return new BytesResult(value, units, roundedBytes); } /** diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java index bac668a..8b74a1e 100644 --- a/core/java/android/transition/Visibility.java +++ b/core/java/android/transition/Visibility.java @@ -557,7 +557,7 @@ public abstract class Visibility extends Transition { if (mIsForcedVisibility) { mView.setTransitionAlpha(0); } else { - mView.setTransitionVisibility(mFinalVisibility); + mView.setVisibility(mFinalVisibility); } } } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 89743e5..73cfd8c 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -2939,11 +2939,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } - /** @hide */ @Override - public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) { - super.onInitializeAccessibilityEventInternal(event); - event.setClassName(ViewGroup.class.getName()); + public CharSequence getAccessibilityClassName() { + return ViewGroup.class.getName(); } @Override diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index cf6a018..f89ee91 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -244,15 +244,6 @@ public class Editor { final CursorAnchorInfoNotifier mCursorAnchorInfoNotifier = new CursorAnchorInfoNotifier(); - private final Runnable mHideFloatingToolbar = new Runnable() { - @Override - public void run() { - if (mTextActionMode != null) { - mTextActionMode.hide(ActionMode.DEFAULT_HIDE_DURATION); - } - } - }; - private final Runnable mShowFloatingToolbar = new Runnable() { @Override public void run() { @@ -389,7 +380,6 @@ public class Editor { mTextView.removeCallbacks(mInsertionActionModeRunnable); } - mTextView.removeCallbacks(mHideFloatingToolbar); mTextView.removeCallbacks(mShowFloatingToolbar); destroyDisplayListsData(); @@ -1248,14 +1238,12 @@ public class Editor { private void hideFloatingToolbar() { if (mTextActionMode != null) { mTextView.removeCallbacks(mShowFloatingToolbar); - // Delay the "hide" a little bit just in case a "show" will happen almost immediately. - mTextView.postDelayed(mHideFloatingToolbar, 100); + mTextActionMode.hide(ActionMode.DEFAULT_HIDE_DURATION); } } private void showFloatingToolbar() { if (mTextActionMode != null) { - mTextView.removeCallbacks(mHideFloatingToolbar); // Delay "show" so it doesn't interfere with click confirmations // or double-clicks that could "dismiss" the floating toolbar. int delay = ViewConfiguration.getDoubleTapTimeout(); diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java index 8ace0f3..2ea2667 100644 --- a/core/java/android/widget/Toolbar.java +++ b/core/java/android/widget/Toolbar.java @@ -26,7 +26,6 @@ import android.annotation.StyleRes; import android.app.ActionBar; import android.content.Context; import android.content.res.TypedArray; -import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; @@ -148,6 +147,9 @@ public class Toolbar extends ViewGroup { // Clear me after use. private final ArrayList<View> mTempViews = new ArrayList<View>(); + // Used to hold views that will be removed while we have an expanded action view. + private final ArrayList<View> mHiddenViews = new ArrayList<>(); + private final int[] mTempMargins = new int[2]; private OnMenuItemClickListener mOnMenuItemClickListener; @@ -435,12 +437,12 @@ public class Toolbar extends ViewGroup { public void setLogo(Drawable drawable) { if (drawable != null) { ensureLogoView(); - if (mLogoView.getParent() == null) { - addSystemView(mLogoView); - updateChildVisibilityForExpandedActionView(mLogoView); + if (!isChildOrHidden(mLogoView)) { + addSystemView(mLogoView, true); } - } else if (mLogoView != null && mLogoView.getParent() != null) { + } else if (mLogoView != null && isChildOrHidden(mLogoView)) { removeView(mLogoView); + mHiddenViews.remove(mLogoView); } if (mLogoView != null) { mLogoView.setImageDrawable(drawable); @@ -577,12 +579,12 @@ public class Toolbar extends ViewGroup { mTitleTextView.setTextColor(mTitleTextColor); } } - if (mTitleTextView.getParent() == null) { - addSystemView(mTitleTextView); - updateChildVisibilityForExpandedActionView(mTitleTextView); + if (!isChildOrHidden(mTitleTextView)) { + addSystemView(mTitleTextView, true); } - } else if (mTitleTextView != null && mTitleTextView.getParent() != null) { + } else if (mTitleTextView != null && isChildOrHidden(mTitleTextView)) { removeView(mTitleTextView); + mHiddenViews.remove(mTitleTextView); } if (mTitleTextView != null) { mTitleTextView.setText(title); @@ -631,12 +633,12 @@ public class Toolbar extends ViewGroup { mSubtitleTextView.setTextColor(mSubtitleTextColor); } } - if (mSubtitleTextView.getParent() == null) { - addSystemView(mSubtitleTextView); - updateChildVisibilityForExpandedActionView(mSubtitleTextView); + if (!isChildOrHidden(mSubtitleTextView)) { + addSystemView(mSubtitleTextView, true); } - } else if (mSubtitleTextView != null && mSubtitleTextView.getParent() != null) { + } else if (mSubtitleTextView != null && isChildOrHidden(mSubtitleTextView)) { removeView(mSubtitleTextView); + mHiddenViews.remove(mSubtitleTextView); } if (mSubtitleTextView != null) { mSubtitleTextView.setText(subtitle); @@ -772,12 +774,12 @@ public class Toolbar extends ViewGroup { public void setNavigationIcon(@Nullable Drawable icon) { if (icon != null) { ensureNavButtonView(); - if (mNavButtonView.getParent() == null) { - addSystemView(mNavButtonView); - updateChildVisibilityForExpandedActionView(mNavButtonView); + if (!isChildOrHidden(mNavButtonView)) { + addSystemView(mNavButtonView, true); } - } else if (mNavButtonView != null && mNavButtonView.getParent() != null) { + } else if (mNavButtonView != null && isChildOrHidden(mNavButtonView)) { removeView(mNavButtonView); + mHiddenViews.remove(mNavButtonView); } if (mNavButtonView != null) { mNavButtonView.setImageDrawable(icon); @@ -866,7 +868,7 @@ public class Toolbar extends ViewGroup { final LayoutParams lp = generateDefaultLayoutParams(); lp.gravity = Gravity.END | (mButtonGravity & Gravity.VERTICAL_GRAVITY_MASK); mMenuView.setLayoutParams(lp); - addSystemView(mMenuView); + addSystemView(mMenuView, false); } } @@ -1041,7 +1043,7 @@ public class Toolbar extends ViewGroup { } } - private void addSystemView(View v) { + private void addSystemView(View v, boolean allowHide) { final ViewGroup.LayoutParams vlp = v.getLayoutParams(); final LayoutParams lp; if (vlp == null) { @@ -1052,7 +1054,13 @@ public class Toolbar extends ViewGroup { lp = (LayoutParams) vlp; } lp.mViewType = LayoutParams.SYSTEM; - addView(v, lp); + + if (allowHide && mExpandedActionView != null) { + v.setLayoutParams(lp); + mHiddenViews.add(v); + } else { + addView(v, lp); + } } @Override @@ -1741,22 +1749,30 @@ public class Toolbar extends ViewGroup { return mWrapper; } - private void setChildVisibilityForExpandedActionView(boolean expand) { + void removeChildrenForExpandedActionView() { final int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { + // Go backwards since we're removing from the list + for (int i = childCount - 1; i >= 0; i--) { final View child = getChildAt(i); final LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (lp.mViewType != LayoutParams.EXPANDED && child != mMenuView) { - child.setVisibility(expand ? GONE : VISIBLE); + removeViewAt(i); + mHiddenViews.add(child); } } } - private void updateChildVisibilityForExpandedActionView(View child) { - final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - if (lp.mViewType != LayoutParams.EXPANDED && child != mMenuView) { - child.setVisibility(mExpandedActionView != null ? GONE : VISIBLE); + void addChildrenForExpandedActionView() { + final int count = mHiddenViews.size(); + // Re-add in reverse order since we removed in reverse order + for (int i = count - 1; i >= 0; i--) { + addView(mHiddenViews.get(i)); } + mHiddenViews.clear(); + } + + private boolean isChildOrHidden(View child) { + return child.getParent() == this || mHiddenViews.contains(child); } /** @@ -1971,7 +1987,7 @@ public class Toolbar extends ViewGroup { addView(mExpandedActionView); } - setChildVisibilityForExpandedActionView(true); + removeChildrenForExpandedActionView(); requestLayout(); item.setActionViewExpanded(true); @@ -1994,7 +2010,7 @@ public class Toolbar extends ViewGroup { removeView(mCollapseButtonView); mExpandedActionView = null; - setChildVisibilityForExpandedActionView(false); + addChildrenForExpandedActionView(); mCurrentExpandedItem = null; requestLayout(); item.setActionViewExpanded(false); diff --git a/core/java/com/android/internal/app/ToolbarActionBar.java b/core/java/com/android/internal/app/ToolbarActionBar.java index 34b9dcb..2b162af 100644 --- a/core/java/com/android/internal/app/ToolbarActionBar.java +++ b/core/java/com/android/internal/app/ToolbarActionBar.java @@ -83,7 +83,9 @@ public class ToolbarActionBar extends ActionBar { @Override public void setCustomView(View view, LayoutParams layoutParams) { - view.setLayoutParams(layoutParams); + if (view != null) { + view.setLayoutParams(layoutParams); + } mDecorToolbar.setCustomView(view); } diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java index 2539a35..f81658e 100644 --- a/core/java/com/android/internal/os/RuntimeInit.java +++ b/core/java/com/android/internal/os/RuntimeInit.java @@ -24,6 +24,7 @@ import android.os.Debug; import android.os.IBinder; import android.os.Process; import android.os.SystemProperties; +import android.os.Trace; import android.util.Log; import android.util.Slog; import com.android.internal.logging.AndroidConfig; @@ -269,11 +270,11 @@ public class RuntimeInit { throws ZygoteInit.MethodAndArgsCaller { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote"); + Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit"); redirectLogStreams(); commonInit(); nativeZygoteInit(); - applicationInit(targetSdkVersion, argv, classLoader); } @@ -318,6 +319,9 @@ public class RuntimeInit { return; } + // The end of of the RuntimeInit event (see #zygoteInit). + Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); + // Remaining arguments are passed to the start class's static main invokeStaticMain(args.startClass, args.startArgs, classLoader); } diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index 1e7ee5a..4f6d781 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -17,6 +17,7 @@ package com.android.internal.os; +import android.os.Trace; import dalvik.system.ZygoteHooks; import android.system.ErrnoException; import android.system.Os; @@ -88,6 +89,13 @@ public final class Zygote { int pid = nativeForkAndSpecialize( uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, instructionSet, appDataDir); + // Enable tracing as soon as possible for the child process. + if (pid == 0) { + Trace.setTracingEnabled(true); + + // Note that this event ends at the end of handleChildProc, + Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork"); + } VM_HOOKS.postForkCommon(); return pid; } @@ -124,6 +132,10 @@ public final class Zygote { VM_HOOKS.preFork(); int pid = nativeForkSystemServer( uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities); + // Enable tracing as soon as we enter the system_server. + if (pid == 0) { + Trace.setTracingEnabled(true); + } VM_HOOKS.postForkCommon(); return pid; } diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index 969d236..1a0345b 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -27,6 +27,7 @@ import android.net.LocalSocket; import android.os.Process; import android.os.SELinux; import android.os.SystemProperties; +import android.os.Trace; import android.system.ErrnoException; import android.system.Os; import android.util.Log; @@ -711,7 +712,6 @@ class ZygoteConnection { private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller { - /** * By the time we get here, the native code has closed the two actual Zygote * socket connections, and substituted /dev/null in their place. The LocalSocket @@ -740,6 +740,8 @@ class ZygoteConnection { Process.setArgV0(parsedArgs.niceName); } + // End of the postFork event. + Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); if (parsedArgs.invokeWith != null) { WrapperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java index 661dce1..99c1277 100644 --- a/core/java/com/android/internal/view/FloatingActionMode.java +++ b/core/java/com/android/internal/view/FloatingActionMode.java @@ -48,12 +48,14 @@ public class FloatingActionMode extends ActionMode { private final Runnable mMovingOff = new Runnable() { public void run() { mFloatingToolbarVisibilityHelper.setMoving(false); + mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); } }; private final Runnable mHideOff = new Runnable() { public void run() { mFloatingToolbarVisibilityHelper.setHideRequested(false); + mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); } }; @@ -87,6 +89,7 @@ public class FloatingActionMode extends ActionMode { } }); mFloatingToolbarVisibilityHelper = new FloatingToolbarVisibilityHelper(mFloatingToolbar); + mFloatingToolbarVisibilityHelper.activate(); } @Override @@ -108,8 +111,7 @@ public class FloatingActionMode extends ActionMode { public void invalidate() { checkToolbarInitialized(); mCallback.onPrepareActionMode(this, mMenu); - mFloatingToolbar.updateLayout(); - invalidateContentRect(); + invalidateContentRect(); // Will re-layout and show the toolbar if necessary. } @Override @@ -131,44 +133,43 @@ public class FloatingActionMode extends ActionMode { mContentRectOnWindow.set(mContentRect); mContentRectOnWindow.offset(mViewPosition[0], mViewPosition[1]); - // Make sure that content rect is not out of the view's visible bounds. - mContentRectOnWindow.set( - Math.max(mContentRectOnWindow.left, mViewRect.left), - Math.max(mContentRectOnWindow.top, mViewRect.top), - Math.min(mContentRectOnWindow.right, mViewRect.right), - Math.min(mContentRectOnWindow.bottom, mViewRect.bottom)); - - if (!mContentRectOnWindow.equals(mPreviousContentRectOnWindow)) { - if (!mPreviousContentRectOnWindow.isEmpty()) { - notifyContentRectMoving(); - } - mFloatingToolbar.setContentRect(mContentRectOnWindow); - mFloatingToolbar.updateLayout(); - } - mPreviousContentRectOnWindow.set(mContentRectOnWindow); if (isContentRectWithinBounds()) { mFloatingToolbarVisibilityHelper.setOutOfBounds(false); + // Make sure that content rect is not out of the view's visible bounds. + mContentRectOnWindow.set( + Math.max(mContentRectOnWindow.left, mViewRect.left), + Math.max(mContentRectOnWindow.top, mViewRect.top), + Math.min(mContentRectOnWindow.right, mViewRect.right), + Math.min(mContentRectOnWindow.bottom, mViewRect.bottom)); + + if (!mContentRectOnWindow.equals(mPreviousContentRectOnWindow)) { + // Content rect is moving. + mOriginatingView.removeCallbacks(mMovingOff); + mFloatingToolbarVisibilityHelper.setMoving(true); + mOriginatingView.postDelayed(mMovingOff, MOVING_HIDE_DELAY); + + mFloatingToolbar.setContentRect(mContentRectOnWindow); + mFloatingToolbar.updateLayout(); + } } else { mFloatingToolbarVisibilityHelper.setOutOfBounds(true); + mContentRectOnWindow.setEmpty(); } - } + mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); - private boolean isContentRectWithinBounds() { - mScreenRect.set( - 0, - 0, - mContext.getResources().getDisplayMetrics().widthPixels, - mContext.getResources().getDisplayMetrics().heightPixels); - - return Rect.intersects(mContentRectOnWindow, mScreenRect) - && Rect.intersects(mContentRectOnWindow, mViewRect); + mPreviousContentRectOnWindow.set(mContentRectOnWindow); } - private void notifyContentRectMoving() { - mOriginatingView.removeCallbacks(mMovingOff); - mFloatingToolbarVisibilityHelper.setMoving(true); - mOriginatingView.postDelayed(mMovingOff, MOVING_HIDE_DELAY); + private boolean isContentRectWithinBounds() { + mScreenRect.set( + 0, + 0, + mContext.getResources().getDisplayMetrics().widthPixels, + mContext.getResources().getDisplayMetrics().heightPixels); + + return Rect.intersects(mContentRectOnWindow, mScreenRect) + && Rect.intersects(mContentRectOnWindow, mViewRect); } @Override @@ -184,6 +185,7 @@ public class FloatingActionMode extends ActionMode { mHideOff.run(); } else { mFloatingToolbarVisibilityHelper.setHideRequested(true); + mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); mOriginatingView.postDelayed(mHideOff, duration); } } @@ -221,7 +223,7 @@ public class FloatingActionMode extends ActionMode { } /** - * @throws IlllegalStateException + * @throws IllegalStateException */ private void checkToolbarInitialized() { Preconditions.checkState(mFloatingToolbar != null); @@ -229,13 +231,14 @@ public class FloatingActionMode extends ActionMode { } private void reset() { + mFloatingToolbarVisibilityHelper.deactivate(); mOriginatingView.removeCallbacks(mMovingOff); mOriginatingView.removeCallbacks(mHideOff); } /** - * A helper that shows/hides the floating toolbar depending on certain states. + * A helper for showing/hiding the floating toolbar depending on certain states. */ private static final class FloatingToolbarVisibilityHelper { @@ -245,29 +248,45 @@ public class FloatingActionMode extends ActionMode { private boolean mMoving; private boolean mOutOfBounds; + private boolean mActive; + public FloatingToolbarVisibilityHelper(FloatingToolbar toolbar) { mToolbar = Preconditions.checkNotNull(toolbar); } + public void activate() { + mHideRequested = false; + mMoving = false; + mOutOfBounds = false; + + mActive = true; + } + + public void deactivate() { + mActive = false; + mToolbar.dismiss(); + } + public void setHideRequested(boolean hide) { mHideRequested = hide; - updateToolbarVisibility(); } public void setMoving(boolean moving) { mMoving = moving; - updateToolbarVisibility(); } public void setOutOfBounds(boolean outOfBounds) { mOutOfBounds = outOfBounds; - updateToolbarVisibility(); } - private void updateToolbarVisibility() { + public void updateToolbarVisibility() { + if (!mActive) { + return; + } + if (mHideRequested || mMoving || mOutOfBounds) { mToolbar.hide(); - } else if (mToolbar.isHidden()) { + } else { mToolbar.show(); } } diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java index 2d0989f..53ebc23 100644 --- a/core/java/com/android/internal/widget/FloatingToolbar.java +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -37,7 +37,6 @@ import android.view.View.MeasureSpec; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.Window; -import android.view.WindowInsets; import android.view.WindowManager; import android.view.animation.Animation; import android.view.animation.AnimationSet; @@ -436,8 +435,6 @@ public final class FloatingToolbar { // The "show" animation will make this visible. mContentContainer.setAlpha(0); } - refreshViewPort(); - updateOverflowHeight(contentRect.top - (mMarginVertical * 2) - mViewPort.top); refreshCoordinatesAndOverflowDirection(contentRect); preparePopupContent(); mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, mCoords.x, mCoords.y); @@ -501,7 +498,6 @@ public final class FloatingToolbar { } cancelOverflowAnimations(); - refreshViewPort(); refreshCoordinatesAndOverflowDirection(contentRect); preparePopupContent(); mPopupWindow.update(mCoords.x, mCoords.y, getWidth(), getHeight()); @@ -529,28 +525,65 @@ public final class FloatingToolbar { } private void refreshCoordinatesAndOverflowDirection(Rect contentRect) { - // NOTE: Ensure that mViewPort has been refreshed before this. + refreshViewPort(); - int x = contentRect.centerX() - getWidth() / 2; - int y; - if (contentRect.top - getHeight() > mViewPort.top) { - y = contentRect.top - getHeight(); - mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_UP; - } else if (contentRect.top - getToolbarHeightWithVerticalMargin() > mViewPort.top) { - y = contentRect.top - getToolbarHeightWithVerticalMargin(); - mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_DOWN; - } else { - y = contentRect.bottom; - mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_DOWN; - } + int availableHeightAboveContent = + contentRect.top - mViewPort.top - 2 * mMarginVertical; + int availableHeightBelowContent = + mViewPort.bottom - contentRect.bottom - 2 * mMarginVertical; + int availableHeightThroughContent = + mViewPort.bottom - contentRect.top + getToolbarHeightWithVerticalMargin(); + int x = contentRect.centerX() - getWidth() / 2; // Update x so that the toolbar isn't rendered behind the nav bar in landscape. x = Math.max(0, Math.min(x, mViewPort.right - getWidth())); - mCoords.set(x, y); - if (mOverflowPanel != null) { + int y; + if (mOverflowPanel == null) { // There is no overflow. + if (availableHeightAboveContent > getToolbarHeightWithVerticalMargin()) { + // There is enough space at the top of the content. + y = contentRect.top - getToolbarHeightWithVerticalMargin(); + } else if (availableHeightBelowContent > getToolbarHeightWithVerticalMargin()) { + // There is enough space at the bottom of the content. + y = contentRect.bottom; + } else { + // Not enough space. Prefer to position as high as possible. + y = Math.max( + mViewPort.top, + contentRect.top - getToolbarHeightWithVerticalMargin()); + } + } else { // There is an overflow. + if (availableHeightAboveContent > mOverflowPanel.getMinimumHeight()) { + // There is enough space at the top of the content rect for the overflow. + // Position above and open upwards. + updateOverflowHeight(availableHeightAboveContent); + y = contentRect.top - getHeight(); + mOverflowDirection = OVERFLOW_DIRECTION_UP; + } else if (availableHeightAboveContent > getToolbarHeightWithVerticalMargin() + && availableHeightThroughContent > mOverflowPanel.getMinimumHeight()) { + // There is enough space at the top of the content rect for the main panel + // but not the overflow. + // Position above but open downwards. + updateOverflowHeight(availableHeightThroughContent); + y = contentRect.top - getToolbarHeightWithVerticalMargin(); + mOverflowDirection = OVERFLOW_DIRECTION_DOWN; + } else if (availableHeightBelowContent > mOverflowPanel.getMinimumHeight()) { + // There is enough space at the bottom of the content rect for the overflow. + // Position below and open downwards. + updateOverflowHeight(availableHeightBelowContent); + y = contentRect.bottom; + mOverflowDirection = OVERFLOW_DIRECTION_DOWN; + } else { + // Not enough space. + // Position at the bottom of the view port and open upwards. + updateOverflowHeight(mViewPort.height()); + y = mViewPort.bottom - getHeight(); + mOverflowDirection = OVERFLOW_DIRECTION_UP; + } mOverflowPanel.setOverflowDirection(mOverflowDirection); } + + mCoords.set(x, y); } private int getToolbarHeightWithVerticalMargin() { @@ -837,13 +870,7 @@ public final class FloatingToolbar { private void refreshViewPort() { - mParent.getGlobalVisibleRect(mViewPort); - WindowInsets windowInsets = mParent.getRootWindowInsets(); - mViewPort.set( - mViewPort.left + windowInsets.getStableInsetLeft(), - mViewPort.top + windowInsets.getStableInsetTop(), - mViewPort.right - windowInsets.getStableInsetRight(), - mViewPort.bottom - windowInsets.getStableInsetBottom()); + mParent.getWindowVisibleDisplayFrame(mViewPort); } private int getToolbarWidth(int suggestedWidth) { @@ -1139,6 +1166,12 @@ public final class FloatingToolbar { setListViewHeight(); } + public int getMinimumHeight() { + return mContentView.getContext().getResources(). + getDimensionPixelSize(R.dimen.floating_toolbar_minimum_overflow_height) + + getEstimatedToolbarHeight(mContentView.getContext()); + } + /** * Returns the content view of the overflow. */ @@ -1173,13 +1206,18 @@ public final class FloatingToolbar { getDimensionPixelSize(R.dimen.floating_toolbar_maximum_overflow_height); int minHeight = mContentView.getContext().getResources(). getDimensionPixelSize(R.dimen.floating_toolbar_minimum_overflow_height); - int availableHeight = mSuggestedHeight - (mSuggestedHeight % itemHeight) + int suggestedListViewHeight = mSuggestedHeight - (mSuggestedHeight % itemHeight) - itemHeight; // reserve space for the back button. ViewGroup.LayoutParams params = mListView.getLayoutParams(); - if (availableHeight >= minHeight) { - params.height = Math.min(Math.min(availableHeight, maxHeight), height); - } else { + if (suggestedListViewHeight <= 0) { + // Invalid height. Use the maximum height available. params.height = Math.min(maxHeight, height); + } else if (suggestedListViewHeight < minHeight) { + // Height is smaller than minimum allowed. Use minimum height. + params.height = minHeight; + } else { + // Use the suggested height. Cap it at the maximum available height. + params.height = Math.min(Math.min(suggestedListViewHeight, maxHeight), height); } mListView.setLayoutParams(params); } @@ -1360,6 +1398,7 @@ public final class FloatingToolbar { PopupWindow popupWindow = new PopupWindow(popupContentHolder); popupWindow.setWindowLayoutType( WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL); + popupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); popupWindow.setAnimationStyle(0); popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); content.setLayoutParams(new ViewGroup.LayoutParams( diff --git a/core/java/com/android/server/backup/AccountSyncSettingsBackupHelper.java b/core/java/com/android/server/backup/AccountSyncSettingsBackupHelper.java index 3f4b980..c0215a8 100644 --- a/core/java/com/android/server/backup/AccountSyncSettingsBackupHelper.java +++ b/core/java/com/android/server/backup/AccountSyncSettingsBackupHelper.java @@ -28,8 +28,6 @@ import android.app.backup.BackupHelper; import android.content.ContentResolver; import android.content.Context; import android.content.SyncAdapterType; -import android.content.SyncStatusObserver; -import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.util.Log; @@ -47,8 +45,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; /** * Helper for backing up account sync settings (whether or not a service should be synced). The @@ -270,6 +266,10 @@ public class AccountSyncSettingsBackupHelper implements BackupHelper { // yet won't be restored. if (currentAccounts.contains(account)) { restoreExistingAccountSyncSettingsFromJSON(accountJSON); + } else { + // TODO: + // Stash the data to a file that the SyncManager can read from to restore + // settings at a later date. } } } finally { @@ -300,6 +300,31 @@ public class AccountSyncSettingsBackupHelper implements BackupHelper { /** * Restore account sync settings using the given JSON. This function won't work if the account * doesn't exist yet. + * This function will only be called during Setup Wizard, where we are guaranteed that there + * are no active syncs. + * There are 2 pieces of data to restore - + * isSyncable (corresponds to {@link ContentResolver#getIsSyncable(Account, String)} + * syncEnabled (corresponds to {@link ContentResolver#getSyncAutomatically(Account, String)} + * <strong>The restore favours adapters that were enabled on the old device, and doesn't care + * about adapters that were disabled.</strong> + * + * syncEnabled=true in restore data. + * syncEnabled will be true on this device. isSyncable will be left as the default in order to + * give the enabled adapter the chance to run an initialization sync. + * + * syncEnabled=false in restore data. + * syncEnabled will be false on this device. isSyncable will be set to 2, unless it was 0 on the + * old device in which case it will be set to 0 on this device. This is because isSyncable=0 is + * a rare state and was probably set to 0 for good reason (historically isSyncable is a way by + * which adapters control their own sync state independently of sync settings which is + * toggleable by the user). + * isSyncable=2 is a new isSyncable state we introduced specifically to allow adapters that are + * disabled after a restore to run initialization logic when the adapter is later enabled. + * See com.android.server.content.SyncStorageEngine#setSyncAutomatically + * + * The end result is that an adapter that the user had on will be turned on and get an + * initialization sync, while an adapter that the user had off will be off until the user + * enables it on this device at which point it will get an initialization sync. */ private void restoreExistingAccountSyncSettingsFromJSON(JSONObject accountJSON) throws JSONException { @@ -307,72 +332,27 @@ public class AccountSyncSettingsBackupHelper implements BackupHelper { JSONArray authorities = accountJSON.getJSONArray(KEY_ACCOUNT_AUTHORITIES); String accountName = accountJSON.getString(KEY_ACCOUNT_NAME); String accountType = accountJSON.getString(KEY_ACCOUNT_TYPE); + final Account account = new Account(accountName, accountType); for (int i = 0; i < authorities.length(); i++) { JSONObject authority = (JSONObject) authorities.get(i); final String authorityName = authority.getString(KEY_AUTHORITY_NAME); - boolean syncEnabled = authority.getBoolean(KEY_AUTHORITY_SYNC_ENABLED); - - // Cancel any active syncs. - if (ContentResolver.isSyncActive(account, authorityName)) { - ContentResolver.cancelSync(account, authorityName); - } - - boolean overwriteSync = true; - Bundle initializationExtras = createSyncInitializationBundle(); - int currentSyncState = ContentResolver.getIsSyncable(account, authorityName); - if (currentSyncState < 0) { - // Requesting a sync is an asynchronous operation, so we setup a countdown latch to - // wait for it to finish. Initialization syncs are generally very brief and - // shouldn't take too much time to finish. - final CountDownLatch latch = new CountDownLatch(1); - Object syncStatusObserverHandle = ContentResolver.addStatusChangeListener( - ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE, new SyncStatusObserver() { - @Override - public void onStatusChanged(int which) { - if (!ContentResolver.isSyncActive(account, authorityName)) { - latch.countDown(); - } - } - }); - - // If we set sync settings for a sync that hasn't been initialized yet, we run the - // risk of having our changes overwritten later on when the sync gets initialized. - // To prevent this from happening we will manually initiate the sync adapter. We - // also explicitly pass in a Bundle with SYNC_EXTRAS_INITIALIZE to prevent a data - // sync from running after the initialization sync. Two syncs will be scheduled, but - // the second one (data sync) will override the first one (initialization sync) and - // still behave as an initialization sync because of the Bundle. - ContentResolver.requestSync(account, authorityName, initializationExtras); - - boolean done = false; - try { - done = latch.await(SYNC_REQUEST_LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Log.e(TAG, "CountDownLatch interrupted\n" + e); - done = false; - } - if (!done) { - overwriteSync = false; - Log.i(TAG, "CountDownLatch timed out, skipping '" + authorityName - + "' authority."); - } - ContentResolver.removeStatusChangeListener(syncStatusObserverHandle); - } - - if (overwriteSync) { - ContentResolver.setSyncAutomatically(account, authorityName, syncEnabled); - Log.i(TAG, "Set sync automatically for '" + authorityName + "': " + syncEnabled); + boolean wasSyncEnabled = authority.getBoolean(KEY_AUTHORITY_SYNC_ENABLED); + int wasSyncable = authority.getInt(KEY_AUTHORITY_SYNC_STATE); + + ContentResolver.setSyncAutomaticallyAsUser( + account, authorityName, wasSyncEnabled, 0 /* user Id */); + + if (!wasSyncEnabled) { + ContentResolver.setIsSyncable( + account, + authorityName, + wasSyncable == 0 ? + 0 /* not syncable */ : 2 /* syncable but needs initialization */); } } } - private Bundle createSyncInitializationBundle() { - Bundle extras = new Bundle(); - extras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true); - return extras; - } - @Override public void writeNewStateDescription(ParcelFileDescriptor newState) { diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp index 2229071..304de8c 100644 --- a/core/jni/android_hardware_camera2_DngCreator.cpp +++ b/core/jni/android_hardware_camera2_DngCreator.cpp @@ -371,8 +371,8 @@ ssize_t JniInputByteBuffer::read(uint8_t* buf, size_t offset, size_t count) { realCount = count; } - jobject chainingBuf = mEnv->CallObjectMethod(mInBuf, gInputByteBufferClassInfo.mGetMethod, mByteArray, 0, - realCount); + jobject chainingBuf = mEnv->CallObjectMethod(mInBuf, gInputByteBufferClassInfo.mGetMethod, + mByteArray, 0, realCount); mEnv->DeleteLocalRef(chainingBuf); if (mEnv->ExceptionCheck()) { @@ -630,8 +630,10 @@ static bool validateDngHeader(JNIEnv* env, TiffWriter* writer, jint width, jint bool hasThumbnail = writer->hasIfd(TIFF_IFD_SUB1); // TODO: handle lens shading map, etc. conversions for other raw buffer sizes. - uint32_t metadataWidth = *(writer->getEntry(TAG_IMAGEWIDTH, (hasThumbnail) ? TIFF_IFD_SUB1 : TIFF_IFD_0)->getData<uint32_t>()); - uint32_t metadataHeight = *(writer->getEntry(TAG_IMAGELENGTH, (hasThumbnail) ? TIFF_IFD_SUB1 : TIFF_IFD_0)->getData<uint32_t>()); + uint32_t metadataWidth = *(writer->getEntry(TAG_IMAGEWIDTH, (hasThumbnail) ? TIFF_IFD_SUB1 : + TIFF_IFD_0)->getData<uint32_t>()); + uint32_t metadataHeight = *(writer->getEntry(TAG_IMAGELENGTH, (hasThumbnail) ? TIFF_IFD_SUB1 : + TIFF_IFD_0)->getData<uint32_t>()); if (width < 0 || metadataWidth != static_cast<uint32_t>(width)) { jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", \ @@ -641,7 +643,8 @@ static bool validateDngHeader(JNIEnv* env, TiffWriter* writer, jint width, jint if (height < 0 || metadataHeight != static_cast<uint32_t>(height)) { jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", \ - "Metadata height %d doesn't match image height %d", metadataHeight, height); + "Metadata height %d doesn't match image height %d", + metadataHeight, height); return false; } @@ -1428,7 +1431,11 @@ static void DngCreator_init(JNIEnv* env, jobject thiz, jobject characteristicsPt } { - // Setup opcode List 2 + // Set up opcode List 2 + OpcodeListBuilder builder; + status_t err = OK; + + // Set up lens shading map camera_metadata_entry entry1 = characteristics.find(ANDROID_LENS_INFO_SHADING_MAP_SIZE); @@ -1444,34 +1451,52 @@ static void DngCreator_init(JNIEnv* env, jobject thiz, jobject characteristicsPt results.find(ANDROID_STATISTICS_LENS_SHADING_MAP); if (entry2.count > 0 && entry2.count == lsmWidth * lsmHeight * 4) { - - OpcodeListBuilder builder; - status_t err = builder.addGainMapsForMetadata(lsmWidth, - lsmHeight, - 0, - 0, - imageHeight, - imageWidth, - opcodeCfaLayout, - entry2.data.f); - if (err == OK) { - size_t listSize = builder.getSize(); - uint8_t opcodeListBuf[listSize]; - err = builder.buildOpList(opcodeListBuf); - if (err == OK) { - BAIL_IF_INVALID(writer->addEntry(TAG_OPCODELIST2, listSize, opcodeListBuf, - TIFF_IFD_0), env, TAG_OPCODELIST2, writer); - } else { - ALOGE("%s: Could not build Lens shading map opcode.", __FUNCTION__); - jniThrowRuntimeException(env, "failed to construct lens shading map opcode."); - } - } else { + err = builder.addGainMapsForMetadata(lsmWidth, + lsmHeight, + 0, + 0, + imageHeight, + imageWidth, + opcodeCfaLayout, + entry2.data.f); + if (err != OK) { ALOGE("%s: Could not add Lens shading map.", __FUNCTION__); jniThrowRuntimeException(env, "failed to add lens shading map."); + return; + } + } + + // Set up rectilinear distortion correction + camera_metadata_entry entry3 = + results.find(ANDROID_LENS_RADIAL_DISTORTION); + camera_metadata_entry entry4 = + results.find(ANDROID_LENS_INTRINSIC_CALIBRATION); + + if (entry3.count == 6 && entry4.count == 5) { + float cx = entry4.data.f[/*c_x*/2]; + float cy = entry4.data.f[/*c_y*/3]; + err = builder.addWarpRectilinearForMetadata(entry3.data.f, imageWidth, imageHeight, cx, + cy); + if (err != OK) { + ALOGE("%s: Could not add distortion correction.", __FUNCTION__); + jniThrowRuntimeException(env, "failed to add distortion correction."); + return; } + } + + + size_t listSize = builder.getSize(); + uint8_t opcodeListBuf[listSize]; + err = builder.buildOpList(opcodeListBuf); + if (err == OK) { + BAIL_IF_INVALID(writer->addEntry(TAG_OPCODELIST2, listSize, opcodeListBuf, + TIFF_IFD_0), env, TAG_OPCODELIST2, writer); } else { - ALOGW("%s: No lens shading map found in result metadata. Image quality may be reduced.", - __FUNCTION__); + ALOGE("%s: Could not build list of opcodes for distortion correction and lens shading" + "map.", __FUNCTION__); + jniThrowRuntimeException(env, "failed to construct opcode list for distortion" + " correction and lens shading map"); + return; } } diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 1cd07d1..ac00532 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -677,13 +677,14 @@ static jint convertAudioPortConfigFromNative(JNIEnv *env, // constructed by java code with correct class type (device, mix etc...) // and reference to AudioPort instance in this client jAudioPort = env->NewObject(gAudioPortClass, gAudioPortCstor, - jHandle, - 0, - NULL, - NULL, - NULL, - NULL, - NULL); + jHandle, // handle + 0, // role + NULL, // name + NULL, // samplingRates + NULL, // channelMasks + NULL, // channelIndexMasks + NULL, // formats + NULL); // gains env->DeleteLocalRef(jHandle); if (jAudioPort == NULL) { return (jint)AUDIO_JAVA_ERROR; @@ -837,11 +838,14 @@ static jint convertAudioPortFromNative(JNIEnv *env, jint jStatus = (jint)AUDIO_JAVA_SUCCESS; jintArray jSamplingRates = NULL; jintArray jChannelMasks = NULL; + jintArray jChannelIndexMasks = NULL; jintArray jFormats = NULL; jobjectArray jGains = NULL; jobject jHandle = NULL; jstring jDeviceName = NULL; bool useInMask; + size_t numPositionMasks = 0; + size_t numIndexMasks = 0; ALOGV("convertAudioPortFromNative id %d role %d type %d name %s", nAudioPort->id, nAudioPort->role, nAudioPort->type, nAudioPort->name); @@ -856,23 +860,43 @@ static jint convertAudioPortFromNative(JNIEnv *env, (jint *)nAudioPort->sample_rates); } - jChannelMasks = env->NewIntArray(nAudioPort->num_channel_masks); + // count up how many masks are positional and indexed + for(size_t index = 0; index < nAudioPort->num_channel_masks; index++) { + const audio_channel_mask_t mask = nAudioPort->channel_masks[index]; + if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) { + numIndexMasks++; + } else { + numPositionMasks++; + } + } + + jChannelMasks = env->NewIntArray(numPositionMasks); if (jChannelMasks == NULL) { jStatus = (jint)AUDIO_JAVA_ERROR; goto exit; } + jChannelIndexMasks = env->NewIntArray(numIndexMasks); + if (jChannelIndexMasks == NULL) { + jStatus = (jint)AUDIO_JAVA_ERROR; + goto exit; + } useInMask = useInChannelMask(nAudioPort->type, nAudioPort->role); - jint jMask; - for (size_t j = 0; j < nAudioPort->num_channel_masks; j++) { - if (useInMask) { - jMask = inChannelMaskFromNative(nAudioPort->channel_masks[j]); + // put the masks in the output arrays + for (size_t maskIndex = 0, posMaskIndex = 0, indexedMaskIndex = 0; + maskIndex < nAudioPort->num_channel_masks; maskIndex++) { + const audio_channel_mask_t mask = nAudioPort->channel_masks[maskIndex]; + if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) { + jint jMask = audio_channel_mask_get_bits(mask); + env->SetIntArrayRegion(jChannelIndexMasks, indexedMaskIndex++, 1, &jMask); } else { - jMask = outChannelMaskFromNative(nAudioPort->channel_masks[j]); + jint jMask = useInMask ? inChannelMaskFromNative(mask) + : outChannelMaskFromNative(mask); + env->SetIntArrayRegion(jChannelMasks, posMaskIndex++, 1, &jMask); } - env->SetIntArrayRegion(jChannelMasks, j, 1, &jMask); } + // formats jFormats = env->NewIntArray(nAudioPort->num_formats); if (jFormats == NULL) { jStatus = (jint)AUDIO_JAVA_ERROR; @@ -883,14 +907,17 @@ static jint convertAudioPortFromNative(JNIEnv *env, env->SetIntArrayRegion(jFormats, j, 1, &jFormat); } + // gains jGains = env->NewObjectArray(nAudioPort->num_gains, gAudioGainClass, NULL); if (jGains == NULL) { jStatus = (jint)AUDIO_JAVA_ERROR; goto exit; } + for (size_t j = 0; j < nAudioPort->num_gains; j++) { audio_channel_mask_t nMask = nAudioPort->gains[j].channel_mask; + jint jMask; if (useInMask) { jMask = inChannelMaskFromNative(nMask); ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask); @@ -931,7 +958,8 @@ static jint convertAudioPortFromNative(JNIEnv *env, jstring jAddress = env->NewStringUTF(nAudioPort->ext.device.address); *jAudioPort = env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor, jHandle, jDeviceName, - jSamplingRates, jChannelMasks, jFormats, jGains, + jSamplingRates, jChannelMasks, jChannelIndexMasks, + jFormats, jGains, nAudioPort->ext.device.type, jAddress); env->DeleteLocalRef(jAddress); } else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) { @@ -939,7 +967,7 @@ static jint convertAudioPortFromNative(JNIEnv *env, *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor, jHandle, nAudioPort->ext.mix.handle, nAudioPort->role, jDeviceName, - jSamplingRates, jChannelMasks, + jSamplingRates, jChannelMasks, jChannelIndexMasks, jFormats, jGains); } else { ALOGE("convertAudioPortFromNative unknown nAudioPort type %d", nAudioPort->type); @@ -1634,7 +1662,7 @@ int register_android_media_AudioSystem(JNIEnv *env) jclass audioPortClass = FindClassOrDie(env, "android/media/AudioPort"); gAudioPortClass = MakeGlobalRefOrDie(env, audioPortClass); gAudioPortCstor = GetMethodIDOrDie(env, audioPortClass, "<init>", - "(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[Landroid/media/AudioGain;)V"); + "(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V"); gAudioPortFields.mHandle = GetFieldIDOrDie(env, audioPortClass, "mHandle", "Landroid/media/AudioHandle;"); gAudioPortFields.mRole = GetFieldIDOrDie(env, audioPortClass, "mRole", "I"); @@ -1672,12 +1700,12 @@ int register_android_media_AudioSystem(JNIEnv *env) jclass audioDevicePortClass = FindClassOrDie(env, "android/media/AudioDevicePort"); gAudioDevicePortClass = MakeGlobalRefOrDie(env, audioDevicePortClass); gAudioDevicePortCstor = GetMethodIDOrDie(env, audioDevicePortClass, "<init>", - "(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V"); + "(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V"); jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort"); gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass); gAudioMixPortCstor = GetMethodIDOrDie(env, audioMixPortClass, "<init>", - "(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[Landroid/media/AudioGain;)V"); + "(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V"); jclass audioGainClass = FindClassOrDie(env, "android/media/AudioGain"); gAudioGainClass = MakeGlobalRefOrDie(env, audioGainClass); diff --git a/core/jni/android_util_Log.cpp b/core/jni/android_util_Log.cpp index 9a80f1d..2b1067b 100644 --- a/core/jni/android_util_Log.cpp +++ b/core/jni/android_util_Log.cpp @@ -41,32 +41,8 @@ struct levels_t { }; static levels_t levels; -static int toLevel(const char* value) -{ - switch (value[0]) { - case 'V': return levels.verbose; - case 'D': return levels.debug; - case 'I': return levels.info; - case 'W': return levels.warn; - case 'E': return levels.error; - case 'A': return levels.assert; - case 'S': return -1; // SUPPRESS - } - return levels.info; -} - static jboolean isLoggable(const char* tag, jint level) { - String8 key; - key.append(LOG_NAMESPACE); - key.append(tag); - - char buf[PROPERTY_VALUE_MAX]; - if (property_get(key.string(), buf, "") <= 0) { - buf[0] = '\0'; - } - - int logLevel = toLevel(buf); - return logLevel >= 0 && level >= logLevel; + return __android_log_is_loggable(level, tag, ANDROID_LOG_INFO); } static jboolean android_util_Log_isLoggable(JNIEnv* env, jobject clazz, jstring tag, jint level) diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml index c0d9995..94e9c4e 100644 --- a/core/res/res/values-sw600dp/dimens.xml +++ b/core/res/res/values-sw600dp/dimens.xml @@ -115,4 +115,6 @@ <!-- width of ImmersiveModeConfirmation (-1 for match_parent) --> <dimen name="immersive_mode_cling_width">380dp</dimen> + + <dimen name="floating_toolbar_preferred_width">544dp</dimen> </resources> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index e7811df..7272ae3 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1271,11 +1271,6 @@ an mcc/mnc specific config.xml --> <string name="mobile_provisioning_url" translatable="false"></string> - <!-- This url is used as the default url when redirection is detected. Any - should work as all url's get redirected. But maybe overridden by - if needed. --> - <string name="mobile_redirected_provisioning_url" translatable="false">http://google.com</string> - <!-- The default character set for GsmAlphabet --> <!-- Empty string means MBCS is not considered --> <string name="gsm_alphabet_default_charset" translatable="false"></string> @@ -2196,6 +2191,9 @@ <!-- Keyguard component --> <string name="config_keyguardComponent" translatable="false">com.android.systemui/com.android.systemui.keyguard.KeyguardService</string> + <!-- For performance and storage reasons, limit the number of fingerprints per user --> + <integer name="config_fingerprintMaxTemplatesPerUser">5</integer> + <!-- This config is used to force VoiceInteractionService to start on certain low ram devices. It declares the package name of VoiceInteractionService that should be started. --> <string translatable="false" name="config_forceVoiceInteractionServicePackage"></string> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 2908cc5..510f6a5 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -34,7 +34,7 @@ to display a size in kilobytes, megabytes, or other size units. Some languages (like French) will want to add a space between the placeholders. --> - <string name="fileSizeSuffix"><xliff:g id="number" example="123">%1$s</xliff:g><xliff:g id="unit" example="KB">%2$s</xliff:g></string> + <string name="fileSizeSuffix"><xliff:g id="number" example="123">%1$s</xliff:g> <xliff:g id="unit" example="KB">%2$s</xliff:g></string> <!-- [CHAR_LIMIT=10] Suffix added to signify duration in days --> <string name="durationDays"><xliff:g id="days">%1$d</xliff:g> days</string> @@ -1969,9 +1969,9 @@ <string name="lockscreen_access_pattern_start">Pattern started</string> <!-- Accessibility description sent when the pattern times out and is cleared. [CHAR LIMIT=NONE] --> <string name="lockscreen_access_pattern_cleared">Pattern cleared</string> - <!-- Accessibility description sent when user adds a cell to the pattern. [CHAR LIMIT=NONE] --> + <!-- Accessibility description sent when user adds a dot to the pattern. [CHAR LIMIT=NONE] --> <string name="lockscreen_access_pattern_cell_added">Cell added</string> - <!-- Accessibility description sent when user adds a cell to the pattern. Announces the + <!-- Accessibility description sent when user adds a dot to the pattern. Announces the actual cell when headphones are connected [CHAR LIMIT=NONE] --> <string name="lockscreen_access_pattern_cell_added_verbose"> Cell <xliff:g id="cell_index" example="3">%1$s</xliff:g> added</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 45e5d17..5ba57c4 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -818,7 +818,6 @@ <java-symbol type="string" name="progress_unmounting" /> <java-symbol type="string" name="mobile_provisioning_apn" /> <java-symbol type="string" name="mobile_provisioning_url" /> - <java-symbol type="string" name="mobile_redirected_provisioning_url" /> <java-symbol type="string" name="quick_contacts_not_available" /> <java-symbol type="string" name="reboot_to_update_package" /> <java-symbol type="string" name="reboot_to_update_prepare" /> @@ -2125,6 +2124,9 @@ <java-symbol type="string" name="fingerprint_error_lockout" /> <java-symbol type="string" name="fingerprint_name_template" /> + <!-- Fingerprint config --> + <java-symbol type="integer" name="config_fingerprintMaxTemplatesPerUser"/> + <!-- From various Material changes --> <java-symbol type="attr" name="titleTextAppearance" /> <java-symbol type="attr" name="subtitleTextAppearance" /> @@ -2309,5 +2311,6 @@ <java-symbol type="string" name="ext_media_unsupported_notification_message" /> <java-symbol type="string" name="ext_media_unsupported_notification_title" /> <java-symbol type="plurals" name="selected_count" /> + <java-symbol type="drawable" name="ic_dialog_alert_material" /> </resources> diff --git a/core/tests/coretests/src/android/net/NetworkTest.java b/core/tests/coretests/src/android/net/NetworkTest.java index b0ecb04..74b6d98 100644 --- a/core/tests/coretests/src/android/net/NetworkTest.java +++ b/core/tests/coretests/src/android/net/NetworkTest.java @@ -16,11 +16,14 @@ package android.net; +import static android.test.MoreAsserts.assertNotEqual; + import android.net.LocalServerSocket; import android.net.LocalSocket; import android.net.LocalSocketAddress; import android.net.Network; import android.test.suitebuilder.annotation.SmallTest; + import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; @@ -29,6 +32,7 @@ import java.net.DatagramSocket; import java.net.InetAddress; import java.net.Inet6Address; import java.net.SocketException; + import junit.framework.TestCase; public class NetworkTest extends TestCase { @@ -93,4 +97,50 @@ public class NetworkTest extends TestCase { fail("SocketException not thrown"); } catch (SocketException expected) {} } + + @SmallTest + public void testZeroIsObviousForDebugging() { + Network zero = new Network(0); + assertEquals(0, zero.hashCode()); + assertEquals(0, zero.getNetworkHandle()); + assertEquals("0", zero.toString()); + } + + @SmallTest + public void testGetNetworkHandle() { + Network one = new Network(1); + Network two = new Network(2); + Network three = new Network(3); + + // None of the hashcodes are zero. + assertNotEqual(0, one.hashCode()); + assertNotEqual(0, two.hashCode()); + assertNotEqual(0, three.hashCode()); + + // All the hashcodes are distinct. + assertNotEqual(one.hashCode(), two.hashCode()); + assertNotEqual(one.hashCode(), three.hashCode()); + assertNotEqual(two.hashCode(), three.hashCode()); + + // None of the handles are zero. + assertNotEqual(0, one.getNetworkHandle()); + assertNotEqual(0, two.getNetworkHandle()); + assertNotEqual(0, three.getNetworkHandle()); + + // All the handles are distinct. + assertNotEqual(one.getNetworkHandle(), two.getNetworkHandle()); + assertNotEqual(one.getNetworkHandle(), three.getNetworkHandle()); + assertNotEqual(two.getNetworkHandle(), three.getNetworkHandle()); + + // The handles are not equal to the hashcodes. + assertNotEqual(one.hashCode(), one.getNetworkHandle()); + assertNotEqual(two.hashCode(), two.getNetworkHandle()); + assertNotEqual(three.hashCode(), three.getNetworkHandle()); + + // Adjust as necessary to test an implementation's specific constants. + // When running with runtest, "adb logcat -s TestRunner" can be useful. + assertEquals(4311403230L, one.getNetworkHandle()); + assertEquals(8606370526L, two.getNetworkHandle()); + assertEquals(12901337822L, three.getNetworkHandle()); + } } diff --git a/docs/html/index.jd b/docs/html/index.jd index 3989b92..cd129d4 100644 --- a/docs/html/index.jd +++ b/docs/html/index.jd @@ -26,9 +26,9 @@ page.customHeadTag=<meta name="google-site-verification" content="sa-bIAI6GKvct3 <p class="dac-hero-description">Get your apps ready for the next version of Android. Test on Nexus 5, 6, 9, and Player. </p> - <a class="dac-hero-cta" href="{@docRoot}preview/index.html"> + <a class="dac-hero-cta" href="{@docRoot}preview/overview.html"> <span class="dac-sprite dac-auto-chevron"></span> - Learn more + Get started </a> </div> </div> diff --git a/docs/html/jd_collections.js b/docs/html/jd_collections.js index 82836e2..86089e6 100644 --- a/docs/html/jd_collections.js +++ b/docs/html/jd_collections.js @@ -1594,7 +1594,8 @@ var RESOURCE_COLLECTIONS = { "training/enterprise/app-restrictions.html", "https://www.youtube.com/watch?v=39NkpWkaH8M&index=2&list=PLOU2XLYxmsIKAK2Bhv19H2THwF-22O5WX", "samples/AppRestrictionSchema/index.html", - "samples/AppRestrictionEnforcer/index.html" + "samples/AppRestrictionEnforcer/index.html", + "https://www.youtube.com/watch?v=dH41OutAMNM" ] }, "training/work/admin": { diff --git a/docs/html/preview/index.jd b/docs/html/preview/index.jd index eb18aa6..68186bd 100644 --- a/docs/html/preview/index.jd +++ b/docs/html/preview/index.jd @@ -26,7 +26,7 @@ footer.hide=1 <a class="dac-hero-cta" href="{@docRoot}preview/overview.html"> <span class="dac-sprite dac-auto-chevron"></span> - Get Started! + Get started </a><br> </div> </div> @@ -44,7 +44,7 @@ footer.hide=1 <div class="dac-section-subtitle"> Essential information to help you get your apps ready for Android M. </div> - + <div class="resource-widget resource-flow-layout col-16" data-query="collection:preview/landing/more" data-cardSizes="6x6" @@ -56,7 +56,7 @@ footer.hide=1 <span class="dac-sprite dac-auto-chevron"></span> Report Issues </a> - </li> + </li> <li class="dac-section-link"><a href="http://g.co/dev/AndroidMDevPreview"> <span class="dac-sprite dac-auto-chevron"></span> Join G+ Community diff --git a/docs/html/training/tv/discovery/searchable.jd b/docs/html/training/tv/discovery/searchable.jd index 27a1c33..4ca7abb 100644 --- a/docs/html/training/tv/discovery/searchable.jd +++ b/docs/html/training/tv/discovery/searchable.jd @@ -90,7 +90,7 @@ more important columns are described below.</p> <td>The production year of your content <strong>(required)</strong></td> </tr><tr> <td>{@code SUGGEST_COLUMN_DURATION}</td> - <td>The duration in milliseconds of your media</td> + <td>The duration in milliseconds of your media <strong>(required)</strong></td> </tr> </table> @@ -99,6 +99,7 @@ more important columns are described below.</p> <li>{@link android.app.SearchManager#SUGGEST_COLUMN_TEXT_1}</li> <li>{@link android.app.SearchManager#SUGGEST_COLUMN_CONTENT_TYPE}</li> <li>{@link android.app.SearchManager#SUGGEST_COLUMN_PRODUCTION_YEAR}</li> + <li>{@link android.app.SearchManager#SUGGEST_COLUMN_DURATION}</li> </ul> <p>When the values of these columns for your content match the values for the same content from other diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java index 82a592a..a0c407f 100644 --- a/graphics/java/android/graphics/drawable/BitmapDrawable.java +++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java @@ -815,6 +815,9 @@ public class BitmapDrawable extends Drawable { if (tileModeY != TILE_MODE_UNDEFINED) { setTileModeY(parseTileMode(tileModeY)); } + + final int densityDpi = r.getDisplayMetrics().densityDpi; + state.mTargetDensity = densityDpi == 0 ? DisplayMetrics.DENSITY_DEFAULT : densityDpi; } @Override @@ -977,7 +980,8 @@ public class BitmapDrawable extends Drawable { */ private void updateLocalState(Resources res) { if (res != null) { - mTargetDensity = res.getDisplayMetrics().densityDpi; + final int densityDpi = res.getDisplayMetrics().densityDpi; + mTargetDensity = densityDpi == 0 ? DisplayMetrics.DENSITY_DEFAULT : densityDpi; } else { mTargetDensity = mBitmapState.mTargetDensity; } diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index 532c888..415af0d 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -1147,6 +1147,7 @@ public abstract class Drawable { * document, tries to create a Drawable from that tag. Returns {@code null} * if the tag is not a valid drawable. */ + @SuppressWarnings("deprecation") public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme) throws XmlPullParserException, IOException { final Drawable drawable; @@ -1202,16 +1203,10 @@ public abstract class Drawable { drawable = new InsetDrawable(); break; case "bitmap": - drawable = new BitmapDrawable(r); - if (r != null) { - ((BitmapDrawable) drawable).setTargetDensity(r.getDisplayMetrics()); - } + drawable = new BitmapDrawable(); break; case "nine-patch": drawable = new NinePatchDrawable(); - if (r != null) { - ((NinePatchDrawable) drawable).setTargetDensity(r.getDisplayMetrics()); - } break; default: throw new XmlPullParserException(parser.getPositionDescription() + diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java index 91bbff7..0b7869b 100644 --- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java +++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java @@ -482,6 +482,9 @@ public class NinePatchDrawable extends Drawable { if (tint != null) { state.mTint = tint; } + + final int densityDpi = r.getDisplayMetrics().densityDpi; + state.mTargetDensity = densityDpi == 0 ? DisplayMetrics.DENSITY_DEFAULT : densityDpi; } @Override @@ -713,7 +716,8 @@ public class NinePatchDrawable extends Drawable { final NinePatchState state = mNinePatchState; if (res != null) { - mTargetDensity = res.getDisplayMetrics().densityDpi; + final int densityDpi = res.getDisplayMetrics().densityDpi; + mTargetDensity = densityDpi == 0 ? DisplayMetrics.DENSITY_DEFAULT : densityDpi; } else { mTargetDensity = state.mTargetDensity; } diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java index 4c0631f..8d4bfcd 100644 --- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java @@ -70,6 +70,8 @@ import javax.security.auth.x500.X500Principal; * <p>NOTE: The key material of the generated symmetric and private keys is not accessible. The key * material of the public keys is accessible. * + * <p>Instances of this class are immutable. + * * <p><h3>Example: Asymmetric key pair</h3> * The following example illustrates how to generate an EC key pair in the Android KeyStore system * under alias {@code key1} authorized to be used only for signing using SHA-256, SHA-384, @@ -79,11 +81,12 @@ import javax.security.auth.x500.X500Principal; * KeyProperties.KEY_ALGORITHM_EC, * "AndroidKeyStore"); * keyPairGenerator.initialize( - * new KeyGenParameterSpec.Builder("key1", + * new KeyGenParameterSpec.Builder( + * "key1", * KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) - * .setDigests(KeyProperties.DIGEST_SHA256 - * | KeyProperties.DIGEST_SHA384 - * | KeyProperties.DIGEST_SHA512) + * .setDigests(KeyProperties.DIGEST_SHA256, + * KeyProperties.DIGEST_SHA384, + * KeyProperties.DIGEST_SHA512) * // Only permit this key to be used if the user authenticated * // within the last five minutes. * .setUserAuthenticationRequired(true) @@ -100,16 +103,17 @@ import javax.security.auth.x500.X500Principal; * * <p><h3>Example: Symmetric key</h3> * The following example illustrates how to generate an AES key in the Android KeyStore system under - * alias {@code key2} authorized to be used only for encryption/decryption in CTR mode. + * alias {@code key2} authorized to be used only for encryption/decryption in CBC mode with PKCS#7 + * padding. * <pre> {@code * KeyGenerator keyGenerator = KeyGenerator.getInstance( - * KeyProperties.KEY_ALGORITHM_HMAC_SHA256, + * KeyProperties.KEY_ALGORITHM_AES, * "AndroidKeyStore"); * keyGenerator.initialize( * new KeyGenParameterSpec.Builder("key2", * KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) - * .setBlockModes(KeyProperties.BLOCK_MODE_CTR) - * .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) + * .setBlockModes(KeyProperties.BLOCK_MODE_CBC) + * .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) * .build()); * SecretKey key = keyGenerator.generateKey(); * @@ -169,10 +173,6 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { int userAuthenticationValidityDurationSeconds) { if (TextUtils.isEmpty(keyStoreAlias)) { throw new IllegalArgumentException("keyStoreAlias must not be empty"); - } else if ((userAuthenticationValidityDurationSeconds < 0) - && (userAuthenticationValidityDurationSeconds != -1)) { - throw new IllegalArgumentException( - "userAuthenticationValidityDurationSeconds must not be negative"); } if (certificateSubject == null) { @@ -197,11 +197,11 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { mSpec = spec; mCertificateSubject = certificateSubject; mCertificateSerialNumber = certificateSerialNumber; - mCertificateNotBefore = certificateNotBefore; - mCertificateNotAfter = certificateNotAfter; - mKeyValidityStart = keyValidityStart; - mKeyValidityForOriginationEnd = keyValidityForOriginationEnd; - mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd; + mCertificateNotBefore = Utils.cloneIfNotNull(certificateNotBefore); + mCertificateNotAfter = Utils.cloneIfNotNull(certificateNotAfter); + mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart); + mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd); + mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd); mPurposes = purposes; mDigests = ArrayUtils.cloneIfNotEmpty(digests); mEncryptionPaddings = @@ -217,6 +217,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { * Returns the alias that will be used in the {@code java.security.KeyStore} * in conjunction with the {@code AndroidKeyStore}. */ + @NonNull public String getKeystoreAlias() { return mKeystoreAlias; } @@ -231,10 +232,10 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { } /** - * Returns the {@link AlgorithmParameterSpec} that will be used for creation - * of the key pair. + * Returns the key algorithm-specific {@link AlgorithmParameterSpec} that will be used for + * creation of the key or {@code null} if algorithm-specific defaults should be used. */ - @NonNull + @Nullable public AlgorithmParameterSpec getAlgorithmParameterSpec() { return mSpec; } @@ -263,7 +264,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { */ @NonNull public Date getCertificateNotBefore() { - return mCertificateNotBefore; + return Utils.cloneIfNotNull(mCertificateNotBefore); } /** @@ -272,7 +273,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { */ @NonNull public Date getCertificateNotAfter() { - return mCertificateNotAfter; + return Utils.cloneIfNotNull(mCertificateNotAfter); } /** @@ -281,7 +282,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { */ @Nullable public Date getKeyValidityStart() { - return mKeyValidityStart; + return Utils.cloneIfNotNull(mKeyValidityStart); } /** @@ -290,7 +291,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { */ @Nullable public Date getKeyValidityForConsumptionEnd() { - return mKeyValidityForConsumptionEnd; + return Utils.cloneIfNotNull(mKeyValidityForConsumptionEnd); } /** @@ -299,7 +300,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { */ @Nullable public Date getKeyValidityForOriginationEnd() { - return mKeyValidityForOriginationEnd; + return Utils.cloneIfNotNull(mKeyValidityForOriginationEnd); } /** @@ -411,7 +412,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { * restricted. * * @return duration in seconds or {@code -1} if authentication is required for every use of the - * key. + * key. * * @see #isUserAuthenticationRequired() */ @@ -447,7 +448,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { * Creates a new instance of the {@code Builder}. * * @param keystoreAlias alias of the entry in which the generated key will appear in - * Android KeyStore. + * Android KeyStore. Must not be empty. * @param purposes set of purposes (e.g., encrypt, decrypt, sign) for which the key can be * used. Attempts to use the key for any other purpose will be rejected. * @@ -462,6 +463,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { public Builder(@NonNull String keystoreAlias, @KeyProperties.PurposeEnum int purposes) { if (keystoreAlias == null) { throw new NullPointerException("keystoreAlias == null"); + } else if (keystoreAlias.isEmpty()) { + throw new IllegalArgumentException("keystoreAlias must not be empty"); } mKeystoreAlias = keystoreAlias; mPurposes = purposes; @@ -488,7 +491,11 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { /** * Sets the algorithm-specific key generation parameters. For example, for RSA keys this may - * be an instance of {@link java.security.spec.RSAKeyGenParameterSpec}. + * be an instance of {@link java.security.spec.RSAKeyGenParameterSpec} whereas for EC keys + * this may be an instance of {@link java.security.spec.ECGenParameterSpec}. + * + * <p>These key generation parameters must match other explicitly set parameters (if any), + * such as key size. */ public Builder setAlgorithmParameterSpec(@NonNull AlgorithmParameterSpec spec) { if (spec == null) { @@ -537,7 +544,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { if (date == null) { throw new NullPointerException("date == null"); } - mCertificateNotBefore = date; + mCertificateNotBefore = Utils.cloneIfNotNull(date); return this; } @@ -552,7 +559,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { if (date == null) { throw new NullPointerException("date == null"); } - mCertificateNotAfter = date; + mCertificateNotAfter = Utils.cloneIfNotNull(date); return this; } @@ -565,7 +572,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { */ @NonNull public Builder setKeyValidityStart(Date startDate) { - mKeyValidityStart = startDate; + mKeyValidityStart = Utils.cloneIfNotNull(startDate); return this; } @@ -594,7 +601,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { */ @NonNull public Builder setKeyValidityForOriginationEnd(Date endDate) { - mKeyValidityForOriginationEnd = endDate; + mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(endDate); return this; } @@ -608,7 +615,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { */ @NonNull public Builder setKeyValidityForConsumptionEnd(Date endDate) { - mKeyValidityForConsumptionEnd = endDate; + mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(endDate); return this; } @@ -768,14 +775,15 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { @NonNull public Builder setUserAuthenticationValidityDurationSeconds( @IntRange(from = -1) int seconds) { + if (seconds < -1) { + throw new IllegalArgumentException("seconds must be -1 or larger"); + } mUserAuthenticationValidityDurationSeconds = seconds; return this; } /** * Builds an instance of {@code KeyGenParameterSpec}. - * - * @throws IllegalArgumentException if a required field is missing */ @NonNull public KeyGenParameterSpec build() { diff --git a/keystore/java/android/security/keystore/KeyInfo.java b/keystore/java/android/security/keystore/KeyInfo.java index e4f921e..03b4100 100644 --- a/keystore/java/android/security/keystore/KeyInfo.java +++ b/keystore/java/android/security/keystore/KeyInfo.java @@ -33,6 +33,8 @@ import javax.crypto.SecretKey; * is authorized for (e.g., only in {@code CBC} mode, or signing only), whether the key should be * encrypted at rest, the key's and validity start and end dates. * + * <p>Instances of this class are immutable. + * * <p><h3>Example: Symmetric Key</h3> * The following example illustrates how to obtain a {@code KeyInfo} describing the provided Android * Keystore {@link SecretKey}. @@ -102,9 +104,9 @@ public class KeyInfo implements KeySpec { mInsideSecureHardware = insideSecureHardware; mOrigin = origin; mKeySize = keySize; - mKeyValidityStart = keyValidityStart; - mKeyValidityForOriginationEnd = keyValidityForOriginationEnd; - mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd; + mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart); + mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd); + mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd); mPurposes = purposes; mEncryptionPaddings = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(encryptionPaddings)); @@ -155,7 +157,7 @@ public class KeyInfo implements KeySpec { */ @Nullable public Date getKeyValidityStart() { - return mKeyValidityStart; + return Utils.cloneIfNotNull(mKeyValidityStart); } /** @@ -165,7 +167,7 @@ public class KeyInfo implements KeySpec { */ @Nullable public Date getKeyValidityForConsumptionEnd() { - return mKeyValidityForConsumptionEnd; + return Utils.cloneIfNotNull(mKeyValidityForConsumptionEnd); } /** @@ -175,7 +177,7 @@ public class KeyInfo implements KeySpec { */ @Nullable public Date getKeyValidityForOriginationEnd() { - return mKeyValidityForOriginationEnd; + return Utils.cloneIfNotNull(mKeyValidityForOriginationEnd); } /** diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java index 432fc12..1e0611c 100644 --- a/keystore/java/android/security/keystore/KeyProtection.java +++ b/keystore/java/android/security/keystore/KeyProtection.java @@ -47,6 +47,8 @@ import javax.crypto.Cipher; * * <p>NOTE: The key material of keys stored in the Android KeyStore is not accessible. * + * <p>Instances of this class are immutable. + * * <p><h3>Example: Symmetric Key</h3> * The following example illustrates how to import an AES key into the Android KeyStore under alias * {@code key1} authorized to be used only for encryption/decryption in CBC mode with PKCS#7 @@ -122,15 +124,9 @@ public final class KeyProtection implements ProtectionParameter { boolean randomizedEncryptionRequired, boolean userAuthenticationRequired, int userAuthenticationValidityDurationSeconds) { - if ((userAuthenticationValidityDurationSeconds < 0) - && (userAuthenticationValidityDurationSeconds != -1)) { - throw new IllegalArgumentException( - "userAuthenticationValidityDurationSeconds must not be negative"); - } - - mKeyValidityStart = keyValidityStart; - mKeyValidityForOriginationEnd = keyValidityForOriginationEnd; - mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd; + mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart); + mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd); + mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd); mPurposes = purposes; mEncryptionPaddings = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(encryptionPaddings)); @@ -150,7 +146,7 @@ public final class KeyProtection implements ProtectionParameter { */ @Nullable public Date getKeyValidityStart() { - return mKeyValidityStart; + return Utils.cloneIfNotNull(mKeyValidityStart); } /** @@ -160,7 +156,7 @@ public final class KeyProtection implements ProtectionParameter { */ @Nullable public Date getKeyValidityForConsumptionEnd() { - return mKeyValidityForConsumptionEnd; + return Utils.cloneIfNotNull(mKeyValidityForConsumptionEnd); } /** @@ -170,7 +166,7 @@ public final class KeyProtection implements ProtectionParameter { */ @Nullable public Date getKeyValidityForOriginationEnd() { - return mKeyValidityForOriginationEnd; + return Utils.cloneIfNotNull(mKeyValidityForOriginationEnd); } /** @@ -320,7 +316,7 @@ public final class KeyProtection implements ProtectionParameter { */ @NonNull public Builder setKeyValidityStart(Date startDate) { - mKeyValidityStart = startDate; + mKeyValidityStart = Utils.cloneIfNotNull(startDate); return this; } @@ -349,7 +345,7 @@ public final class KeyProtection implements ProtectionParameter { */ @NonNull public Builder setKeyValidityForOriginationEnd(Date endDate) { - mKeyValidityForOriginationEnd = endDate; + mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(endDate); return this; } @@ -363,7 +359,7 @@ public final class KeyProtection implements ProtectionParameter { */ @NonNull public Builder setKeyValidityForConsumptionEnd(Date endDate) { - mKeyValidityForConsumptionEnd = endDate; + mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(endDate); return this; } @@ -517,6 +513,9 @@ public final class KeyProtection implements ProtectionParameter { @NonNull public Builder setUserAuthenticationValidityDurationSeconds( @IntRange(from = -1) int seconds) { + if (seconds < -1) { + throw new IllegalArgumentException("seconds must be -1 or larger"); + } mUserAuthenticationValidityDurationSeconds = seconds; return this; } diff --git a/keystore/java/android/security/keystore/Utils.java b/keystore/java/android/security/keystore/Utils.java new file mode 100644 index 0000000..9bec682 --- /dev/null +++ b/keystore/java/android/security/keystore/Utils.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore; + +import java.util.Date; + +/** + * Assorted utility methods. + * + * @hide + */ +abstract class Utils { + private Utils() {} + + static Date cloneIfNotNull(Date value) { + return (value != null) ? (Date) value.clone() : null; + } +} diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index b4cbc36..fc18491 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -241,8 +241,12 @@ void RenderNode::prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer) { animatorDirtyMask = mAnimatorManager.animate(info); } - bool willHaveFunctor = info.mode == TreeInfo::MODE_FULL && mStagingDisplayListData - ? !mStagingDisplayListData->functors.isEmpty() : !mDisplayListData->functors.isEmpty(); + bool willHaveFunctor = false; + if (info.mode == TreeInfo::MODE_FULL && mStagingDisplayListData) { + willHaveFunctor = !mStagingDisplayListData->functors.isEmpty(); + } else if (mDisplayListData) { + willHaveFunctor = !mDisplayListData->functors.isEmpty(); + } bool childFunctorsNeedLayer = mProperties.prepareForFunctorPresence( willHaveFunctor, functorsNeedLayer); diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java index 431d37e..173d349 100644 --- a/media/java/android/media/AudioDeviceInfo.java +++ b/media/java/android/media/AudioDeviceInfo.java @@ -173,8 +173,7 @@ public final class AudioDeviceInfo { * @see AudioFormat */ public @NonNull int[] getChannelIndexMasks() { - // TODO: implement - return new int[0]; + return mPort.channelIndexMasks(); } /** diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java index c078260..aea39a3 100644 --- a/media/java/android/media/AudioDevicePort.java +++ b/media/java/android/media/AudioDevicePort.java @@ -37,12 +37,12 @@ public class AudioDevicePort extends AudioPort { private final String mAddress; AudioDevicePort(AudioHandle handle, String deviceName, - int[] samplingRates, int[] channelMasks, + int[] samplingRates, int[] channelMasks, int[] channelIndexMasks, int[] formats, AudioGain[] gains, int type, String address) { super(handle, (AudioManager.isInputDevice(type) == true) ? AudioPort.ROLE_SOURCE : AudioPort.ROLE_SINK, - deviceName, samplingRates, channelMasks, formats, gains); + deviceName, samplingRates, channelMasks, channelIndexMasks, formats, gains); mType = type; mAddress = address; } diff --git a/media/java/android/media/AudioMixPort.java b/media/java/android/media/AudioMixPort.java index ab55c8d..ba144bf 100644 --- a/media/java/android/media/AudioMixPort.java +++ b/media/java/android/media/AudioMixPort.java @@ -31,9 +31,10 @@ public class AudioMixPort extends AudioPort { private final int mIoHandle; AudioMixPort(AudioHandle handle, int ioHandle, int role, String deviceName, - int[] samplingRates, int[] channelMasks, + int[] samplingRates, int[] channelMasks, int[] channelIndexMasks, int[] formats, AudioGain[] gains) { - super(handle, role, deviceName, samplingRates, channelMasks, formats, gains); + super(handle, role, deviceName, samplingRates, channelMasks, channelIndexMasks, + formats, gains); mIoHandle = ioHandle; } diff --git a/media/java/android/media/AudioPort.java b/media/java/android/media/AudioPort.java index 7328d7a..19bf51d 100644 --- a/media/java/android/media/AudioPort.java +++ b/media/java/android/media/AudioPort.java @@ -71,12 +71,13 @@ public class AudioPort { private final String mName; private final int[] mSamplingRates; private final int[] mChannelMasks; + private final int[] mChannelIndexMasks; private final int[] mFormats; private final AudioGain[] mGains; private AudioPortConfig mActiveConfig; AudioPort(AudioHandle handle, int role, String name, - int[] samplingRates, int[] channelMasks, + int[] samplingRates, int[] channelMasks, int[] channelIndexMasks, int[] formats, AudioGain[] gains) { mHandle = handle; @@ -84,6 +85,7 @@ public class AudioPort { mName = name; mSamplingRates = samplingRates; mChannelMasks = channelMasks; + mChannelIndexMasks = channelIndexMasks; mFormats = formats; mGains = gains; } @@ -133,6 +135,15 @@ public class AudioPort { } /** + * Get the list of supported channel index mask configurations + * (e.g 0x0003 means 2 channel, 0x000F means 4 channel....) + * Empty array if channel index mask is not relevant for this audio port + */ + public int[] channelIndexMasks() { + return mChannelIndexMasks; + } + + /** * Get the list of supported audio format configurations * (e.g AudioFormat.ENCODING_PCM_16BIT) * Empty array if format is not relevant for this audio port diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java index 73a723d..4143e15 100644 --- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java @@ -120,13 +120,20 @@ public class ExternalStorageProvider extends DocumentsProvider { if (!volume.isMountedReadable()) continue; final String rootId; - if (VolumeInfo.ID_EMULATED_INTERNAL.equals(volume.getId())) { + final String title; + if (volume.getType() == VolumeInfo.TYPE_EMULATED) { + // We currently only support a single emulated volume mounted at + // a time, and it's always considered the primary rootId = ROOT_ID_PRIMARY_EMULATED; - } else if (volume.getType() == VolumeInfo.TYPE_EMULATED) { - final VolumeInfo privateVol = mStorageManager.findPrivateForEmulated(volume); - rootId = privateVol.getFsUuid(); + if (VolumeInfo.ID_EMULATED_INTERNAL.equals(volume.getId())) { + title = getContext().getString(R.string.root_internal_storage); + } else { + final VolumeInfo privateVol = mStorageManager.findPrivateForEmulated(volume); + title = mStorageManager.getBestVolumeDescription(privateVol); + } } else if (volume.getType() == VolumeInfo.TYPE_PUBLIC) { rootId = volume.getFsUuid(); + title = mStorageManager.getBestVolumeDescription(volume); } else { // Unsupported volume; ignore continue; @@ -148,11 +155,7 @@ public class ExternalStorageProvider extends DocumentsProvider { root.rootId = rootId; root.flags = Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED | Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_IS_CHILD; - if (ROOT_ID_PRIMARY_EMULATED.equals(rootId)) { - root.title = getContext().getString(R.string.root_internal_storage); - } else { - root.title = mStorageManager.getBestVolumeDescription(volume); - } + root.title = title; if (volume.getType() == VolumeInfo.TYPE_PUBLIC) { root.flags |= Root.FLAG_HAS_SETTINGS; } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index 7bf2223..5a14967 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -2682,9 +2682,6 @@ class DatabaseHelper extends SQLiteOpenHelper { // Set default cdma call auto retry loadSetting(stmt, Settings.Global.CALL_AUTO_RETRY, 0); - // Set default simplified carrier network settings to 0 - loadSetting(stmt, Settings.Global.HIDE_CARRIER_NETWORK_SETTINGS, 0); - // Set the preferred network mode to target desired value or Default // value defined in RILConstants int type; diff --git a/packages/Shell/src/com/android/shell/BugreportReceiver.java b/packages/Shell/src/com/android/shell/BugreportReceiver.java index e1bfc43..13747ed 100644 --- a/packages/Shell/src/com/android/shell/BugreportReceiver.java +++ b/packages/Shell/src/com/android/shell/BugreportReceiver.java @@ -33,11 +33,23 @@ import android.os.FileUtils; import android.os.SystemProperties; import android.support.v4.content.FileProvider; import android.text.format.DateUtils; +import android.util.Log; import android.util.Patterns; import com.google.android.collect.Lists; +import libcore.io.Streams; +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.Closeable; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; import java.util.ArrayList; /** @@ -73,30 +85,14 @@ public class BugreportReceiver extends BroadcastReceiver { final Uri bugreportUri = FileProvider.getUriForFile(context, AUTHORITY, bugreportFile); final Uri screenshotUri = FileProvider.getUriForFile(context, AUTHORITY, screenshotFile); - Intent sendIntent = buildSendIntent(context, bugreportUri, screenshotUri); - Intent notifIntent; - - // Send through warning dialog by default - if (getWarningState(context, STATE_SHOW) == STATE_SHOW) { - notifIntent = buildWarningIntent(context, sendIntent); + boolean isPlainText = bugreportFile.getName().toLowerCase().endsWith(".txt"); + if (!isPlainText) { + // Already zipped, send it right away. + sendBugreportNotification(context, bugreportFile, screenshotFile); } else { - notifIntent = sendIntent; + // Asynchronously zip the file first, then send it. + sendZippedBugreportNotification(context, bugreportFile, screenshotFile); } - notifIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - - final Notification.Builder builder = new Notification.Builder(context) - .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb) - .setContentTitle(context.getString(R.string.bugreport_finished_title)) - .setTicker(context.getString(R.string.bugreport_finished_title)) - .setContentText(context.getString(R.string.bugreport_finished_text)) - .setContentIntent(PendingIntent.getActivity( - context, 0, notifIntent, PendingIntent.FLAG_CANCEL_CURRENT)) - .setAutoCancel(true) - .setLocalOnly(true) - .setColor(context.getColor( - com.android.internal.R.color.system_notification_accent_color)); - - NotificationManager.from(context).notify(TAG, 0, builder.build()); // Clean up older bugreports in background final PendingResult result = goAsync(); @@ -141,6 +137,88 @@ public class BugreportReceiver extends BroadcastReceiver { } /** + * Sends a bugreport notitication. + */ + private static void sendBugreportNotification(Context context, File bugreportFile, + File screenshotFile) { + // Files are kept on private storage, so turn into Uris that we can + // grant temporary permissions for. + final Uri bugreportUri = FileProvider.getUriForFile(context, AUTHORITY, bugreportFile); + final Uri screenshotUri = FileProvider.getUriForFile(context, AUTHORITY, screenshotFile); + + Intent sendIntent = buildSendIntent(context, bugreportUri, screenshotUri); + Intent notifIntent; + + // Send through warning dialog by default + if (getWarningState(context, STATE_SHOW) == STATE_SHOW) { + notifIntent = buildWarningIntent(context, sendIntent); + } else { + notifIntent = sendIntent; + } + notifIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + final Notification.Builder builder = new Notification.Builder(context) + .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb) + .setContentTitle(context.getString(R.string.bugreport_finished_title)) + .setTicker(context.getString(R.string.bugreport_finished_title)) + .setContentText(context.getString(R.string.bugreport_finished_text)) + .setContentIntent(PendingIntent.getActivity( + context, 0, notifIntent, PendingIntent.FLAG_CANCEL_CURRENT)) + .setAutoCancel(true) + .setLocalOnly(true) + .setColor(context.getColor( + com.android.internal.R.color.system_notification_accent_color)); + + NotificationManager.from(context).notify(TAG, 0, builder.build()); + } + + /** + * Sends a zipped bugreport notification. + */ + private static void sendZippedBugreportNotification(final Context context, + final File bugreportFile, final File screenshotFile) { + new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(Void... params) { + File zippedFile = zipBugreport(bugreportFile); + sendBugreportNotification(context, zippedFile, screenshotFile); + return null; + } + }.execute(); + } + + /** + * Zips a bugreport file, returning the path to the new file (or to the + * original in case of failure). + */ + private static File zipBugreport(File bugreportFile) { + String bugreportPath = bugreportFile.getAbsolutePath(); + String zippedPath = bugreportPath.replace(".txt", ".zip"); + Log.v(TAG, "zipping " + bugreportPath + " as " + zippedPath); + File bugreportZippedFile = new File(zippedPath); + try (InputStream is = new FileInputStream(bugreportFile); + ZipOutputStream zos = new ZipOutputStream( + new BufferedOutputStream(new FileOutputStream(bugreportZippedFile)))) { + ZipEntry entry = new ZipEntry("bugreport.txt"); + zos.putNextEntry(entry); + int totalBytes = Streams.copy(is, zos); + Log.v(TAG, "size of original bugreport: " + totalBytes + " bytes"); + zos.closeEntry(); + // Delete old file; + boolean deleted = bugreportFile.delete(); + if (deleted) { + Log.v(TAG, "deleted original bugreport (" + bugreportPath + ")"); + } else { + Log.e(TAG, "could not delete original bugreport (" + bugreportPath + ")"); + } + return bugreportZippedFile; + } catch (IOException e) { + Log.e(TAG, "exception zipping file " + zippedPath, e); + return bugreportFile; // Return original. + } + } + + /** * Find the best matching {@link Account} based on build properties. */ private static Account findSendToAccount(Context context) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index e3b1b9f..5ac436a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -1180,7 +1180,9 @@ public class NotificationPanelView extends PanelView implements } else if (statusBarState == StatusBarState.KEYGUARD || statusBarState == StatusBarState.SHADE_LOCKED) { mKeyguardBottomArea.animate().cancel(); - mKeyguardBottomArea.setVisibility(View.VISIBLE); + if (!mDozing) { + mKeyguardBottomArea.setVisibility(View.VISIBLE); + } mKeyguardBottomArea.setAlpha(1f); } else { mKeyguardBottomArea.animate().cancel(); @@ -1717,7 +1719,8 @@ public class NotificationPanelView extends PanelView implements float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2); mKeyguardStatusBar.setAlpha(Math.min(getKeyguardContentsAlpha(), alphaQsExpansion) * mKeyguardStatusBarAnimateAlpha); - mKeyguardStatusBar.setVisibility(mKeyguardStatusBar.getAlpha() != 0f ? VISIBLE : INVISIBLE); + mKeyguardStatusBar.setVisibility(mKeyguardStatusBar.getAlpha() != 0f + && !mDozing ? VISIBLE : INVISIBLE); setQsTranslation(mQsExpansionHeight); } diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java index 05ee9c2..d360875 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java +++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java @@ -53,6 +53,7 @@ public class StorageNotification extends SystemUI { private static final int MOVE_ID = 0x534d4f56; // SMOV private static final String ACTION_SNOOZE_VOLUME = "com.android.systemui.action.SNOOZE_VOLUME"; + private static final String ACTION_FINISH_WIZARD = "com.android.systemui.action.FINISH_WIZARD"; // TODO: delay some notifications to avoid bumpy fast operations @@ -107,6 +108,15 @@ public class StorageNotification extends SystemUI { } }; + private final BroadcastReceiver mFinishReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + // When finishing the adoption wizard, clean up any notifications + // for moving primary storage + mNotificationManager.cancelAsUser(null, MOVE_ID, UserHandle.ALL); + } + }; + private final MoveCallback mMoveCallback = new MoveCallback() { @Override public void onCreated(int moveId, Bundle extras) { @@ -146,6 +156,8 @@ public class StorageNotification extends SystemUI { mContext.registerReceiver(mSnoozeReceiver, new IntentFilter(ACTION_SNOOZE_VOLUME), android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null); + mContext.registerReceiver(mFinishReceiver, new IntentFilter(ACTION_FINISH_WIZARD), + android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, null); // Kick current state into place final List<DiskInfo> disks = mStorageManager.getDisks(); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index f645764..82399da 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -960,44 +960,6 @@ public class ConnectivityService extends IConnectivityManager.Stub return nai != null ? nai.network : null; } - /** - * Find the first Provisioning network. - * - * @return NetworkInfo or null if none. - */ - private NetworkInfo getProvisioningNetworkInfo() { - enforceAccessPermission(); - - // Find the first Provisioning Network - NetworkInfo provNi = null; - for (NetworkInfo ni : getAllNetworkInfo()) { - if (ni.isConnectedToProvisioningNetwork()) { - provNi = ni; - break; - } - } - if (DBG) log("getProvisioningNetworkInfo: X provNi=" + provNi); - return provNi; - } - - /** - * Find the first Provisioning network or the ActiveDefaultNetwork - * if there is no Provisioning network - * - * @return NetworkInfo or null if none. - */ - @Override - public NetworkInfo getProvisioningOrActiveNetworkInfo() { - enforceAccessPermission(); - - NetworkInfo provNi = getProvisioningNetworkInfo(); - if (provNi == null) { - provNi = getActiveNetworkInfo(); - } - if (DBG) log("getProvisioningOrActiveNetworkInfo: X provNi=" + provNi); - return provNi; - } - public NetworkInfo getActiveNetworkInfoUnfiltered() { enforceAccessPermission(); final int uid = Binder.getCallingUid(); @@ -1567,14 +1529,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } }; - /** @hide */ - @Override - public void captivePortalCheckCompleted(NetworkInfo info, boolean isCaptivePortal) { - enforceConnectivityInternalPermission(); - if (DBG) log("captivePortalCheckCompleted: ni=" + info + " captive=" + isCaptivePortal); -// mNetTrackers[info.getType()].captivePortalCheckCompleted(isCaptivePortal); - } - /** * Setup data activity tracking for the given network. * @@ -3357,7 +3311,6 @@ public class ConnectivityService extends IConnectivityManager.Stub * <?xml version="1.0" encoding="utf-8"?> * <provisioningUrls> * <provisioningUrl mcc="310" mnc="4">http://myserver.com/foo?mdn=%3$s&iccid=%1$s&imei=%2$s</provisioningUrl> - * <redirectedUrl mcc="310" mnc="4">http://www.google.com</redirectedUrl> * </provisioningUrls> */ private static final String PROVISIONING_URL_PATH = @@ -3368,33 +3321,15 @@ public class ConnectivityService extends IConnectivityManager.Stub private static final String TAG_PROVISIONING_URLS = "provisioningUrls"; /** XML tag for individual url */ private static final String TAG_PROVISIONING_URL = "provisioningUrl"; - /** XML tag for redirected url */ - private static final String TAG_REDIRECTED_URL = "redirectedUrl"; /** XML attribute for mcc */ private static final String ATTR_MCC = "mcc"; /** XML attribute for mnc */ private static final String ATTR_MNC = "mnc"; - private static final int REDIRECTED_PROVISIONING = 1; - private static final int PROVISIONING = 2; - - private String getProvisioningUrlBaseFromFile(int type) { + private String getProvisioningUrlBaseFromFile() { FileReader fileReader = null; XmlPullParser parser = null; Configuration config = mContext.getResources().getConfiguration(); - String tagType; - - switch (type) { - case PROVISIONING: - tagType = TAG_PROVISIONING_URL; - break; - case REDIRECTED_PROVISIONING: - tagType = TAG_REDIRECTED_URL; - break; - default: - throw new RuntimeException("getProvisioningUrlBaseFromFile: Unexpected parameter " + - type); - } try { fileReader = new FileReader(mProvisioningUrlFile); @@ -3408,7 +3343,7 @@ public class ConnectivityService extends IConnectivityManager.Stub String element = parser.getName(); if (element == null) break; - if (element.equals(tagType)) { + if (element.equals(TAG_PROVISIONING_URL)) { String mcc = parser.getAttributeValue(null, ATTR_MCC); try { if (mcc != null && Integer.parseInt(mcc) == config.mcc) { @@ -3443,19 +3378,9 @@ public class ConnectivityService extends IConnectivityManager.Stub } @Override - public String getMobileRedirectedProvisioningUrl() { - enforceConnectivityInternalPermission(); - String url = getProvisioningUrlBaseFromFile(REDIRECTED_PROVISIONING); - if (TextUtils.isEmpty(url)) { - url = mContext.getResources().getString(R.string.mobile_redirected_provisioning_url); - } - return url; - } - - @Override public String getMobileProvisioningUrl() { enforceConnectivityInternalPermission(); - String url = getProvisioningUrlBaseFromFile(PROVISIONING); + String url = getProvisioningUrlBaseFromFile(); if (TextUtils.isEmpty(url)) { url = mContext.getResources().getString(R.string.mobile_provisioning_url); log("getMobileProvisioningUrl: mobile_provisioining_url from resource =" + url); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index e9b9767..667abb6 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -31,7 +31,6 @@ import static com.android.server.am.ActivityManagerDebugConfig.*; import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; import static com.android.server.am.TaskRecord.INVALID_TASK_ID; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK; -import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE; import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; @@ -10338,11 +10337,12 @@ public final class ActivityManagerService extends ActivityManagerNative void startRunningVoiceLocked(IVoiceInteractionSession session, int targetUid) { mVoiceWakeLock.setWorkSource(new WorkSource(targetUid)); if (mRunningVoice == null || mRunningVoice.asBinder() != session.asBinder()) { - if (mRunningVoice == null) { + boolean wasRunningVoice = mRunningVoice != null; + mRunningVoice = session; + if (!wasRunningVoice) { mVoiceWakeLock.acquire(); updateSleepIfNeededLocked(); } - mRunningVoice = session; } } @@ -11495,7 +11495,7 @@ public final class ActivityManagerService extends ActivityManagerNative for (int i=0; i<ris.size(); i++) { ActivityInfo ai = ris.get(i).activityInfo; ComponentName comp = new ComponentName(ai.packageName, ai.name); - if (false && lastDoneReceivers.contains(comp)) { + if (lastDoneReceivers.contains(comp)) { // We already did the pre boot receiver for this app with the current // platform version, so don't do it again... ris.remove(i); @@ -18595,29 +18595,24 @@ public final class ActivityManagerService extends ActivityManagerNative return; } boolean isInteraction; - if (!mSleeping) { - isInteraction = app.curProcState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + // To avoid some abuse patterns, we are going to be careful about what we consider + // to be an app interaction. Being the top activity doesn't count while the display + // is sleeping, nor do short foreground services. + if (app.curProcState <= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE) { + isInteraction = true; app.fgInteractionTime = 0; - } else { - // If the display is off, we are going to be more restrictive about what we consider - // to be an app interaction. Being the top activity doesn't count, nor do generally - // foreground services. - if (app.curProcState <= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE) { - isInteraction = true; - app.fgInteractionTime = 0; - } else if (app.curProcState <= ActivityManager.PROCESS_STATE_TOP_SLEEPING) { - final long now = SystemClock.elapsedRealtime(); - if (app.fgInteractionTime == 0) { - app.fgInteractionTime = now; - isInteraction = false; - } else { - isInteraction = now > app.fgInteractionTime + SERVICE_USAGE_INTERACTION_TIME; - } + } else if (app.curProcState <= ActivityManager.PROCESS_STATE_TOP_SLEEPING) { + final long now = SystemClock.elapsedRealtime(); + if (app.fgInteractionTime == 0) { + app.fgInteractionTime = now; + isInteraction = false; } else { - isInteraction = app.curProcState - <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; - app.fgInteractionTime = 0; + isInteraction = now > app.fgInteractionTime + SERVICE_USAGE_INTERACTION_TIME; } + } else { + isInteraction = app.curProcState + <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + app.fgInteractionTime = 0; } if (isInteraction && !app.reportedInteraction) { String[] packages = app.getPackageList(); diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index f222dba..2eb8797 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -801,7 +801,7 @@ public class SyncManager { for (String authority : syncableAuthorities) { int isSyncable = getIsSyncable(account.account, account.userId, authority); - if (isSyncable == 0) { + if (isSyncable == AuthorityInfo.NOT_SYNCABLE) { continue; } final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo; @@ -813,8 +813,9 @@ public class SyncManager { final boolean allowParallelSyncs = syncAdapterInfo.type.allowParallelSyncs(); final boolean isAlwaysSyncable = syncAdapterInfo.type.isAlwaysSyncable(); if (isSyncable < 0 && isAlwaysSyncable) { - mSyncStorageEngine.setIsSyncable(account.account, account.userId, authority, 1); - isSyncable = 1; + mSyncStorageEngine.setIsSyncable( + account.account, account.userId, authority, AuthorityInfo.SYNCABLE); + isSyncable = AuthorityInfo.SYNCABLE; } if (onlyThoseWithUnkownSyncableState && isSyncable >= 0) { continue; diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java index d68b615..cca0c16 100644 --- a/services/core/java/com/android/server/content/SyncStorageEngine.java +++ b/services/core/java/com/android/server/content/SyncStorageEngine.java @@ -301,6 +301,30 @@ public class SyncStorageEngine extends Handler { } public static class AuthorityInfo { + // Legal values of getIsSyncable + /** + * Default state for a newly installed adapter. An uninitialized adapter will receive an + * initialization sync which are governed by a different set of rules to that of regular + * syncs. + */ + public static final int NOT_INITIALIZED = -1; + /** + * The adapter will not receive any syncs. This is behaviourally equivalent to + * setSyncAutomatically -> false. However setSyncAutomatically is surfaced to the user + * while this is generally meant to be controlled by the developer. + */ + public static final int NOT_SYNCABLE = 0; + /** + * The adapter is initialized and functioning. This is the normal state for an adapter. + */ + public static final int SYNCABLE = 1; + /** + * The adapter is syncable but still requires an initialization sync. For example an adapter + * than has been restored from a previous device will be in this state. Not meant for + * external use. + */ + public static final int SYNCABLE_NOT_INITIALIZED = 2; + final EndPoint target; final int ident; boolean enabled; @@ -349,12 +373,11 @@ public class SyncStorageEngine extends Handler { } private void defaultInitialisation() { - syncable = -1; // default to "unknown" + syncable = NOT_INITIALIZED; // default to "unknown" backoffTime = -1; // if < 0 then we aren't in backoff mode backoffDelay = -1; // if < 0 then we aren't in backoff mode PeriodicSync defaultSync; - // Old version is one sync a day. Empty bundle gets replaced by any addPeriodicSync() - // call. + // Old version is one sync a day. if (target.target_provider) { defaultSync = new PeriodicSync(target.account, target.provider, @@ -663,6 +686,12 @@ public class SyncStorageEngine extends Handler { } return; } + // If the adapter was syncable but missing its initialization sync, set it to + // uninitialized now. This is to give it a chance to run any one-time initialization + // logic. + if (sync && authority.syncable == AuthorityInfo.SYNCABLE_NOT_INITIALIZED) { + authority.syncable = AuthorityInfo.NOT_INITIALIZED; + } authority.enabled = sync; writeAccountInfoLocked(); } @@ -682,7 +711,7 @@ public class SyncStorageEngine extends Handler { new EndPoint(account, providerName, userId), "get authority syncable"); if (authority == null) { - return -1; + return AuthorityInfo.NOT_INITIALIZED; } return authority.syncable; } @@ -696,7 +725,7 @@ public class SyncStorageEngine extends Handler { return authorityInfo.syncable; } } - return -1; + return AuthorityInfo.NOT_INITIALIZED; } } @@ -720,7 +749,8 @@ public class SyncStorageEngine extends Handler { } public void setIsTargetServiceActive(ComponentName cname, int userId, boolean active) { - setSyncableStateForEndPoint(new EndPoint(cname, userId), active ? 1 : 0); + setSyncableStateForEndPoint(new EndPoint(cname, userId), active ? + AuthorityInfo.SYNCABLE : AuthorityInfo.NOT_SYNCABLE); } /** @@ -733,10 +763,8 @@ public class SyncStorageEngine extends Handler { AuthorityInfo aInfo; synchronized (mAuthorities) { aInfo = getOrCreateAuthorityLocked(target, -1, false); - if (syncable > 1) { - syncable = 1; - } else if (syncable < -1) { - syncable = -1; + if (syncable < AuthorityInfo.NOT_INITIALIZED) { + syncable = AuthorityInfo.NOT_INITIALIZED; } if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.d(TAG, "setIsSyncable: " + aInfo.toString() + " -> " + syncable); @@ -750,7 +778,7 @@ public class SyncStorageEngine extends Handler { aInfo.syncable = syncable; writeAccountInfoLocked(); } - if (syncable > 0) { + if (syncable == AuthorityInfo.SYNCABLE) { requestSync(aInfo, SyncOperation.REASON_IS_SYNCABLE, new Bundle()); } reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS); @@ -2012,7 +2040,7 @@ public class SyncStorageEngine extends Handler { int userId = user == null ? 0 : Integer.parseInt(user); if (accountType == null && packageName == null) { accountType = "com.google"; - syncable = "unknown"; + syncable = String.valueOf(AuthorityInfo.NOT_INITIALIZED); } authority = mAuthorities.get(id); if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) { @@ -2052,11 +2080,19 @@ public class SyncStorageEngine extends Handler { } if (authority != null) { authority.enabled = enabled == null || Boolean.parseBoolean(enabled); - if ("unknown".equals(syncable)) { - authority.syncable = -1; - } else { - authority.syncable = - (syncable == null || Boolean.parseBoolean(syncable)) ? 1 : 0; + try { + authority.syncable = (syncable == null) ? + AuthorityInfo.NOT_INITIALIZED : Integer.parseInt(syncable); + } catch (NumberFormatException e) { + // On L we stored this as {"unknown", "true", "false"} so fall back to this + // format. + if ("unknown".equals(syncable)) { + authority.syncable = AuthorityInfo.NOT_INITIALIZED; + } else { + authority.syncable = Boolean.parseBoolean(syncable) ? + AuthorityInfo.SYNCABLE : AuthorityInfo.NOT_SYNCABLE; + } + } } else { Log.w(TAG, "Failure adding authority: account=" @@ -2190,11 +2226,7 @@ public class SyncStorageEngine extends Handler { out.attribute(null, "package", info.service.getPackageName()); out.attribute(null, "class", info.service.getClassName()); } - if (authority.syncable < 0) { - out.attribute(null, "syncable", "unknown"); - } else { - out.attribute(null, "syncable", Boolean.toString(authority.syncable != 0)); - } + out.attribute(null, "syncable", Integer.toString(authority.syncable)); for (PeriodicSync periodicSync : authority.periodicSyncs) { out.startTag(null, "periodicSync"); out.attribute(null, "period", Long.toString(periodicSync.period)); diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java index 7f0be57..c52a1c1 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -33,6 +33,7 @@ import android.os.MessageQueue; import android.os.RemoteException; import android.os.SELinux; import android.os.ServiceManager; +import android.os.UserHandle; import android.util.Slog; import com.android.server.SystemService; @@ -389,12 +390,12 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe } } - public List<Fingerprint> getEnrolledFingerprints(int groupId) { - return mFingerprintUtils.getFingerprintsForUser(mContext, groupId); + public List<Fingerprint> getEnrolledFingerprints(int userId) { + return mFingerprintUtils.getFingerprintsForUser(mContext, userId); } - public boolean hasEnrolledFingerprints(int groupId) { - return mFingerprintUtils.getFingerprintsForUser(mContext, groupId).size() > 0; + public boolean hasEnrolledFingerprints(int userId) { + return mFingerprintUtils.getFingerprintsForUser(mContext, userId).size() > 0; } boolean hasPermission(String permission) { @@ -598,6 +599,15 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe public void enroll(final IBinder token, final byte[] cryptoToken, final int groupId, final IFingerprintServiceReceiver receiver, final int flags) { checkPermission(MANAGE_FINGERPRINT); + final int limit = mContext.getResources().getInteger( + com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser); + final int callingUid = Binder.getCallingUid(); + final int userId = UserHandle.getUserId(callingUid); + final int enrolled = FingerprintService.this.getEnrolledFingerprints(userId).size(); + if (enrolled >= limit) { + Slog.w(TAG, "Too many fingerprints registered"); + return; + } final byte [] cryptoClone = Arrays.copyOf(cryptoToken, cryptoToken.length); final boolean restricted = isRestricted(); @@ -689,11 +699,11 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe } @Override // Binder call - public List<Fingerprint> getEnrolledFingerprints(int groupId, String opPackageName) { + public List<Fingerprint> getEnrolledFingerprints(int userId, String opPackageName) { if (!canUseFingerprint(opPackageName)) { return Collections.emptyList(); } - return FingerprintService.this.getEnrolledFingerprints(groupId); + return FingerprintService.this.getEnrolledFingerprints(userId); } @Override // Binder call diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java index 77b800e..7999321 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -246,6 +246,8 @@ abstract class HdmiCecLocalDevice { return handleRequestActiveSource(message); case Constants.MESSAGE_GET_MENU_LANGUAGE: return handleGetMenuLanguage(message); + case Constants.MESSAGE_SET_MENU_LANGUAGE: + return handleSetMenuLanguage(message); case Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS: return handleGivePhysicalAddress(); case Constants.MESSAGE_GIVE_OSD_NAME: @@ -377,6 +379,14 @@ abstract class HdmiCecLocalDevice { } @ServiceThreadOnly + protected boolean handleSetMenuLanguage(HdmiCecMessage message) { + assertRunOnServiceThread(); + Slog.w(TAG, "Only Playback device can handle <Set Menu Language>:" + message.toString()); + // 'return false' will cause to reply with <Feature Abort>. + return false; + } + + @ServiceThreadOnly protected boolean handleGiveOsdName(HdmiCecMessage message) { assertRunOnServiceThread(); // Note that since this method is called after logical address allocation is done, diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java index 30a9b43..493471b 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java @@ -26,9 +26,14 @@ import android.os.SystemProperties; import android.provider.Settings.Global; import android.util.Slog; +import com.android.internal.app.LocalePicker; +import com.android.internal.app.LocalePicker.LocaleInfo; import com.android.internal.util.IndentingPrintWriter; import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly; +import java.io.UnsupportedEncodingException; +import java.util.List; + /** * Represent a logical device of type Playback residing in Android system. */ @@ -306,6 +311,35 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice { return true; // Broadcast message. } + @ServiceThreadOnly + protected boolean handleSetMenuLanguage(HdmiCecMessage message) { + assertRunOnServiceThread(); + + try { + String iso3Language = new String(message.getParams(), 0, 3, "US-ASCII"); + + // Don't use Locale.getAvailableLocales() since it returns a locale + // which is not available on Settings. + final List<LocaleInfo> localeInfos = LocalePicker.getAllAssetLocales( + mService.getContext(), false); + for (LocaleInfo localeInfo : localeInfos) { + if (localeInfo.getLocale().getISO3Language().equals(iso3Language)) { + // WARNING: CEC adopts ISO/FDIS-2 for language code, while Android requires + // additional country variant to pinpoint the locale. This keeps the right + // locale from being chosen. 'eng' in the CEC command, for instance, + // will always be mapped to en-AU among other variants like en-US, en-GB, + // an en-IN, which may not be the expected one. + LocalePicker.updateLocale(localeInfo.getLocale()); + return true; + } + } + Slog.w(TAG, "Can't handle <Set Menu Language> of " + iso3Language); + return false; + } catch (UnsupportedEncodingException e) { + return false; + } + } + @Override @ServiceThreadOnly protected void sendStandby(int deviceId) { diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java index 10f1696..4af7d4e 100644 --- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java +++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java @@ -51,7 +51,7 @@ import java.util.concurrent.TimeUnit; public class ValidateNotificationPeople implements NotificationSignalExtractor { // Using a shorter log tag since setprop has a limit of 32chars on variable name. private static final String TAG = "ValidateNoPeople"; - private static final boolean INFO = true; + private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final boolean ENABLE_PEOPLE_VALIDATOR = true; @@ -100,7 +100,7 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { public void onChange(boolean selfChange, Uri uri, int userId) { super.onChange(selfChange, uri, userId); if (DEBUG || mEvictionCount % 100 == 0) { - if (INFO) Slog.i(TAG, "mEvictionCount: " + mEvictionCount); + if (VERBOSE) Slog.i(TAG, "mEvictionCount: " + mEvictionCount); } mPeopleCache.evictAll(); mEvictionCount++; @@ -113,20 +113,20 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { public RankingReconsideration process(NotificationRecord record) { if (!mEnabled) { - if (INFO) Slog.i(TAG, "disabled"); + if (VERBOSE) Slog.i(TAG, "disabled"); return null; } if (record == null || record.getNotification() == null) { - if (INFO) Slog.i(TAG, "skipping empty notification"); + if (VERBOSE) Slog.i(TAG, "skipping empty notification"); return null; } if (record.getUserId() == UserHandle.USER_ALL) { - if (INFO) Slog.i(TAG, "skipping global notification"); + if (VERBOSE) Slog.i(TAG, "skipping global notification"); return null; } Context context = getContextAsUser(record.getUser()); if (context == null) { - if (INFO) Slog.i(TAG, "skipping notification that lacks a context"); + if (VERBOSE) Slog.i(TAG, "skipping notification that lacks a context"); return null; } return validatePeople(context, record); @@ -220,7 +220,7 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { return null; } - if (INFO) Slog.i(TAG, "Validating: " + key + " for " + context.getUserId()); + if (VERBOSE) Slog.i(TAG, "Validating: " + key + " for " + context.getUserId()); final LinkedList<String> pendingLookups = new LinkedList<String>(); for (int personIdx = 0; personIdx < people.length && personIdx < MAX_PEOPLE; personIdx++) { final String handle = people[personIdx]; @@ -244,7 +244,7 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { affinityOut[0] = affinity; if (pendingLookups.isEmpty()) { - if (INFO) Slog.i(TAG, "final affinity: " + affinity); + if (VERBOSE) Slog.i(TAG, "final affinity: " + affinity); if (affinity != NONE) MetricsLogger.count(mBaseContext, "note_with_people", 1); return null; } @@ -422,7 +422,7 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { @Override public void work() { - if (INFO) Slog.i(TAG, "Executing: validation for: " + mKey); + if (VERBOSE) Slog.i(TAG, "Executing: validation for: " + mKey); long timeStartMs = System.currentTimeMillis(); for (final String handle: mPendingLookups) { LookupResult lookupResult = null; @@ -463,7 +463,7 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { public void applyChangesLocked(NotificationRecord operand) { float affinityBound = operand.getContactAffinity(); operand.setContactAffinity(Math.max(mContactAffinity, affinityBound)); - if (INFO) Slog.i(TAG, "final affinity: " + operand.getContactAffinity()); + if (VERBOSE) Slog.i(TAG, "final affinity: " + operand.getContactAffinity()); } public float getContactAffinity() { diff --git a/services/core/java/com/android/server/pm/KeySetManagerService.java b/services/core/java/com/android/server/pm/KeySetManagerService.java index 1ee07a5..0de0c92 100644 --- a/services/core/java/com/android/server/pm/KeySetManagerService.java +++ b/services/core/java/com/android/server/pm/KeySetManagerService.java @@ -16,6 +16,9 @@ package com.android.server.pm; +import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK; + +import com.android.internal.util.Preconditions; import android.content.pm.PackageParser; import android.util.ArrayMap; import android.util.ArraySet; @@ -98,6 +101,7 @@ public class KeySetManagerService { mRefCount++; return; } + public long decrRefCountLPw() { mRefCount--; return mRefCount; @@ -168,25 +172,82 @@ public class KeySetManagerService { } /** + * addScannedPackageLPw directly modifies the package metadata in pm.Settings + * at a point of no-return. We need to make sure that the scanned package does + * not contain bad keyset meta-data that could generate an incorrect + * PackageSetting. Verify that there is a signing keyset, there are no issues + * with null objects, and the upgrade and defined keysets match. + * + * Returns true if the package can safely be added to the keyset metadata. + */ + public void assertScannedPackageValid(PackageParser.Package pkg) + throws PackageManagerException { + if (pkg == null || pkg.packageName == null) { + throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, + "Passed invalid package to keyset validation."); + } + ArraySet<PublicKey> signingKeys = pkg.mSigningKeys; + if (signingKeys == null || !(signingKeys.size() > 0) || signingKeys.contains(null)) { + throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, + "Package has invalid signing-key-set."); + } + ArrayMap<String, ArraySet<PublicKey>> definedMapping = pkg.mKeySetMapping; + if (definedMapping != null) { + if (definedMapping.containsKey(null) || definedMapping.containsValue(null)) { + throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, + "Package has null defined key set."); + } + int defMapSize = definedMapping.size(); + for (int i = 0; i < defMapSize; i++) { + if (!(definedMapping.valueAt(i).size() > 0) + || definedMapping.valueAt(i).contains(null)) { + throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, + "Package has null/no public keys for defined key-sets."); + } + } + } + ArraySet<String> upgradeAliases = pkg.mUpgradeKeySets; + if (upgradeAliases != null) { + if (definedMapping == null || !(definedMapping.keySet().containsAll(upgradeAliases))) { + throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, + "Package has upgrade-key-sets without corresponding definitions."); + } + } + } + + public void addScannedPackageLPw(PackageParser.Package pkg) { + Preconditions.checkNotNull(pkg, "Attempted to add null pkg to ksms."); + Preconditions.checkNotNull(pkg.packageName, "Attempted to add null pkg to ksms."); + PackageSetting ps = mPackages.get(pkg.packageName); + Preconditions.checkNotNull(ps, "pkg: " + pkg.packageName + + "does not have a corresponding entry in mPackages."); + addSigningKeySetToPackageLPw(ps, pkg.mSigningKeys); + if (pkg.mKeySetMapping != null) { + addDefinedKeySetsToPackageLPw(ps, pkg.mKeySetMapping); + if (pkg.mUpgradeKeySets != null) { + addUpgradeKeySetsToPackageLPw(ps, pkg.mUpgradeKeySets); + } + } + } + + /** * Informs the system that the given package was signed by the provided KeySet. */ - public void addSigningKeySetToPackageLPw(String packageName, + void addSigningKeySetToPackageLPw(PackageSetting pkg, ArraySet<PublicKey> signingKeys) { /* check existing keyset for reuse or removal */ - PackageSetting pkg = mPackages.get(packageName); long signingKeySetId = pkg.keySetData.getProperSigningKeySet(); if (signingKeySetId != PackageKeySetData.KEYSET_UNASSIGNED) { ArraySet<PublicKey> existingKeys = getPublicKeysFromKeySetLPr(signingKeySetId); - if (existingKeys.equals(signingKeys)) { + if (existingKeys != null && existingKeys.equals(signingKeys)) { /* no change in signing keys, leave PackageSetting alone */ return; } else { /* old keyset no longer valid, remove ref */ - KeySetHandle ksh = mKeySets.get(signingKeySetId); decrementKeySetLPw(signingKeySetId); } } @@ -212,13 +273,12 @@ public class KeySetManagerService { return KEYSET_NOT_FOUND; } - /* + /** * Inform the system that the given package defines the given KeySets. * Remove any KeySets the package no longer defines. */ - public void addDefinedKeySetsToPackageLPw(String packageName, + void addDefinedKeySetsToPackageLPw(PackageSetting pkg, ArrayMap<String, ArraySet<PublicKey>> definedMapping) { - PackageSetting pkg = mPackages.get(packageName); ArrayMap<String, Long> prevDefinedKeySets = pkg.keySetData.getAliases(); /* add all of the newly defined KeySets */ @@ -227,7 +287,7 @@ public class KeySetManagerService { for (int i = 0; i < defMapSize; i++) { String alias = definedMapping.keyAt(i); ArraySet<PublicKey> pubKeys = definedMapping.valueAt(i); - if (alias != null && pubKeys != null && pubKeys.size() > 0) { + if (alias != null && pubKeys != null || pubKeys.size() > 0) { KeySetHandle ks = addKeySetLPw(pubKeys); newKeySetAliases.put(alias, ks.getId()); } @@ -250,9 +310,8 @@ public class KeySetManagerService { * alias in its manifest to be an upgradeKeySet. This must be called * after all of the defined KeySets have been added. */ - public void addUpgradeKeySetsToPackageLPw(String packageName, - ArraySet<String> upgradeAliases) { - PackageSetting pkg = mPackages.get(packageName); + void addUpgradeKeySetsToPackageLPw(PackageSetting pkg, + ArraySet<String> upgradeAliases) { final int uaSize = upgradeAliases.size(); for (int i = 0; i < uaSize; i++) { pkg.keySetData.addUpgradeKeySet(upgradeAliases.valueAt(i)); @@ -290,11 +349,11 @@ public class KeySetManagerService { * identify a {@link KeySetHandle}. */ public ArraySet<PublicKey> getPublicKeysFromKeySetLPr(long id) { - if(mKeySetMapping.get(id) == null) { + ArraySet<Long> pkIds = mKeySetMapping.get(id); + if (pkIds == null) { return null; } ArraySet<PublicKey> mPubKeys = new ArraySet<PublicKey>(); - ArraySet<Long> pkIds = mKeySetMapping.get(id); final int pkSize = pkIds.size(); for (int i = 0; i < pkSize; i++) { mPubKeys.add(mPublicKeys.get(pkIds.valueAt(i)).getKey()); @@ -376,6 +435,10 @@ public class KeySetManagerService { */ private void decrementKeySetLPw(long id) { KeySetHandle ks = mKeySets.get(id); + if (ks == null) { + /* nothing to do */ + return; + } if (ks.decrRefCountLPw() <= 0) { ArraySet<Long> pubKeys = mKeySetMapping.get(id); final int pkSize = pubKeys.size(); @@ -385,7 +448,6 @@ public class KeySetManagerService { mKeySets.delete(id); mKeySetMapping.delete(id); } - return; } /* @@ -394,16 +456,20 @@ public class KeySetManagerService { */ private void decrementPublicKeyLPw(long id) { PublicKeyHandle pk = mPublicKeys.get(id); + if (pk == null) { + /* nothing to do */ + return; + } if (pk.decrRefCountLPw() <= 0) { mPublicKeys.delete(id); } - return; } /** * Adds the given PublicKey to the system, deduping as it goes. */ private long addPublicKeyLPw(PublicKey key) { + Preconditions.checkNotNull(key, "Cannot add null public key!"); long id = getIdForPublicKeyLPr(key); if (id != PUBLIC_KEY_NOT_FOUND) { @@ -473,6 +539,8 @@ public class KeySetManagerService { /* remove refs from common keysets and public keys */ PackageSetting pkg = mPackages.get(packageName); + Preconditions.checkNotNull(pkg, "pkg name: " + packageName + + "does not have a corresponding entry in mPackages."); long signingKeySetId = pkg.keySetData.getProperSigningKeySet(); decrementKeySetLPw(signingKeySetId); ArrayMap<String, Long> definedKeySets = pkg.keySetData.getAliases(); @@ -715,16 +783,36 @@ public class KeySetManagerService { final int numRefCounts = keySetRefCounts.size(); for (int i = 0; i < numRefCounts; i++) { KeySetHandle ks = mKeySets.get(keySetRefCounts.keyAt(i)); + if (ks == null) { + /* something went terribly wrong and we have references to a non-existent key-set */ + Slog.wtf(TAG, "Encountered non-existent key-set reference when reading settings"); + continue; + } ks.setRefCountLPw(keySetRefCounts.valueAt(i)); } + /* + * In case something went terribly wrong and we have keysets with no associated packges + * that refer to them, record the orphaned keyset ids, and remove them using + * decrementKeySetLPw() after all keyset references have been set so that the associtaed + * public keys have the appropriate references from all keysets. + */ + ArraySet<Long> orphanedKeySets = new ArraySet<Long>(); final int numKeySets = mKeySets.size(); for (int i = 0; i < numKeySets; i++) { + if (mKeySets.valueAt(i).getRefCountLPr() == 0) { + Slog.wtf(TAG, "Encountered key-set w/out package references when reading settings"); + orphanedKeySets.add(mKeySets.keyAt(i)); + } ArraySet<Long> pubKeys = mKeySetMapping.valueAt(i); final int pkSize = pubKeys.size(); for (int j = 0; j < pkSize; j++) { mPublicKeys.get(pubKeys.valueAt(j)).incrRefCountLPw(); } } + final int numOrphans = orphanedKeySets.size(); + for (int i = 0; i < numOrphans; i++) { + decrementKeySetLPw(orphanedKeySets.valueAt(i)); + } } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 548d93c..5b7dd70 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -5109,16 +5109,18 @@ public class PackageManagerService extends IPackageManager.Stub { && !isCompatSignatureUpdateNeeded(pkg) && !isRecoverSignatureUpdateNeeded(pkg)) { long mSigningKeySetId = ps.keySetData.getProperSigningKeySet(); + KeySetManagerService ksms = mSettings.mKeySetManagerService; + ArraySet<PublicKey> signingKs; + synchronized (mPackages) { + signingKs = ksms.getPublicKeysFromKeySetLPr(mSigningKeySetId); + } if (ps.signatures.mSignatures != null && ps.signatures.mSignatures.length != 0 - && mSigningKeySetId != PackageKeySetData.KEYSET_UNASSIGNED) { + && signingKs != null) { // Optimization: reuse the existing cached certificates // if the package appears to be unchanged. pkg.mSignatures = ps.signatures.mSignatures; - KeySetManagerService ksms = mSettings.mKeySetManagerService; - synchronized (mPackages) { - pkg.mSigningKeys = ksms.getPublicKeysFromKeySetLPr(mSigningKeySetId); - } + pkg.mSigningKeys = signingKs; return; } @@ -6590,6 +6592,10 @@ public class PackageManagerService extends IPackageManager.Stub { } } + // Make sure we're not adding any bogus keyset info + KeySetManagerService ksms = mSettings.mKeySetManagerService; + ksms.assertScannedPackageValid(pkg); + // writer synchronized (mPackages) { // We don't expect installation to fail beyond this point @@ -6626,20 +6632,7 @@ public class PackageManagerService extends IPackageManager.Stub { } // Add the package's KeySets to the global KeySetManagerService - KeySetManagerService ksms = mSettings.mKeySetManagerService; - try { - ksms.addSigningKeySetToPackageLPw(pkg.packageName, pkg.mSigningKeys); - if (pkg.mKeySetMapping != null) { - ksms.addDefinedKeySetsToPackageLPw(pkg.packageName, pkg.mKeySetMapping); - if (pkg.mUpgradeKeySets != null) { - ksms.addUpgradeKeySetsToPackageLPw(pkg.packageName, pkg.mUpgradeKeySets); - } - } - } catch (NullPointerException e) { - Slog.e(TAG, "Could not add KeySet to " + pkg.packageName, e); - } catch (IllegalArgumentException e) { - Slog.e(TAG, "Could not add KeySet to malformed package" + pkg.packageName, e); - } + ksms.addScannedPackageLPw(pkg); int N = pkg.providers.size(); StringBuilder r = null; @@ -11188,7 +11181,7 @@ public class PackageManagerService extends IPackageManager.Stub { KeySetManagerService ksms = mSettings.mKeySetManagerService; for (int i = 0; i < upgradeKeySets.length; i++) { Set<PublicKey> upgradeSet = ksms.getPublicKeysFromKeySetLPr(upgradeKeySets[i]); - if (newPkg.mSigningKeys.containsAll(upgradeSet)) { + if (upgradeSet != null && newPkg.mSigningKeys.containsAll(upgradeSet)) { return true; } } diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 095b7d7..4082ff3 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -966,6 +966,7 @@ public class UserManagerService extends IUserManager.Stub { writeBoolean(serializer, restrictions, UserManager.DISALLOW_ADJUST_VOLUME); writeBoolean(serializer, restrictions, UserManager.DISALLOW_OUTGOING_CALLS); writeBoolean(serializer, restrictions, UserManager.DISALLOW_SMS); + writeBoolean(serializer, restrictions, UserManager.DISALLOW_FUN); writeBoolean(serializer, restrictions, UserManager.DISALLOW_CREATE_WINDOWS); writeBoolean(serializer, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE); writeBoolean(serializer, restrictions, UserManager.DISALLOW_OUTGOING_BEAM); @@ -1096,6 +1097,7 @@ public class UserManagerService extends IUserManager.Stub { readBoolean(parser, restrictions, UserManager.DISALLOW_ADJUST_VOLUME); readBoolean(parser, restrictions, UserManager.DISALLOW_OUTGOING_CALLS); readBoolean(parser, restrictions, UserManager.DISALLOW_SMS); + readBoolean(parser, restrictions, UserManager.DISALLOW_FUN); readBoolean(parser, restrictions, UserManager.DISALLOW_CREATE_WINDOWS); readBoolean(parser, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE); readBoolean(parser, restrictions, UserManager.DISALLOW_OUTGOING_BEAM); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index ea66a04..f1f61f3 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -209,6 +209,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_UNMUTE_MICROPHONE); DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_ADJUST_VOLUME); DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_SMS); + DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_FUN); DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_SAFE_BOOT); } diff --git a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java index 2557974..7f9a0de 100644 --- a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java @@ -118,7 +118,7 @@ public class KeySetManagerServiceTest extends AndroidTestCase { ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys.add(keyA); - mKsms.addSigningKeySetToPackageLPw(ps.name, signingKeys); + mKsms.addSigningKeySetToPackageLPw(ps, signingKeys); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1)); @@ -145,10 +145,10 @@ public class KeySetManagerServiceTest extends AndroidTestCase { ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys.add(keyA); - mKsms.addSigningKeySetToPackageLPw(ps.name, signingKeys); + mKsms.addSigningKeySetToPackageLPw(ps, signingKeys); /* add again, to represent upgrade of package */ - mKsms.addSigningKeySetToPackageLPw(ps.name, signingKeys); + mKsms.addSigningKeySetToPackageLPw(ps, signingKeys); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1)); @@ -175,13 +175,13 @@ public class KeySetManagerServiceTest extends AndroidTestCase { ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys.add(keyA); - mKsms.addSigningKeySetToPackageLPw(ps.name, signingKeys); + mKsms.addSigningKeySetToPackageLPw(ps, signingKeys); /* now upgrade with new key */ PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); signingKeys.removeAt(0); signingKeys.add(keyB); - mKsms.addSigningKeySetToPackageLPw(ps.name, signingKeys); + mKsms.addSigningKeySetToPackageLPw(ps, signingKeys); assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2)); @@ -212,14 +212,14 @@ public class KeySetManagerServiceTest extends AndroidTestCase { ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys.add(keyA); - mKsms.addSigningKeySetToPackageLPw(ps1.name, signingKeys); - mKsms.addSigningKeySetToPackageLPw(ps2.name, signingKeys); + mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys); + mKsms.addSigningKeySetToPackageLPw(ps2, signingKeys); /* now upgrade with new key */ PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); signingKeys.removeAt(0); signingKeys.add(keyB); - mKsms.addSigningKeySetToPackageLPw(ps1.name, signingKeys); + mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2)); @@ -255,13 +255,13 @@ public class KeySetManagerServiceTest extends AndroidTestCase { ArraySet<PublicKey> signingKeys1 = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys1.add(keyA); - mKsms.addSigningKeySetToPackageLPw(ps1.name, signingKeys1); + mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys1); /* collect second signing key and add */ ArraySet<PublicKey> signingKeys2 = new ArraySet<PublicKey>(); PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); signingKeys2.add(keyB); - mKsms.addSigningKeySetToPackageLPw(ps2.name, signingKeys2); + mKsms.addSigningKeySetToPackageLPw(ps2, signingKeys2); /* verify first is unchanged */ assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1)); @@ -300,10 +300,10 @@ public class KeySetManagerServiceTest extends AndroidTestCase { ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys.add(keyA); - mKsms.addSigningKeySetToPackageLPw(ps1.name, signingKeys); + mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys); /* add again for second package */ - mKsms.addSigningKeySetToPackageLPw(ps2.name, signingKeys); + mKsms.addSigningKeySetToPackageLPw(ps2, signingKeys); assertEquals(2, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1)); @@ -333,12 +333,12 @@ public class KeySetManagerServiceTest extends AndroidTestCase { ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys.add(keyA); - mKsms.addSigningKeySetToPackageLPw(ps1.name, signingKeys); + mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys); /* give ps2 a superset (add keyB) */ PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); signingKeys.add(keyB); - mKsms.addSigningKeySetToPackageLPw(ps2.name, signingKeys); + mKsms.addSigningKeySetToPackageLPw(ps2, signingKeys); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2)); @@ -374,12 +374,12 @@ public class KeySetManagerServiceTest extends AndroidTestCase { ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys.add(keyA); - mKsms.addSigningKeySetToPackageLPw(ps.name, signingKeys); + mKsms.addSigningKeySetToPackageLPw(ps, signingKeys); /* now with additional key */ PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); signingKeys.add(keyB); - mKsms.addSigningKeySetToPackageLPw(ps.name, signingKeys); + mKsms.addSigningKeySetToPackageLPw(ps, signingKeys); assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2)); @@ -413,7 +413,7 @@ public class KeySetManagerServiceTest extends AndroidTestCase { PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); keys.add(keyA); definedKS.put("aliasA", keys); - mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS); + mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1)); @@ -441,7 +441,7 @@ public class KeySetManagerServiceTest extends AndroidTestCase { keys.add(keyA); definedKS.put("aliasA", keys); definedKS.put("aliasA2", keys); - mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS); + mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); assertEquals(2, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1)); @@ -470,7 +470,7 @@ public class KeySetManagerServiceTest extends AndroidTestCase { PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); keys.add(keyA); definedKS.put("aliasA", keys); - mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS); + mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); /* now upgrade to different defined key-set */ keys = new ArraySet<PublicKey>(); @@ -478,7 +478,7 @@ public class KeySetManagerServiceTest extends AndroidTestCase { keys.add(keyB); definedKS.remove("aliasA"); definedKS.put("aliasB", keys); - mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS); + mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1)); @@ -510,14 +510,14 @@ public class KeySetManagerServiceTest extends AndroidTestCase { PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); keys.add(keyA); definedKS.put("aliasA", keys); - mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS); + mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); /* now upgrade to different set w/same alias as before */ keys = new ArraySet<PublicKey>(); PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); keys.add(keyB); definedKS.put("aliasA", keys); - mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS); + mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1)); @@ -551,7 +551,7 @@ public class KeySetManagerServiceTest extends AndroidTestCase { keys2.add(keyB); definedKS.put("aliasA", keys1); definedKS.put("aliasB", keys2); - mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS); + mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); /* now upgrade to different set (B, C) */ keys1 = new ArraySet<PublicKey>(); @@ -559,7 +559,7 @@ public class KeySetManagerServiceTest extends AndroidTestCase { keys1.add(keyC); definedKS.remove("aliasA"); definedKS.put("aliasC", keys1); - mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS); + mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 3)); assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 3)); @@ -612,7 +612,7 @@ public class KeySetManagerServiceTest extends AndroidTestCase { PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); keys1.add(keyA); definedKS.put("aliasA", keys1); - mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS); + mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); /* now upgrade to different set */ ArraySet<PublicKey> keys2 = new ArraySet<PublicKey>(); @@ -620,12 +620,12 @@ public class KeySetManagerServiceTest extends AndroidTestCase { keys2.add(keyB); definedKS.remove("aliasA"); definedKS.put("aliasB", keys2); - mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS); + mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); /* upgrade back to original */ definedKS.remove("aliasB"); definedKS.put("aliasA", keys1); - mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS); + mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1)); assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 2)); @@ -655,10 +655,10 @@ public class KeySetManagerServiceTest extends AndroidTestCase { PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); keys.add(keyA); definedKS.put("aliasA", keys); - mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS); + mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); ArraySet<String> upgradeKS = new ArraySet<String>(); upgradeKS.add("aliasA"); - mKsms.addUpgradeKeySetsToPackageLPw(ps.name, upgradeKS); + mKsms.addUpgradeKeySetsToPackageLPw(ps, upgradeKS); assertEquals(1, ps.keySetData.getUpgradeKeySets().length); assertEquals(1, ps.keySetData.getUpgradeKeySets()[0]); @@ -677,11 +677,11 @@ public class KeySetManagerServiceTest extends AndroidTestCase { PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); keys.add(keyA); definedKS.put("aliasA", keys); - mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS); + mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); ArraySet<String> upgradeKS = new ArraySet<String>(); upgradeKS.add("aliasB"); try { - mKsms.addUpgradeKeySetsToPackageLPw(ps.name, upgradeKS); + mKsms.addUpgradeKeySetsToPackageLPw(ps, upgradeKS); } catch (IllegalArgumentException e) { /* should have been caught in packagemanager, so exception thrown */ @@ -704,17 +704,17 @@ public class KeySetManagerServiceTest extends AndroidTestCase { PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); keys.add(keyA); definedKS.put("aliasA", keys); - mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS); + mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); ArraySet<String> upgradeKS = new ArraySet<String>(); upgradeKS.add("aliasA"); - mKsms.addUpgradeKeySetsToPackageLPw(ps.name, upgradeKS); + mKsms.addUpgradeKeySetsToPackageLPw(ps, upgradeKS); keys = new ArraySet<PublicKey>(); PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); keys.add(keyB); definedKS.remove("aliasA"); definedKS.put("aliasB", keys); - mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS); + mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); assertNull(ps.keySetData.getUpgradeKeySets()); } @@ -729,7 +729,7 @@ public class KeySetManagerServiceTest extends AndroidTestCase { ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys.add(keyA); - mKsms.addSigningKeySetToPackageLPw(ps.name, signingKeys); + mKsms.addSigningKeySetToPackageLPw(ps, signingKeys); /* remove its references */ mKsms.removeAppKeySetDataLPw(ps.name); @@ -754,8 +754,8 @@ public class KeySetManagerServiceTest extends AndroidTestCase { ArraySet<PublicKey> signingKeys = new ArraySet<PublicKey>(); PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); signingKeys.add(keyA); - mKsms.addSigningKeySetToPackageLPw(ps1.name, signingKeys); - mKsms.addSigningKeySetToPackageLPw(ps2.name, signingKeys); + mKsms.addSigningKeySetToPackageLPw(ps1, signingKeys); + mKsms.addSigningKeySetToPackageLPw(ps2, signingKeys); /* remove references from first package */ mKsms.removeAppKeySetDataLPw(ps1.name); @@ -784,13 +784,13 @@ public class KeySetManagerServiceTest extends AndroidTestCase { /* removal requires signing keyset to be specified (since all apps are * assumed to have it). We skipped this in the defined tests, but can't * here. */ - mKsms.addSigningKeySetToPackageLPw(ps.name, keys); + mKsms.addSigningKeySetToPackageLPw(ps, keys); definedKS.put("aliasA", keys); - mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS); + mKsms.addDefinedKeySetsToPackageLPw(ps, definedKS); ArraySet<String> upgradeKS = new ArraySet<String>(); upgradeKS.add("aliasA"); - mKsms.addUpgradeKeySetsToPackageLPw(ps.name, upgradeKS); + mKsms.addUpgradeKeySetsToPackageLPw(ps, upgradeKS); mKsms.removeAppKeySetDataLPw(ps.name); assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1)); diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index b0fca95..fafe44a 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -853,7 +853,38 @@ public class VoiceInteractionManagerService extends SystemService { PackageMonitor mPackageMonitor = new PackageMonitor() { @Override public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) { - return super.onHandleForceStop(intent, packages, uid, doit); + if (DEBUG) Slog.d(TAG, "onHandleForceStop uid=" + uid + " doit=" + doit); + + int userHandle = UserHandle.getUserId(uid); + ComponentName curInteractor = getCurInteractor(userHandle); + ComponentName curRecognizer = getCurRecognizer(userHandle); + boolean hit = false; + for (String pkg : packages) { + if (curInteractor != null && pkg.equals(curInteractor.getPackageName())) { + hit = true; + break; + } else if (curRecognizer != null + && pkg.equals(curRecognizer.getPackageName())) { + hit = true; + break; + } + } + if (hit && doit) { + // The user is force stopping our current interactor/recognizer. + // Clear the current settings and restore default state. + synchronized (VoiceInteractionManagerService.this) { + mSoundTriggerHelper.stopAllRecognitions(); + if (mImpl != null) { + mImpl.shutdownLocked(); + mImpl = null; + } + setCurInteractor(null, userHandle); + setCurRecognizer(null, userHandle); + initForUser(userHandle); + switchImplementationIfNeededLocked(true); + } + } + return hit; } @Override @@ -865,51 +896,53 @@ public class VoiceInteractionManagerService extends SystemService { int userHandle = getChangingUserId(); if (DEBUG) Slog.d(TAG, "onSomePackagesChanged user=" + userHandle); - ComponentName curInteractor = getCurInteractor(userHandle); - ComponentName curRecognizer = getCurRecognizer(userHandle); - if (curRecognizer == null) { - // Could a new recognizer appear when we don't have one pre-installed? - if (anyPackagesAppearing()) { - curRecognizer = findAvailRecognizer(null, userHandle); - if (curRecognizer != null) { - setCurRecognizer(curRecognizer, userHandle); + synchronized (VoiceInteractionManagerService.this) { + ComponentName curInteractor = getCurInteractor(userHandle); + ComponentName curRecognizer = getCurRecognizer(userHandle); + if (curRecognizer == null) { + // Could a new recognizer appear when we don't have one pre-installed? + if (anyPackagesAppearing()) { + curRecognizer = findAvailRecognizer(null, userHandle); + if (curRecognizer != null) { + setCurRecognizer(curRecognizer, userHandle); + } } - } - return; - } - - if (curInteractor != null) { - int change = isPackageDisappearing(curInteractor.getPackageName()); - if (change == PACKAGE_PERMANENT_CHANGE) { - // The currently set interactor is permanently gone; fall back to - // the default config. - setCurInteractor(null, userHandle); - setCurRecognizer(null, userHandle); - initForUser(userHandle); return; } - change = isPackageAppearing(curInteractor.getPackageName()); - if (change != PACKAGE_UNCHANGED) { - // If current interactor is now appearing, for any reason, then - // restart our connection with it. - if (mImpl != null && curInteractor.getPackageName().equals( - mImpl.mComponent.getPackageName())) { - switchImplementationIfNeededLocked(true); + if (curInteractor != null) { + int change = isPackageDisappearing(curInteractor.getPackageName()); + if (change == PACKAGE_PERMANENT_CHANGE) { + // The currently set interactor is permanently gone; fall back to + // the default config. + setCurInteractor(null, userHandle); + setCurRecognizer(null, userHandle); + initForUser(userHandle); + return; + } + + change = isPackageAppearing(curInteractor.getPackageName()); + if (change != PACKAGE_UNCHANGED) { + // If current interactor is now appearing, for any reason, then + // restart our connection with it. + if (mImpl != null && curInteractor.getPackageName().equals( + mImpl.mComponent.getPackageName())) { + switchImplementationIfNeededLocked(true); + } } + return; } - return; - } - // There is no interactor, so just deal with a simple recognizer. - int change = isPackageDisappearing(curRecognizer.getPackageName()); - if (change == PACKAGE_PERMANENT_CHANGE - || change == PACKAGE_TEMPORARY_CHANGE) { - setCurRecognizer(findAvailRecognizer(null, userHandle), userHandle); + // There is no interactor, so just deal with a simple recognizer. + int change = isPackageDisappearing(curRecognizer.getPackageName()); + if (change == PACKAGE_PERMANENT_CHANGE + || change == PACKAGE_TEMPORARY_CHANGE) { + setCurRecognizer(findAvailRecognizer(null, userHandle), userHandle); - } else if (isPackageModified(curRecognizer.getPackageName())) { - setCurRecognizer(findAvailRecognizer(curRecognizer.getPackageName(), - userHandle), userHandle); + } else if (isPackageModified(curRecognizer.getPackageName())) { + setCurRecognizer(findAvailRecognizer(curRecognizer.getPackageName(), + userHandle), userHandle); + } } } }; diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 1cc275d..8291a30 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -667,7 +667,7 @@ public class TelephonyManager { IPhoneSubInfo info = getSubscriberInfo(); if (info == null) return null; - return info.getDeviceSvnUsingSubId(subId[0]); + return info.getDeviceSvnUsingSubId(subId[0], mContext.getOpPackageName()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { @@ -744,7 +744,7 @@ public class TelephonyManager { IPhoneSubInfo info = getSubscriberInfo(); if (info == null) return null; - return info.getImeiForSubscriber(subId[0]); + return info.getImeiForSubscriber(subId[0], mContext.getOpPackageName()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { @@ -773,7 +773,7 @@ public class TelephonyManager { IPhoneSubInfo info = getSubscriberInfo(); if (info == null) return null; - String nai = info.getNaiForSubscriber(subId[0]); + String nai = info.getNaiForSubscriber(subId[0], mContext.getOpPackageName()); if (Log.isLoggable(TAG, Log.VERBOSE)) { Rlog.v(TAG, "Nai = " + nai); } @@ -1856,7 +1856,7 @@ public class TelephonyManager { IPhoneSubInfo info = getSubscriberInfo(); if (info == null) return null; - return info.getIccSerialNumberForSubscriber(subId); + return info.getIccSerialNumberForSubscriber(subId, mContext.getOpPackageName()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { @@ -1938,7 +1938,7 @@ public class TelephonyManager { IPhoneSubInfo info = getSubscriberInfo(); if (info == null) return null; - return info.getSubscriberIdForSubscriber(subId); + return info.getSubscriberIdForSubscriber(subId, mContext.getOpPackageName()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { @@ -1959,7 +1959,7 @@ public class TelephonyManager { IPhoneSubInfo info = getSubscriberInfo(); if (info == null) return null; - return info.getGroupIdLevel1(); + return info.getGroupIdLevel1(mContext.getOpPackageName()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { @@ -1983,7 +1983,7 @@ public class TelephonyManager { IPhoneSubInfo info = getSubscriberInfo(); if (info == null) return null; - return info.getGroupIdLevel1ForSubscriber(subId); + return info.getGroupIdLevel1ForSubscriber(subId, mContext.getOpPackageName()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { @@ -2029,7 +2029,7 @@ public class TelephonyManager { IPhoneSubInfo info = getSubscriberInfo(); if (info == null) return null; - return info.getLine1NumberForSubscriber(subId); + return info.getLine1NumberForSubscriber(subId, mContext.getOpPackageName()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { @@ -2122,7 +2122,7 @@ public class TelephonyManager { IPhoneSubInfo info = getSubscriberInfo(); if (info == null) return null; - return info.getLine1AlphaTagForSubscriber(subId); + return info.getLine1AlphaTagForSubscriber(subId, mContext.getOpPackageName()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { @@ -2178,7 +2178,7 @@ public class TelephonyManager { IPhoneSubInfo info = getSubscriberInfo(); if (info == null) return null; - return info.getMsisdnForSubscriber(subId); + return info.getMsisdnForSubscriber(subId, mContext.getOpPackageName()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { @@ -2211,7 +2211,7 @@ public class TelephonyManager { IPhoneSubInfo info = getSubscriberInfo(); if (info == null) return null; - return info.getVoiceMailNumberForSubscriber(subId); + return info.getVoiceMailNumberForSubscriber(subId, mContext.getOpPackageName()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { @@ -2350,7 +2350,7 @@ public class TelephonyManager { IPhoneSubInfo info = getSubscriberInfo(); if (info == null) return null; - return info.getVoiceMailAlphaTagForSubscriber(subId); + return info.getVoiceMailAlphaTagForSubscriber(subId, mContext.getOpPackageName()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl index c91a59c..ed85392 100644 --- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl +++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl @@ -25,12 +25,12 @@ interface IPhoneSubInfo { /** * Retrieves the unique device ID, e.g., IMEI for GSM phones. */ - String getDeviceId(); + String getDeviceId(String callingPackage); /** * Retrieves the unique Network Access ID */ - String getNaiForSubscriber(int subId); + String getNaiForSubscriber(int subId, String callingPackage); /** * Retrieves the unique device ID of a phone for the device, e.g., IMEI @@ -41,91 +41,91 @@ interface IPhoneSubInfo { /** * Retrieves the IMEI. */ - String getImeiForSubscriber(int subId); + String getImeiForSubscriber(int subId, String callingPackage); /** * Retrieves the software version number for the device, e.g., IMEI/SV * for GSM phones. */ - String getDeviceSvn(); + String getDeviceSvn(String callingPackage); /** * Retrieves the software version number of a subId for the device, e.g., IMEI/SV * for GSM phones. */ - String getDeviceSvnUsingSubId(int subId); + String getDeviceSvnUsingSubId(int subId, String callingPackage); /** * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones. */ - String getSubscriberId(); + String getSubscriberId(String callingPackage); /** * Retrieves the unique subscriber ID of a given subId, e.g., IMSI for GSM phones. */ - String getSubscriberIdForSubscriber(int subId); + String getSubscriberIdForSubscriber(int subId, String callingPackage); /** * Retrieves the Group Identifier Level1 for GSM phones. */ - String getGroupIdLevel1(); + String getGroupIdLevel1(String callingPackage); /** * Retrieves the Group Identifier Level1 for GSM phones of a subId. */ - String getGroupIdLevel1ForSubscriber(int subId); + String getGroupIdLevel1ForSubscriber(int subId, String callingPackage); /** * Retrieves the serial number of the ICC, if applicable. */ - String getIccSerialNumber(); + String getIccSerialNumber(String callingPackage); /** * Retrieves the serial number of a given subId. */ - String getIccSerialNumberForSubscriber(int subId); + String getIccSerialNumberForSubscriber(int subId, String callingPackage); /** * Retrieves the phone number string for line 1. */ - String getLine1Number(); + String getLine1Number(String callingPackage); /** * Retrieves the phone number string for line 1 of a subcription. */ - String getLine1NumberForSubscriber(int subId); + String getLine1NumberForSubscriber(int subId, String callingPackage); /** * Retrieves the alpha identifier for line 1. */ - String getLine1AlphaTag(); + String getLine1AlphaTag(String callingPackage); /** * Retrieves the alpha identifier for line 1 of a subId. */ - String getLine1AlphaTagForSubscriber(int subId); + String getLine1AlphaTagForSubscriber(int subId, String callingPackage); /** * Retrieves MSISDN Number. */ - String getMsisdn(); + String getMsisdn(String callingPackage); /** * Retrieves the Msisdn of a subId. */ - String getMsisdnForSubscriber(int subId); + String getMsisdnForSubscriber(int subId, String callingPackage); /** * Retrieves the voice mail number. */ - String getVoiceMailNumber(); + String getVoiceMailNumber(String callingPackage); /** * Retrieves the voice mail number of a given subId. */ - String getVoiceMailNumberForSubscriber(int subId); + String getVoiceMailNumberForSubscriber(int subId, String callingPackage); /** * Retrieves the complete voice mail number. @@ -140,13 +140,13 @@ interface IPhoneSubInfo { /** * Retrieves the alpha identifier associated with the voice mail number. */ - String getVoiceMailAlphaTag(); + String getVoiceMailAlphaTag(String callingPackage); /** * Retrieves the alpha identifier associated with the voice mail number * of a subId. */ - String getVoiceMailAlphaTagForSubscriber(int subId); + String getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage); /** * Returns the IMS private user identity (IMPI) that was loaded from the ISIM. diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index a1d5dd5..5d55ec6 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -684,6 +684,18 @@ public class WifiConfiguration implements Parcelable { /** * @hide + * For debug: date at which the config was last updated + */ + public String updateTime; + + /** + * @hide + * For debug: date at which the config was last updated + */ + public String creationTime; + + /** + * @hide * The WiFi configuration is considered to have no internet access for purpose of autojoining * if there has been a report of it having no internet access, and, it never have had * internet access in the past. @@ -1000,6 +1012,12 @@ public class WifiConfiguration implements Parcelable { sbuf.append(" numNoInternetAccessReports "); sbuf.append(this.numNoInternetAccessReports).append("\n"); } + if (this.updateTime != null) { + sbuf.append("creation=").append(this.updateTime).append("\n"); + } + if (this.creationTime != null) { + sbuf.append("update=").append(this.creationTime).append("\n"); + } if (this.didSelfAdd) sbuf.append(" didSelfAdd"); if (this.selfAdded) sbuf.append(" selfAdded"); if (this.validatedInternetAccess) sbuf.append(" validatedInternetAccess"); @@ -1505,6 +1523,8 @@ public class WifiConfiguration implements Parcelable { userApproved = source.userApproved; numNoInternetAccessReports = source.numNoInternetAccessReports; noInternetAccessExpected = source.noInternetAccessExpected; + creationTime = source.creationTime; + updateTime = source.updateTime; } } |