diff options
Diffstat (limited to 'core')
330 files changed, 5170 insertions, 2891 deletions
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java index 2cb27b0..eafcdb2 100644 --- a/core/java/android/app/ActivityView.java +++ b/core/java/android/app/ActivityView.java @@ -350,10 +350,15 @@ public class ActivityView extends ViewGroup { if (activityView != null) { final ActivityViewCallback callback = activityView.mActivityViewCallback; if (callback != null) { + final WeakReference<ActivityViewCallback> callbackRef = + new WeakReference<>(callback); activityView.post(new Runnable() { @Override public void run() { - callback.onAllActivitiesComplete(activityView); + ActivityViewCallback callback = callbackRef.get(); + if (callback != null) { + callback.onAllActivitiesComplete(activityView); + } } }); } diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index fd7bae7..59fe490 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -27,6 +27,7 @@ import android.app.job.IJobScheduler; import android.app.job.JobScheduler; import android.app.trust.TrustManager; import android.app.usage.IUsageStatsManager; +import android.app.usage.NetworkStatsManager; import android.app.usage.UsageStatsManager; import android.appwidget.AppWidgetManager; import android.bluetooth.BluetoothManager; @@ -639,6 +640,13 @@ final class SystemServiceRegistry { return new UsageStatsManager(ctx.getOuterContext(), service); }}); + registerService(Context.NETWORK_STATS_SERVICE, NetworkStatsManager.class, + new CachedServiceFetcher<NetworkStatsManager>() { + @Override + public NetworkStatsManager createService(ContextImpl ctx) { + return new NetworkStatsManager(ctx.getOuterContext()); + }}); + registerService(Context.JOB_SCHEDULER_SERVICE, JobScheduler.class, new StaticServiceFetcher<JobScheduler>() { @Override diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 6dde07b..cf6619f 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -20,7 +20,6 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.app.Activity; -import android.app.admin.IDevicePolicyManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -176,7 +175,8 @@ public class DevicePolicyManager { * * <p>This component is set as device owner and active admin when device owner provisioning is * started by an NFC message containing an NFC record with MIME type - * {@link #MIME_TYPE_PROVISIONING_NFC}. + * {@link #MIME_TYPE_PROVISIONING_NFC_V2}. For the NFC record, the component name should be + * flattened to a string, via {@link ComponentName#flattenToShortString()}. * * @see DeviceAdminReceiver */ @@ -346,7 +346,7 @@ public class DevicePolicyManager { * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION} if the version of the * installed package is less than this version code. * - * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner * provisioning via an NFC bump. */ public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE @@ -363,10 +363,10 @@ public class DevicePolicyManager { = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER"; /** - * A String extra holding the SHA-1 checksum of the file at download location specified in - * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}. If this doesn't match - * the file at the download location an error will be shown to the user and the user will be - * asked to factory reset the device. + * 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}. If + * this doesn't match the file at the download location an error will be shown to the user and + * the user will be asked to factory reset the device. * * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner * provisioning via an NFC bump. @@ -392,21 +392,23 @@ public class DevicePolicyManager { * A boolean extra indicating whether device encryption is required as part of Device Owner * provisioning. * - * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner * provisioning via an NFC bump. */ public static final String EXTRA_PROVISIONING_SKIP_ENCRYPTION = "android.app.extra.PROVISIONING_SKIP_ENCRYPTION"; /** - * On devices managed by a device owner app, a String representation of a Component name extra - * indicating the component of the application that is temporarily granted device owner - * privileges during device initialization and profile owner privileges during secondary user - * initialization. + * On devices managed by a device owner app, a {@link ComponentName} extra indicating the + * component of the application that is temporarily granted device owner privileges during + * device initialization and profile owner privileges during secondary user initialization. * - * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner - * provisioning via an NFC bump. - * @see ComponentName#unflattenFromString() + * <p> + * It can also be used in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts + * device owner provisioning via an NFC bump. For the NFC record, it should be flattened to a + * string first. + * + * @see ComponentName#flattenToShortString() */ public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME"; @@ -416,7 +418,7 @@ public class DevicePolicyManager { * initializer package. When not provided it is assumed that the device initializer package is * already installed. * - * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner * provisioning via an NFC bump. */ public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION @@ -428,7 +430,7 @@ public class DevicePolicyManager { * {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION} if the version of * the installed package is less than this version code. * - * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner * provisioning via an NFC bump. */ public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE @@ -438,19 +440,20 @@ public class DevicePolicyManager { * A String extra holding a http cookie header which should be used in the http request to the * url specified in {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}. * - * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner * provisioning via an NFC bump. */ public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER"; /** - * A String extra holding the SHA-1 checksum of the file at download location specified in + * A String extra holding the URL-safe base64 encoded SHA-1 checksum of the file at download + * location specified in * {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}. If this doesn't * match the file at the download location an error will be shown to the user and the user will * be asked to factory reset the device. * - * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner * provisioning via an NFC bump. */ public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM @@ -460,7 +463,7 @@ public class DevicePolicyManager { * A String extra holding the MAC address of the Bluetooth device to connect to with status * updates during provisioning. * - * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner * provisioning via an NFC bump. */ public static final String EXTRA_PROVISIONING_BT_MAC_ADDRESS @@ -472,7 +475,7 @@ public class DevicePolicyManager { * * <p>This value must be specified when {@code #EXTRA_PROVISIONING_BT_MAC_ADDRESS} is present. * - * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner * provisioning via an NFC bump. */ public static final String EXTRA_PROVISIONING_BT_UUID @@ -484,7 +487,7 @@ public class DevicePolicyManager { * * <p>This value must be specified when {@code #EXTRA_PROVISIONING_BT_MAC_ADDRESS} is present. * - * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner * provisioning via an NFC bump. */ public static final String EXTRA_PROVISIONING_BT_DEVICE_ID @@ -494,31 +497,26 @@ public class DevicePolicyManager { * A Boolean extra that that will cause a provisioned device to temporarily proxy network * traffic over Bluetooth. When a Wi-Fi network is available, the network proxy will stop. * - * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner + * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner * provisioning via an NFC bump. */ public static final String EXTRA_PROVISIONING_BT_USE_PROXY = "android.app.extra.PROVISIONING_BT_USE_PROXY"; - /** - * This MIME type is used for starting the Device Owner provisioning. - * - * <p>During device owner provisioning a device admin app is set as the owner of the device. - * A device owner has full control over the device. The device owner can not be modified by the - * user and the only way of resetting the device is if the device owner app calls a factory - * reset. - * - * <p> A typical use case would be a device that is owned by a company, but used by either an - * employee or client. + * This MIME type is used for starting the Device Owner provisioning that does not require + * provisioning features introduced in Android API level + * {@link android.os.Build.VERSION_CODES#MNC} or later levels. * - * <p> The NFC message should be send to an unprovisioned device. + * <p>For more information about the provisioning process see + * {@link #MIME_TYPE_PROVISIONING_NFC_V2}. * * <p>The NFC record must contain a serialized {@link java.util.Properties} object which * contains the following properties: * <ul> - * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}</li> + * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}</li> + * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}, optional</li> * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER}, optional</li> - * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM}</li> + * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM}, optional</li> * <li>{@link #EXTRA_PROVISIONING_LOCAL_TIME} (convert to String), optional</li> * <li>{@link #EXTRA_PROVISIONING_TIME_ZONE}, optional</li> * <li>{@link #EXTRA_PROVISIONING_LOCALE}, optional</li> @@ -529,17 +527,56 @@ public class DevicePolicyManager { * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_HOST}, optional</li> * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_PORT} (convert to String), optional</li> * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_BYPASS}, optional</li> - * <li>{@link #EXTRA_PROVISIONING_WIFI_PAC_URL}, optional</li> - * <li>{@link #EXTRA_PROVISIONING_SKIP_ENCRYPTION}, optional</li></ul> + * <li>{@link #EXTRA_PROVISIONING_WIFI_PAC_URL}, optional</li></ul> * * <p> - * In version {@link android.os.Build.VERSION_CODES#LOLLIPOP}, it should also contain - * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}. - * As of {@link android.os.Build.VERSION_CODES#MNC}, it should contain - * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME} instead, (although - * specifying only {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME} is still supported). - * This componentName must have been converted to a String via - * {@link android.content.ComponentName#flattenToString()} + * As of {@link android.os.Build.VERSION_CODES#MNC}, the properties should contain + * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME} instead of + * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}, (although specifying only + * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME} is still supported). + * + * @see #MIME_TYPE_PROVISIONING_NFC_V2 + * + */ + public static final String MIME_TYPE_PROVISIONING_NFC + = "application/com.android.managedprovisioning"; + + + /** + * This MIME type is used for starting the Device Owner provisioning that requires + * new provisioning features introduced in API version + * {@link android.os.Build.VERSION_CODES#MNC} in addition to those supported in earlier + * versions. + * + * <p>During device owner provisioning a device admin app is set as the owner of the device. + * A device owner has full control over the device. The device owner can not be modified by the + * user and the only way of resetting the device is if the device owner app calls a factory + * reset. + * + * <p> A typical use case would be a device that is owned by a company, but used by either an + * employee or client. + * + * <p> The NFC message should be sent to an unprovisioned device. + * + * <p>The NFC record must contain a serialized {@link java.util.Properties} object which + * contains the following properties in addition to properties listed at + * {@link #MIME_TYPE_PROVISIONING_NFC}: + * <ul> + * <li>{@link #EXTRA_PROVISIONING_SKIP_ENCRYPTION}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}. + * Replaces {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}. The value of the property + * should be converted to a String via + * {@link android.content.ComponentName#flattenToString()}</li> + * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_BT_MAC_ADDRESS}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_BT_UUID}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_BT_DEVICE_ID}, optional</li> + * <li>{@link #EXTRA_PROVISIONING_BT_USE_PROXY}, optional</li></ul> * * <p> When device owner provisioning has completed, an intent of the type * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} is broadcasted to the @@ -551,8 +588,8 @@ public class DevicePolicyManager { * <p>Input: Nothing.</p> * <p>Output: Nothing</p> */ - public static final String MIME_TYPE_PROVISIONING_NFC - = "application/com.android.managedprovisioning"; + public static final String MIME_TYPE_PROVISIONING_NFC_V2 + = "application/com.android.managedprovisioning.v2"; /** * Activity action: ask the user to add a new device administrator to the system. @@ -577,11 +614,10 @@ public class DevicePolicyManager { /** * @hide * Activity action: ask the user to add a new device administrator as the profile owner - * for this user. Only system privileged apps that have MANAGE_USERS and MANAGE_DEVICE_ADMINS - * permission can call this API. + * for this user. Only system apps can launch this intent. * - * <p>The ComponentName of the profile owner admin is pass in {@link #EXTRA_DEVICE_ADMIN} extra - * field. This will invoke a UI to bring the user through adding the profile owner admin + * <p>The ComponentName of the profile owner admin is passed in the {@link #EXTRA_DEVICE_ADMIN} + * extra field. This will invoke a UI to bring the user through adding the profile owner admin * to remotely control restrictions on the user. * * <p>The intent must be invoked via {@link Activity#startActivityForResult()} to receive the @@ -593,8 +629,8 @@ public class DevicePolicyManager { * field to provide the user with additional explanation (in addition * to your component's description) about what is being added. * - * <p>If there is already a profile owner active or the caller doesn't have the required - * permissions, the operation will return a failure result. + * <p>If there is already a profile owner active or the caller is not a system app, the + * operation will return a failure result. */ @SystemApi public static final String ACTION_SET_PROFILE_OWNER diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java index a1f1d92..0a0d77d 100644 --- a/core/java/android/app/admin/DevicePolicyManagerInternal.java +++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java @@ -60,4 +60,13 @@ public abstract class DevicePolicyManagerInternal { */ public abstract void addOnCrossProfileWidgetProvidersChangeListener( OnCrossProfileWidgetProvidersChangeListener listener); + + /** + * Checks if an app with given uid is an active device admin of its user and has the policy + * specified. + * @param uid App uid. + * @param reqPolicy Required policy, for policies see {@link DevicePolicyManager}. + * @return true if the uid is an active admin with the given policy. + */ + public abstract boolean isActiveAdminWithPolicy(int uid, int reqPolicy); } diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java new file mode 100644 index 0000000..af7c053 --- /dev/null +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -0,0 +1,233 @@ +/** + * 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.app.usage; + +import android.app.usage.NetworkUsageStats.Bucket; +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkIdentity; +import android.net.NetworkTemplate; +import android.os.RemoteException; +import android.os.UserHandle; +import android.util.Log; + +/** + * Provides access to network usage history and statistics. Usage data is collected in + * discrete bins of time called 'Buckets'. See {@link NetworkUsageStats.Bucket} for details. + * <p /> + * Queries can define a time interval in the form of start and end timestamps (Long.MIN_VALUE and + * Long.MAX_VALUE can be used to simulate open ended intervals). All queries (except + * {@link #querySummaryForDevice}) collect only network usage of apps belonging to the same user + * as the client. In addition tethering usage, usage by removed users and apps, and usage by system + * is also included in the results. + * <h3> + * Summary queries + * </h3> + * These queries aggregate network usage across the whole interval. Therefore there will be only one + * bucket for a particular key and state combination. In case of the user-wide and device-wide + * summaries a single bucket containing the totalised network usage is returned. + * <h3> + * History queries + * </h3> + * These queries do not aggregate over time but do aggregate over state. Therefore there can be + * multiple buckets for a particular key but all Bucket's state is going to be + * {@link NetworkUsageStats.Bucket#STATE_ALL}. + * <p /> + * <b>NOTE:</b> This API requires the permission + * {@link android.Manifest.permission#PACKAGE_USAGE_STATS}, which is a system-level permission and + * will not be granted to third-party apps. However, declaring the permission implies intention to + * use the API and the user of the device can grant permission through the Settings application. + * Profile owner apps are automatically granted permission to query data on the profile they manage + * (that is, for any query except {@link #querySummaryForDevice}). Device owner apps likewise get + * access to usage data of the primary user. + */ +public class NetworkStatsManager { + private final static String TAG = "NetworkStatsManager"; + + private final Context mContext; + + /** + * {@hide} + */ + public NetworkStatsManager(Context context) { + mContext = context; + } + /** + * Query network usage statistics summaries. Result is summarised data usage for the whole + * device. Result is a single Bucket aggregated over time, state and uid. + * + * @param networkType As defined in {@link ConnectivityManager}, e.g. + * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} + * etc. + * @param subscriberId If applicable, the subscriber id of the network interface. + * @param startTime Start of period. Defined in terms of "Unix time", see + * {@link java.lang.System#currentTimeMillis}. + * @param endTime End of period. Defined in terms of "Unix time", see + * {@link java.lang.System#currentTimeMillis}. + * @return Bucket object or null if permissions are insufficient or error happened during + * statistics collection. + */ + public Bucket querySummaryForDevice(int networkType, String subscriberId, + long startTime, long endTime) throws SecurityException, RemoteException { + NetworkTemplate template = createTemplate(networkType, subscriberId); + if (template == null) { + return null; + } + + Bucket bucket = null; + NetworkUsageStats stats = new NetworkUsageStats(mContext, template, startTime, endTime); + bucket = stats.getDeviceSummaryForNetwork(startTime, endTime); + + stats.close(); + return bucket; + } + + /** + * Query network usage statistics summaries. Result is summarised data usage for all uids + * belonging to calling user. Result is a single Bucket aggregated over time, state and uid. + * + * @param networkType As defined in {@link ConnectivityManager}, e.g. + * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} + * etc. + * @param subscriberId If applicable, the subscriber id of the network interface. + * @param startTime Start of period. Defined in terms of "Unix time", see + * {@link java.lang.System#currentTimeMillis}. + * @param endTime End of period. Defined in terms of "Unix time", see + * {@link java.lang.System#currentTimeMillis}. + * @return Bucket object or null if permissions are insufficient or error happened during + * statistics collection. + */ + public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime, + long endTime) throws SecurityException, RemoteException { + NetworkTemplate template = createTemplate(networkType, subscriberId); + if (template == null) { + return null; + } + + NetworkUsageStats stats; + stats = new NetworkUsageStats(mContext, template, startTime, endTime); + stats.startSummaryEnumeration(startTime, endTime); + + stats.close(); + return stats.getSummaryAggregate(); + } + + /** + * Query network usage statistics summaries. Result filtered to include only uids belonging to + * calling user. Result is aggregated over time, hence all buckets will have the same start and + * end timestamps. Not aggregated over state or uid. + * + * @param networkType As defined in {@link ConnectivityManager}, e.g. + * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} + * etc. + * @param subscriberId If applicable, the subscriber id of the network interface. + * @param startTime Start of period. Defined in terms of "Unix time", see + * {@link java.lang.System#currentTimeMillis}. + * @param endTime End of period. Defined in terms of "Unix time", see + * {@link java.lang.System#currentTimeMillis}. + * @return Statistics object or null if permissions are insufficient or error happened during + * statistics collection. + */ + public NetworkUsageStats querySummary(int networkType, String subscriberId, long startTime, + long endTime) throws SecurityException, RemoteException { + NetworkTemplate template = createTemplate(networkType, subscriberId); + if (template == null) { + return null; + } + + NetworkUsageStats result; + result = new NetworkUsageStats(mContext, template, startTime, endTime); + result.startSummaryEnumeration(startTime, endTime); + + return result; + } + + /** + * Query network usage statistics details. Only usable for uids belonging to calling user. + * Result is aggregated over state but not aggregated over time. + * + * @param networkType As defined in {@link ConnectivityManager}, e.g. + * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} + * etc. + * @param subscriberId If applicable, the subscriber id of the network interface. + * @param startTime Start of period. Defined in terms of "Unix time", see + * {@link java.lang.System#currentTimeMillis}. + * @param endTime End of period. Defined in terms of "Unix time", see + * {@link java.lang.System#currentTimeMillis}. + * @param uid UID of app + * @return Statistics object or null if permissions are insufficient or error happened during + * statistics collection. + */ + public NetworkUsageStats queryDetailsForUid(int networkType, String subscriberId, + long startTime, long endTime, int uid) throws SecurityException, RemoteException { + NetworkTemplate template = createTemplate(networkType, subscriberId); + if (template == null) { + return null; + } + + NetworkUsageStats result; + result = new NetworkUsageStats(mContext, template, startTime, endTime); + result.startHistoryEnumeration(uid); + + return result; + } + + /** + * Query network usage statistics details. Result filtered to include only uids belonging to + * calling user. Result is aggregated over state but not aggregated over time or uid. + * + * @param networkType As defined in {@link ConnectivityManager}, e.g. + * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} + * etc. + * @param subscriberId If applicable, the subscriber id of the network interface. + * @param startTime Start of period. Defined in terms of "Unix time", see + * {@link java.lang.System#currentTimeMillis}. + * @param endTime End of period. Defined in terms of "Unix time", see + * {@link java.lang.System#currentTimeMillis}. + * @return Statistics object or null if permissions are insufficient or error happened during + * statistics collection. + */ + public NetworkUsageStats queryDetails(int networkType, String subscriberId, long startTime, + long endTime) throws SecurityException, RemoteException { + NetworkTemplate template = createTemplate(networkType, subscriberId); + if (template == null) { + return null; + } + NetworkUsageStats result; + result = new NetworkUsageStats(mContext, template, startTime, endTime); + result.startUserUidEnumeration(); + return result; + } + + private static NetworkTemplate createTemplate(int networkType, String subscriberId) { + NetworkTemplate template = null; + switch (networkType) { + case ConnectivityManager.TYPE_MOBILE: { + template = NetworkTemplate.buildTemplateMobileAll(subscriberId); + } break; + case ConnectivityManager.TYPE_WIFI: { + template = NetworkTemplate.buildTemplateWifiWildcard(); + } break; + default: { + Log.w(TAG, "Cannot create template for network type " + networkType + + ", subscriberId '" + NetworkIdentity.scrubSubscriberId(subscriberId) + + "'."); + } + } + return template; + } +} diff --git a/core/java/android/app/usage/NetworkUsageStats.java b/core/java/android/app/usage/NetworkUsageStats.java new file mode 100644 index 0000000..990d231 --- /dev/null +++ b/core/java/android/app/usage/NetworkUsageStats.java @@ -0,0 +1,479 @@ +/** + * 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.app.usage; + +import android.content.Context; +import android.net.INetworkStatsService; +import android.net.INetworkStatsSession; +import android.net.NetworkStats; +import android.net.NetworkStatsHistory; +import android.net.NetworkTemplate; +import android.net.TrafficStats; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; + +import dalvik.system.CloseGuard; + +/** + * Class providing enumeration over buckets of network usage statistics. NetworkUsageStats objects + * are returned as results to various queries in {@link NetworkStatsManager}. + */ +public final class NetworkUsageStats implements AutoCloseable { + private final static String TAG = "NetworkUsageStats"; + + private final CloseGuard mCloseGuard = CloseGuard.get(); + + /** + * Start timestamp of stats collected + */ + private final long mStartTimeStamp; + + /** + * End timestamp of stats collected + */ + private final long mEndTimeStamp; + + + /** + * Non-null array indicates the query enumerates over uids. + */ + private int[] mUids; + + /** + * Index of the current uid in mUids when doing uid enumeration or a single uid value, + * depending on query type. + */ + private int mUidOrUidIndex; + + /** + * The session while the query requires it, null if all the stats have been collected or close() + * has been called. + */ + private INetworkStatsSession mSession; + private NetworkTemplate mTemplate; + + /** + * Results of a summary query. + */ + private NetworkStats mSummary = null; + + /** + * Results of detail queries. + */ + private NetworkStatsHistory mHistory = null; + + /** + * Where we are in enumerating over the current result. + */ + private int mEnumerationIndex = 0; + + /** + * Recycling entry objects to prevent heap fragmentation. + */ + private NetworkStats.Entry mRecycledSummaryEntry = null; + private NetworkStatsHistory.Entry mRecycledHistoryEntry = null; + + /** @hide */ + NetworkUsageStats(Context context, NetworkTemplate template, long startTimestamp, + long endTimestamp) throws RemoteException, SecurityException { + final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface( + ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); + // Open network stats session + mSession = statsService.openSessionForUsageStats(context.getOpPackageName()); + mCloseGuard.open("close"); + mTemplate = template; + mStartTimeStamp = startTimestamp; + mEndTimeStamp = endTimestamp; + } + + @Override + protected void finalize() throws Throwable { + try { + if (mCloseGuard != null) { + mCloseGuard.warnIfOpen(); + } + close(); + } finally { + super.finalize(); + } + } + + // -------------------------BEGINNING OF PUBLIC API----------------------------------- + + /** + * Buckets are the smallest elements of a query result. As some dimensions of a result may be + * aggregated (e.g. time or state) some values may be equal across all buckets. + */ + public static class Bucket { + /** + * Combined usage across all other states. + */ + public static final int STATE_ALL = -1; + + /** + * Usage not accounted in any other states. + */ + public static final int STATE_DEFAULT = 0x1; + + /** + * Foreground usage. + */ + public static final int STATE_FOREGROUND = 0x2; + + /** + * Special UID value for removed apps. + */ + public static final int UID_REMOVED = -4; + + /** + * Special UID value for data usage by tethering. + */ + public static final int UID_TETHERING = -5; + + private int mUid; + private int mState; + private long mBeginTimeStamp; + private long mEndTimeStamp; + private long mRxBytes; + private long mRxPackets; + private long mTxBytes; + private long mTxPackets; + + private static int convertState(int networkStatsSet) { + switch (networkStatsSet) { + case NetworkStats.SET_ALL : return STATE_ALL; + case NetworkStats.SET_DEFAULT : return STATE_DEFAULT; + case NetworkStats.SET_FOREGROUND : return STATE_FOREGROUND; + } + return 0; + } + + private static int convertUid(int uid) { + switch (uid) { + case TrafficStats.UID_REMOVED: return UID_REMOVED; + case TrafficStats.UID_TETHERING: return UID_TETHERING; + } + return uid; + } + + public Bucket() { + } + + /** + * Key of the bucket. Usually an app uid or one of the following special values:<p /> + * <ul> + * <li>{@link #UID_REMOVED}</li> + * <li>{@link #UID_TETHERING}</li> + * <li>{@link android.os.Process#SYSTEM_UID}</li> + * </ul> + * @return Bucket key. + */ + public int getUid() { + return mUid; + } + + /** + * Usage state. One of the following values:<p/> + * <ul> + * <li>{@link #STATE_ALL}</li> + * <li>{@link #STATE_DEFAULT}</li> + * <li>{@link #STATE_FOREGROUND}</li> + * </ul> + * @return Usage state. + */ + public int getState() { + return mState; + } + + /** + * Start timestamp of the bucket's time interval. Defined in terms of "Unix time", see + * {@link java.lang.System#currentTimeMillis}. + * @return Start of interval. + */ + public long getStartTimeStamp() { + return mBeginTimeStamp; + } + + /** + * End timestamp of the bucket's time interval. Defined in terms of "Unix time", see + * {@link java.lang.System#currentTimeMillis}. + * @return End of interval. + */ + public long getEndTimeStamp() { + return mEndTimeStamp; + } + + /** + * Number of bytes received during the bucket's time interval. Statistics are measured at + * the network layer, so they include both TCP and UDP usage. + * @return Number of bytes. + */ + public long getRxBytes() { + return mRxBytes; + } + + /** + * Number of bytes transmitted during the bucket's time interval. Statistics are measured at + * the network layer, so they include both TCP and UDP usage. + * @return Number of bytes. + */ + public long getTxBytes() { + return mTxBytes; + } + + /** + * Number of packets received during the bucket's time interval. Statistics are measured at + * the network layer, so they include both TCP and UDP usage. + * @return Number of packets. + */ + public long getRxPackets() { + return mRxPackets; + } + + /** + * Number of packets transmitted during the bucket's time interval. Statistics are measured + * at the network layer, so they include both TCP and UDP usage. + * @return Number of packets. + */ + public long getTxPackets() { + return mTxPackets; + } + } + + /** + * Fills the recycled bucket with data of the next bin in the enumeration. + * @param bucketOut Bucket to be filled with data. + * @return true if successfully filled the bucket, false otherwise. + */ + public boolean getNextBucket(Bucket bucketOut) { + if (mSummary != null) { + return getNextSummaryBucket(bucketOut); + } else { + return getNextHistoryBucket(bucketOut); + } + } + + /** + * Check if it is possible to ask for a next bucket in the enumeration. + * @return true if there is at least one more bucket. + */ + public boolean hasNextBucket() { + if (mSummary != null) { + return mEnumerationIndex < mSummary.size(); + } else if (mHistory != null) { + return mEnumerationIndex < mHistory.size() + || hasNextUid(); + } + return false; + } + + /** + * Closes the enumeration. Call this method before this object gets out of scope. + */ + @Override + public void close() { + if (mSession != null) { + try { + mSession.close(); + } catch (RemoteException e) { + Log.w(TAG, e); + // Otherwise, meh + } + } + mSession = null; + if (mCloseGuard != null) { + mCloseGuard.close(); + } + } + + // -------------------------END OF PUBLIC API----------------------------------- + + /** + * Collects device summary results into a Bucket. + * @param startTime + * @param endTime + * @throws RemoteException + */ + Bucket getDeviceSummaryForNetwork(long startTime, long endTime) throws RemoteException { + mSummary = mSession.getDeviceSummaryForNetwork(mTemplate, startTime, endTime); + + // Setting enumeration index beyond end to avoid accidental enumeration over data that does + // not belong to the calling user. + mEnumerationIndex = mSummary.size(); + + return getSummaryAggregate(); + } + + /** + * Collects summary results and sets summary enumeration mode. + * @param startTime + * @param endTime + * @throws RemoteException + */ + void startSummaryEnumeration(long startTime, long endTime) throws RemoteException { + mSummary = mSession.getSummaryForAllUid(mTemplate, startTime, endTime, false); + + mEnumerationIndex = 0; + } + + /** + * Collects history results for uid and resets history enumeration index. + */ + void startHistoryEnumeration(int uid) { + mHistory = null; + try { + mHistory = mSession.getHistoryForUid(mTemplate, uid, NetworkStats.SET_ALL, + NetworkStats.TAG_NONE, NetworkStatsHistory.FIELD_ALL); + setSingleUid(uid); + } catch (RemoteException e) { + Log.w(TAG, e); + // Leaving mHistory null + } + mEnumerationIndex = 0; + } + + /** + * Starts uid enumeration for current user. + * @throws RemoteException + */ + void startUserUidEnumeration() throws RemoteException { + setUidEnumeration(mSession.getRelevantUids()); + stepHistory(); + } + + /** + * Steps to next uid in enumeration and collects history for that. + */ + private void stepHistory(){ + if (hasNextUid()) { + stepUid(); + mHistory = null; + try { + mHistory = mSession.getHistoryForUid(mTemplate, getUid(), NetworkStats.SET_ALL, + NetworkStats.TAG_NONE, NetworkStatsHistory.FIELD_ALL); + } catch (RemoteException e) { + Log.w(TAG, e); + // Leaving mHistory null + } + mEnumerationIndex = 0; + } + } + + private void fillBucketFromSummaryEntry(Bucket bucketOut) { + bucketOut.mUid = Bucket.convertUid(mRecycledSummaryEntry.uid); + bucketOut.mState = Bucket.convertState(mRecycledSummaryEntry.set); + bucketOut.mBeginTimeStamp = mStartTimeStamp; + bucketOut.mEndTimeStamp = mEndTimeStamp; + bucketOut.mRxBytes = mRecycledSummaryEntry.rxBytes; + bucketOut.mRxPackets = mRecycledSummaryEntry.rxPackets; + bucketOut.mTxBytes = mRecycledSummaryEntry.txBytes; + bucketOut.mTxPackets = mRecycledSummaryEntry.txPackets; + } + + /** + * Getting the next item in summary enumeration. + * @param bucketOut Next item will be set here. + * @return true if a next item could be set. + */ + private boolean getNextSummaryBucket(Bucket bucketOut) { + if (bucketOut != null && mEnumerationIndex < mSummary.size()) { + mRecycledSummaryEntry = mSummary.getValues(mEnumerationIndex++, mRecycledSummaryEntry); + fillBucketFromSummaryEntry(bucketOut); + return true; + } + return false; + } + + Bucket getSummaryAggregate() { + if (mSummary == null) { + return null; + } + Bucket bucket = new Bucket(); + if (mRecycledSummaryEntry == null) { + mRecycledSummaryEntry = new NetworkStats.Entry(); + } + mSummary.getTotal(mRecycledSummaryEntry); + fillBucketFromSummaryEntry(bucket); + return bucket; + } + /** + * Getting the next item in a history enumeration. + * @param bucketOut Next item will be set here. + * @return true if a next item could be set. + */ + private boolean getNextHistoryBucket(Bucket bucketOut) { + if (bucketOut != null && mHistory != null) { + if (mEnumerationIndex < mHistory.size()) { + mRecycledHistoryEntry = mHistory.getValues(mEnumerationIndex++, + mRecycledHistoryEntry); + bucketOut.mUid = Bucket.convertUid(getUid()); + bucketOut.mState = Bucket.STATE_ALL; + bucketOut.mBeginTimeStamp = mRecycledHistoryEntry.bucketStart; + bucketOut.mEndTimeStamp = mRecycledHistoryEntry.bucketStart + + mRecycledHistoryEntry.bucketDuration; + bucketOut.mRxBytes = mRecycledHistoryEntry.rxBytes; + bucketOut.mRxPackets = mRecycledHistoryEntry.rxPackets; + bucketOut.mTxBytes = mRecycledHistoryEntry.txBytes; + bucketOut.mTxPackets = mRecycledHistoryEntry.txPackets; + return true; + } else if (hasNextUid()) { + stepHistory(); + return getNextHistoryBucket(bucketOut); + } + } + return false; + } + + // ------------------ UID LOGIC------------------------ + + private boolean isUidEnumeration() { + return mUids != null; + } + + private boolean hasNextUid() { + return isUidEnumeration() && (mUidOrUidIndex + 1) < mUids.length; + } + + private int getUid() { + // Check if uid enumeration. + if (isUidEnumeration()) { + if (mUidOrUidIndex < 0 || mUidOrUidIndex >= mUids.length) { + throw new IndexOutOfBoundsException( + "Index=" + mUidOrUidIndex + " mUids.length=" + mUids.length); + } + return mUids[mUidOrUidIndex]; + } + // Single uid mode. + return mUidOrUidIndex; + } + + private void setSingleUid(int uid) { + mUidOrUidIndex = uid; + } + + private void setUidEnumeration(int[] uids) { + mUids = uids; + mUidOrUidIndex = -1; + } + + private void stepUid() { + if (mUids != null) { + ++mUidOrUidIndex; + } + } +} diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java index 7eae439..0106686 100644 --- a/core/java/android/bluetooth/le/ScanSettings.java +++ b/core/java/android/bluetooth/le/ScanSettings.java @@ -25,6 +25,13 @@ import android.os.Parcelable; * parameters for the scan. */ public final class ScanSettings implements Parcelable { + + /** + * A special Bluetooth LE scan mode. Applications using this scan mode will passively listen for + * other scan results without starting BLE scans themselves. + */ + public static final int SCAN_MODE_OPPORTUNISTIC = -1; + /** * Perform Bluetooth LE scan in low power mode. This is the default scan mode as it consumes the * least power. @@ -177,7 +184,7 @@ public final class ScanSettings implements Parcelable { * @throws IllegalArgumentException If the {@code scanMode} is invalid. */ public Builder setScanMode(int scanMode) { - if (scanMode < SCAN_MODE_LOW_POWER || scanMode > SCAN_MODE_LOW_LATENCY) { + if (scanMode < SCAN_MODE_OPPORTUNISTIC || scanMode > SCAN_MODE_LOW_LATENCY) { throw new IllegalArgumentException("invalid scan mode " + scanMode); } mScanMode = scanMode; diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 39a70be..e9d4e59 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2149,7 +2149,7 @@ public abstract class Context { CONNECTIVITY_SERVICE, //@hide: UPDATE_LOCK_SERVICE, //@hide: NETWORKMANAGEMENT_SERVICE, - //@hide: NETWORK_STATS_SERVICE, + NETWORK_STATS_SERVICE, //@hide: NETWORK_POLICY_SERVICE, WIFI_SERVICE, WIFI_PASSPOINT_SERVICE, @@ -2259,6 +2259,9 @@ public abstract class Context { * <dd> A {@link android.os.BatteryManager} for managing battery state * <dt> {@link #JOB_SCHEDULER_SERVICE} ("taskmanager") * <dd> A {@link android.app.job.JobScheduler} for managing scheduled tasks + * <dt> {@link #NETWORK_STATS_SERVICE} ("netstats") + * <dd> A {@link android.app.usage.NetworkStatsManager NetworkStatsManager} for querying network + * usage statistics. * </dl> * * <p>Note: System services obtained via this API may be closely associated with @@ -2316,6 +2319,8 @@ public abstract class Context { * @see android.os.BatteryManager * @see #JOB_SCHEDULER_SERVICE * @see android.app.job.JobScheduler + * @see #NETWORK_STATS_SERVICE + * @see android.app.usage.NetworkStatsManager */ public abstract Object getSystemService(@ServiceName @NonNull String name); @@ -2334,7 +2339,8 @@ public abstract class Context { * {@link android.telephony.TelephonyManager}, {@link android.telephony.SubscriptionManager}, * {@link android.view.inputmethod.InputMethodManager}, * {@link android.app.UiModeManager}, {@link android.app.DownloadManager}, - * {@link android.os.BatteryManager}, {@link android.app.job.JobScheduler}. + * {@link android.os.BatteryManager}, {@link android.app.job.JobScheduler}, + * {@link android.app.usage.NetworkStatsManager}. * </p><p> * Note: System services obtained via this API may be closely associated with * the Context in which they are obtained from. In general, do not share the @@ -2563,7 +2569,13 @@ public abstract class Context { */ public static final String NETWORKMANAGEMENT_SERVICE = "network_management"; - /** {@hide} */ + /** + * Use with {@link #getSystemService} to retrieve a {@link + * android.app.usage.NetworkStatsManager} for querying network usage stats. + * + * @see #getSystemService + * @see android.app.usage.NetworkStatsManager + */ public static final String NETWORK_STATS_SERVICE = "netstats"; /** {@hide} */ public static final String NETWORK_POLICY_SERVICE = "netpolicy"; @@ -2819,7 +2831,7 @@ public abstract class Context { /** * Use with {@link #getSystemService} to retrieve a - * {@link android.bluetooth.BluetoothAdapter} for using Bluetooth. + * {@link android.bluetooth.BluetoothManager} for using Bluetooth. * * @see #getSystemService */ diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 9be96a1..030b770 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1502,6 +1502,66 @@ public class Intent implements Parcelable, Cloneable { */ public static final String METADATA_SETUP_VERSION = "android.SETUP_VERSION"; + /** + * Activity action: Launch UI to manage the permissions of an app. + * <p> + * Input: {@link #EXTRA_PACKAGE_NAME} specifies the package whose permissions + * will be managed by the launched UI. + * </p> + * <p> + * Output: Nothing. + * </p> + * + * @see #EXTRA_PACKAGE_NAME + * + * @hide + */ + @SystemApi + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_MANAGE_APP_PERMISSIONS = + "android.intent.action.MANAGE_APP_PERMISSIONS"; + + /** + * Intent extra: An app package name. + * <p> + * Type: String + * </p>S + * + * @hide + */ + @SystemApi + public static final String EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME"; + + /** + * Activity action: Launch UI to manage which apps have a given permission. + * <p> + * Input: {@link #EXTRA_PERMISSION_NAME} specifies the permission access + * to which will be managed by the launched UI. + * </p> + * <p> + * Output: Nothing. + * </p> + * + * @see #EXTRA_PERMISSION_NAME + * + * @hide + */ + @SystemApi + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_MANAGE_PERMISSION_APPS = + "android.intent.action.MANAGE_PERMISSION_APPS"; + + /** + * Intent extra: The name of a permission. + * <p> + * Type: String + * </p> + * + * @hide + */ + @SystemApi + public static final String EXTRA_PERMISSION_NAME = "android.intent.extra.PERMISSION_NAME"; + // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Standard intent broadcast actions (see action variable). diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 8f17845..2496e45 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -340,8 +340,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * cleartext network traffic, in which case platform components (e.g., HTTP stacks, * {@code WebView}, {@code MediaPlayer}) will refuse app's requests to use cleartext traffic. * Third-party libraries are encouraged to honor this flag as well. - * - * @hide */ public static final int FLAG_USES_CLEARTEXT_TRAFFIC = 1<<27; @@ -379,7 +377,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * {@link #FLAG_LARGE_HEAP}, {@link #FLAG_STOPPED}, * {@link #FLAG_SUPPORTS_RTL}, {@link #FLAG_INSTALLED}, * {@link #FLAG_IS_DATA_ONLY}, {@link #FLAG_IS_GAME}, - * {@link #FLAG_FULL_BACKUP_ONLY}, {@link #FLAG_MULTIARCH}. + * {@link #FLAG_FULL_BACKUP_ONLY}, {@link #FLAG_USES_CLEARTEXT_TRAFFIC}, + * {@link #FLAG_MULTIARCH}. */ public int flags = 0; @@ -655,7 +654,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { } pw.println(prefix + "dataDir=" + dataDir); if (sharedLibraryFiles != null) { - pw.println(prefix + "sharedLibraryFiles=" + sharedLibraryFiles); + pw.println(prefix + "sharedLibraryFiles=" + Arrays.toString(sharedLibraryFiles)); } pw.println(prefix + "enabled=" + enabled + " targetSdkVersion=" + targetSdkVersion + " versionCode=" + versionCode); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index e5859d0..212cf6d 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -376,16 +376,6 @@ public class PackageParser { return path.endsWith(".apk"); } - /* - public static PackageInfo generatePackageInfo(PackageParser.Package p, - int gids[], int flags, long firstInstallTime, long lastUpdateTime, - HashSet<String> grantedPermissions) { - PackageUserState state = new PackageUserState(); - return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime, - grantedPermissions, state, UserHandle.getCallingUserId()); - } - */ - /** * Generate and return the {@link PackageInfo} for a parsed package. * @@ -394,7 +384,7 @@ public class PackageParser { */ public static PackageInfo generatePackageInfo(PackageParser.Package p, int gids[], int flags, long firstInstallTime, long lastUpdateTime, - ArraySet<String> grantedPermissions, PackageUserState state) { + Set<String> grantedPermissions, PackageUserState state) { return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime, grantedPermissions, state, UserHandle.getCallingUserId()); @@ -574,7 +564,7 @@ public class PackageParser { for (int i=0; i<N; i++) { final String perm = p.requestedPermissions.get(i); pi.requestedPermissions[i] = perm; - // The notion of requried permissions is deprecated but for compatibility. + // The notion of required permissions is deprecated but for compatibility. pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED; if (grantedPermissions != null && grantedPermissions.contains(perm)) { pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED; diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 95ad57e..44018ff 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -111,12 +111,12 @@ public class Resources { // single-threaded, and after that these are immutable. private static final LongSparseArray<ConstantState>[] sPreloadedDrawables; private static final LongSparseArray<ConstantState> sPreloadedColorDrawables - = new LongSparseArray<ConstantState>(); + = new LongSparseArray<>(); private static final LongSparseArray<ColorStateListFactory> sPreloadedColorStateLists - = new LongSparseArray<ColorStateListFactory>(); + = new LongSparseArray<>(); // Pool of TypedArrays targeted to this Resources object. - final SynchronizedPool<TypedArray> mTypedArrayPool = new SynchronizedPool<TypedArray>(5); + final SynchronizedPool<TypedArray> mTypedArrayPool = new SynchronizedPool<>(5); // Used by BridgeResources in layoutlib static Resources mSystem = null; @@ -128,21 +128,19 @@ public class Resources { private final Object mAccessLock = new Object(); private final Configuration mTmpConfig = new Configuration(); private final ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> mDrawableCache = - new ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>>(); + new ArrayMap<>(); private final ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> mColorDrawableCache = - new ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>>(); + new ArrayMap<>(); private final ConfigurationBoundResourceCache<ColorStateList> mColorStateListCache = - new ConfigurationBoundResourceCache<ColorStateList>(this); + new ConfigurationBoundResourceCache<>(this); private final ConfigurationBoundResourceCache<Animator> mAnimatorCache = - new ConfigurationBoundResourceCache<Animator>(this); + new ConfigurationBoundResourceCache<>(this); private final ConfigurationBoundResourceCache<StateListAnimator> mStateListAnimatorCache = - new ConfigurationBoundResourceCache<StateListAnimator>(this); + new ConfigurationBoundResourceCache<>(this); private TypedValue mTmpValue = new TypedValue(); private boolean mPreloading; - private TypedArray mCachedStyledAttributes = null; - private int mLastCachedXmlBlockIndex = -1; private final int[] mCachedXmlBlockIds = { 0, 0, 0, 0 }; private final XmlBlock[] mCachedXmlBlocks = new XmlBlock[4]; @@ -157,8 +155,8 @@ public class Resources { static { sPreloadedDrawables = new LongSparseArray[2]; - sPreloadedDrawables[0] = new LongSparseArray<ConstantState>(); - sPreloadedDrawables[1] = new LongSparseArray<ConstantState>(); + sPreloadedDrawables[0] = new LongSparseArray<>(); + sPreloadedDrawables[1] = new LongSparseArray<>(); } /** @@ -1876,7 +1874,7 @@ public class Resources { // the framework. mCompatibilityInfo.applyToDisplayMetrics(mMetrics); - int configChanges = calcConfigChanges(config); + final int configChanges = calcConfigChanges(config); if (mConfiguration.locale == null) { mConfiguration.locale = Locale.getDefault(); mConfiguration.setLayoutDirection(mConfiguration.locale); @@ -1891,7 +1889,8 @@ public class Resources { if (mConfiguration.locale != null) { locale = adjustLanguageTag(mConfiguration.locale.toLanguageTag()); } - int width, height; + + final int width, height; if (mMetrics.widthPixels >= mMetrics.heightPixels) { width = mMetrics.widthPixels; height = mMetrics.heightPixels; @@ -1901,12 +1900,15 @@ public class Resources { //noinspection SuspiciousNameCombination height = mMetrics.widthPixels; } - int keyboardHidden = mConfiguration.keyboardHidden; - if (keyboardHidden == Configuration.KEYBOARDHIDDEN_NO - && mConfiguration.hardKeyboardHidden - == Configuration.HARDKEYBOARDHIDDEN_YES) { + + final int keyboardHidden; + if (mConfiguration.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO + && mConfiguration.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) { keyboardHidden = Configuration.KEYBOARDHIDDEN_SOFT; + } else { + keyboardHidden = mConfiguration.keyboardHidden; } + mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc, locale, mConfiguration.orientation, mConfiguration.touchscreen, @@ -2508,10 +2510,10 @@ public class Resources { // Clean out the caches before we add more. This shouldn't // happen very often. pruneCaches(caches); - themedCache = new LongSparseArray<WeakReference<ConstantState>>(1); + themedCache = new LongSparseArray<>(1); caches.put(themeKey, themedCache); } - themedCache.put(key, new WeakReference<ConstantState>(cs)); + themedCache.put(key, new WeakReference<>(cs)); } } } @@ -2830,15 +2832,6 @@ public class Resources { + Integer.toHexString(id)); } - /*package*/ void recycleCachedStyledAttributes(TypedArray attrs) { - synchronized (mAccessLock) { - final TypedArray cached = mCachedStyledAttributes; - if (cached == null || cached.mData.length < attrs.mData.length) { - mCachedStyledAttributes = attrs; - } - } - } - /** * Obtains styled attributes from the theme, if available, or unstyled * resources if the theme is null. diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java index a6c3ea4..88fa339 100644 --- a/core/java/android/hardware/SystemSensorManager.java +++ b/core/java/android/hardware/SystemSensorManager.java @@ -54,11 +54,13 @@ public class SystemSensorManager extends SensorManager { // Looper associated with the context in which this instance was created. private final Looper mMainLooper; private final int mTargetSdkLevel; + private final String mPackageName; /** {@hide} */ public SystemSensorManager(Context context, Looper mainLooper) { mMainLooper = mainLooper; mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion; + mPackageName = context.getPackageName(); synchronized(sSensorModuleLock) { if (!sSensorModuleInitialized) { sSensorModuleInitialized = true; @@ -117,14 +119,14 @@ public class SystemSensorManager extends SensorManager { if (queue == null) { Looper looper = (handler != null) ? handler.getLooper() : mMainLooper; queue = new SensorEventQueue(listener, looper, this); - if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags)) { + if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs)) { queue.dispose(); return false; } mSensorListeners.put(listener, queue); return true; } else { - return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags); + return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs); } } } @@ -165,14 +167,14 @@ public class SystemSensorManager extends SensorManager { TriggerEventQueue queue = mTriggerListeners.get(listener); if (queue == null) { queue = new TriggerEventQueue(listener, mMainLooper, this); - if (!queue.addSensor(sensor, 0, 0, 0)) { + if (!queue.addSensor(sensor, 0, 0)) { queue.dispose(); return false; } mTriggerListeners.put(listener, queue); return true; } else { - return queue.addSensor(sensor, 0, 0, 0); + return queue.addSensor(sensor, 0, 0); } } } @@ -223,9 +225,9 @@ public class SystemSensorManager extends SensorManager { */ private static abstract class BaseEventQueue { private native long nativeInitBaseEventQueue(BaseEventQueue eventQ, MessageQueue msgQ, - float[] scratch); + float[] scratch, String packageName); private static native int nativeEnableSensor(long eventQ, int handle, int rateUs, - int maxBatchReportLatencyUs, int reservedFlags); + int maxBatchReportLatencyUs); private static native int nativeDisableSensor(long eventQ, int handle); private static native void nativeDestroySensorEventQueue(long eventQ); private static native int nativeFlushSensor(long eventQ); @@ -238,7 +240,8 @@ public class SystemSensorManager extends SensorManager { protected final SystemSensorManager mManager; BaseEventQueue(Looper looper, SystemSensorManager manager) { - nSensorEventQueue = nativeInitBaseEventQueue(this, looper.getQueue(), mScratch); + nSensorEventQueue = nativeInitBaseEventQueue(this, looper.getQueue(), mScratch, + manager.mPackageName); mCloseGuard.open("dispose"); mManager = manager; } @@ -248,7 +251,7 @@ public class SystemSensorManager extends SensorManager { } public boolean addSensor( - Sensor sensor, int delayUs, int maxBatchReportLatencyUs, int reservedFlags) { + Sensor sensor, int delayUs, int maxBatchReportLatencyUs) { // Check if already present. int handle = sensor.getHandle(); if (mActiveSensors.get(handle)) return false; @@ -256,10 +259,10 @@ public class SystemSensorManager extends SensorManager { // Get ready to receive events before calling enable. mActiveSensors.put(handle, true); addSensorEvent(sensor); - if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags) != 0) { + if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs) != 0) { // Try continuous mode if batching fails. if (maxBatchReportLatencyUs == 0 || - maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0, 0) != 0) { + maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0) != 0) { removeSensor(sensor, false); return false; } @@ -328,11 +331,11 @@ public class SystemSensorManager extends SensorManager { } private int enableSensor( - Sensor sensor, int rateUs, int maxBatchReportLatencyUs, int reservedFlags) { + Sensor sensor, int rateUs, int maxBatchReportLatencyUs) { if (nSensorEventQueue == 0) throw new NullPointerException(); if (sensor == null) throw new NullPointerException(); return nativeEnableSensor(nSensorEventQueue, sensor.getHandle(), rateUs, - maxBatchReportLatencyUs, reservedFlags); + maxBatchReportLatencyUs); } private int disableSensor(Sensor sensor) { diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 34a0727..a0e2bf8 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -2337,7 +2337,7 @@ public class ConnectivityManager { * successfully finding a network for the applications request. Retrieve it with * {@link android.content.Intent#getParcelableExtra(String)}. * <p> - * Note that if you intend to invoke (@link #setProcessDefaultNetwork(Network)) or + * Note that if you intend to invoke {@link #setProcessDefaultNetwork} or * {@link Network#openConnection(java.net.URL)} then you must get a * ConnectivityManager instance before doing so. */ diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 2c3881c..6436e42 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -27,6 +27,14 @@ interface INetworkStatsService { /** Start a statistics query session. */ INetworkStatsSession openSession(); + /** Start a statistics query session. If calling package is profile or device owner then it is + * granted automatic access if apiLevel is NetworkStatsManager.API_LEVEL_DPC_ALLOWED. If + * apiLevel is at least NetworkStatsManager.API_LEVEL_REQUIRES_PACKAGE_USAGE_STATS then + * PACKAGE_USAGE_STATS permission is always checked. If PACKAGE_USAGE_STATS is not granted + * READ_NETWORK_USAGE_STATS is checked for. + */ + INetworkStatsSession openSessionForUsageStats(String callingPackage); + /** Return network layer usage total for traffic that matches template. */ long getNetworkTotalBytes(in NetworkTemplate template, long start, long end); diff --git a/core/java/android/net/INetworkStatsSession.aidl b/core/java/android/net/INetworkStatsSession.aidl index 1596fa2..7bcb043 100644 --- a/core/java/android/net/INetworkStatsSession.aidl +++ b/core/java/android/net/INetworkStatsSession.aidl @@ -23,6 +23,9 @@ import android.net.NetworkTemplate; /** {@hide} */ interface INetworkStatsSession { + /** Return device aggregated network layer usage summary for traffic that matches template. */ + NetworkStats getDeviceSummaryForNetwork(in NetworkTemplate template, long start, long end); + /** Return network layer usage summary for traffic that matches template. */ NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end); /** Return historical network layer stats for traffic that matches template. */ @@ -33,6 +36,9 @@ interface INetworkStatsSession { /** Return historical network layer stats for specific UID traffic that matches template. */ NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int set, int tag, int fields); + /** Return array of uids that have stats and are accessible to the calling user */ + int[] getRelevantUids(); + void close(); } diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index a7f9c5b..8c8bfab 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -148,9 +148,9 @@ public final class NetworkCapabilities implements Parcelable { */ public static final int NET_CAPABILITY_TRUSTED = 14; - /* + /** * Indicates that this network is not a VPN. This capability is set by default and should be - * explicitly cleared when creating VPN networks. + * explicitly cleared for VPN networks. */ public static final int NET_CAPABILITY_NOT_VPN = 15; diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 0766253..77d7e0c 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -50,12 +50,19 @@ public class NetworkStats implements Parcelable { public static final int UID_ALL = -1; /** {@link #tag} value matching any tag. */ public static final int TAG_ALL = -1; - /** {@link #set} value when all sets combined. */ + /** {@link #set} value when all sets combined, not including debug sets. */ public static final int SET_ALL = -1; /** {@link #set} value where background data is accounted. */ public static final int SET_DEFAULT = 0; /** {@link #set} value where foreground data is accounted. */ public static final int SET_FOREGROUND = 1; + /** All {@link #set} value greater than SET_DEBUG_START are debug {@link #set} values. */ + public static final int SET_DEBUG_START = 1000; + /** Debug {@link #set} value when the VPN stats are moved in. */ + public static final int SET_DBG_VPN_IN = 1001; + /** Debug {@link #set} value when the VPN stats are moved out of a vpn UID. */ + public static final int SET_DBG_VPN_OUT = 1002; + /** {@link #tag} value for total data across all tags. */ public static final int TAG_NONE = 0; @@ -729,6 +736,10 @@ public class NetworkStats implements Parcelable { return "DEFAULT"; case SET_FOREGROUND: return "FOREGROUND"; + case SET_DBG_VPN_IN: + return "DBG_VPN_IN"; + case SET_DBG_VPN_OUT: + return "DBG_VPN_OUT"; default: return "UNKNOWN"; } @@ -745,12 +756,27 @@ public class NetworkStats implements Parcelable { return "def"; case SET_FOREGROUND: return "fg"; + case SET_DBG_VPN_IN: + return "vpnin"; + case SET_DBG_VPN_OUT: + return "vpnout"; default: return "unk"; } } /** + * @return true if the querySet matches the dataSet. + */ + public static boolean setMatches(int querySet, int dataSet) { + if (querySet == dataSet) { + return true; + } + // SET_ALL matches all non-debugging sets. + return querySet == SET_ALL && dataSet < SET_DEBUG_START; + } + + /** * Return text description of {@link #tag} value. */ public static String tagToString(int tag) { @@ -843,6 +869,9 @@ public class NetworkStats implements Parcelable { if (recycle.uid == UID_ALL) { throw new IllegalStateException( "Cannot adjust VPN accounting on an iface aggregated NetworkStats."); + } if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) { + throw new IllegalStateException( + "Cannot adjust VPN accounting on a NetworkStats containing SET_DBG_VPN_*"); } if (recycle.uid == tunUid && recycle.tag == TAG_NONE @@ -906,6 +935,9 @@ public class NetworkStats implements Parcelable { combineValues(tmpEntry); if (tag[i] == TAG_NONE) { moved.add(tmpEntry); + // Add debug info + tmpEntry.set = SET_DBG_VPN_IN; + combineValues(tmpEntry); } } } @@ -913,6 +945,13 @@ public class NetworkStats implements Parcelable { } private void deductTrafficFromVpnApp(int tunUid, String underlyingIface, Entry moved) { + // Add debug info + moved.uid = tunUid; + moved.set = SET_DBG_VPN_OUT; + moved.tag = TAG_NONE; + moved.iface = underlyingIface; + combineValues(moved); + // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than // the TAG_NONE traffic. int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE); diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 26e6b85..8b3ecae 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -29,6 +29,7 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.telephony.SignalStrength; import android.text.format.DateFormat; +import android.util.ArrayMap; import android.util.Printer; import android.util.SparseArray; import android.util.SparseIntArray; @@ -283,21 +284,21 @@ public abstract class BatteryStats implements Parcelable { * * @return a Map from Strings to Uid.Wakelock objects. */ - public abstract Map<String, ? extends Wakelock> getWakelockStats(); + public abstract ArrayMap<String, ? extends Wakelock> getWakelockStats(); /** * Returns a mapping containing sync statistics. * * @return a Map from Strings to Timer objects. */ - public abstract Map<String, ? extends Timer> getSyncStats(); + public abstract ArrayMap<String, ? extends Timer> getSyncStats(); /** * Returns a mapping containing scheduled job statistics. * * @return a Map from Strings to Timer objects. */ - public abstract Map<String, ? extends Timer> getJobStats(); + public abstract ArrayMap<String, ? extends Timer> getJobStats(); /** * The statistics associated with a particular wake lock. @@ -323,14 +324,14 @@ public abstract class BatteryStats implements Parcelable { * * @return a Map from Strings to Uid.Proc objects. */ - public abstract Map<String, ? extends Proc> getProcessStats(); + public abstract ArrayMap<String, ? extends Proc> getProcessStats(); /** * Returns a mapping containing package statistics. * * @return a Map from Strings to Uid.Pkg objects. */ - public abstract Map<String, ? extends Pkg> getPackageStats(); + public abstract ArrayMap<String, ? extends Pkg> getPackageStats(); /** * {@hide} @@ -501,17 +502,16 @@ public abstract class BatteryStats implements Parcelable { public static abstract class Pkg { /** - * Returns the number of times this package has done something that could wake up the - * device from sleep. - * - * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT. + * Returns information about all wakeup alarms that have been triggered for this + * package. The mapping keys are tag names for the alarms, the counter contains + * the number of times the alarm was triggered while on battery. */ - public abstract int getWakeups(int which); + public abstract ArrayMap<String, ? extends Counter> getWakeupAlarmStats(); /** * Returns a mapping containing service statistics. */ - public abstract Map<String, ? extends Serv> getServiceStats(); + public abstract ArrayMap<String, ? extends Serv> getServiceStats(); /** * The statistics associated with a particular service. @@ -1352,7 +1352,7 @@ public abstract class BatteryStats implements Parcelable { int idx = code&HistoryItem.EVENT_TYPE_MASK; HashMap<String, SparseIntArray> active = mActiveEvents[idx]; if (active == null) { - active = new HashMap<String, SparseIntArray>(); + active = new HashMap<>(); mActiveEvents[idx] = active; } SparseIntArray uids = active.get(name); @@ -2382,12 +2382,12 @@ public abstract class BatteryStats implements Parcelable { final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which); final long bluetoothOnTime = getBluetoothOnTime(rawRealtime, which); - StringBuilder sb = new StringBuilder(128); + final StringBuilder sb = new StringBuilder(128); - SparseArray<? extends Uid> uidStats = getUidStats(); + final SparseArray<? extends Uid> uidStats = getUidStats(); final int NU = uidStats.size(); - String category = STAT_NAMES[which]; + final String category = STAT_NAMES[which]; // Dump "battery" stat dumpLine(pw, 0 /* uid */, category, BATTERY_DATA, @@ -2402,37 +2402,35 @@ public abstract class BatteryStats implements Parcelable { long partialWakeLockTimeTotal = 0; for (int iu = 0; iu < NU; iu++) { - Uid u = uidStats.valueAt(iu); - - Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats(); - if (wakelocks.size() > 0) { - for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent - : wakelocks.entrySet()) { - Uid.Wakelock wl = ent.getValue(); - - Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL); - if (fullWakeTimer != null) { - fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(rawRealtime, - which); - } + final Uid u = uidStats.valueAt(iu); - Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL); - if (partialWakeTimer != null) { - partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked( - rawRealtime, which); - } + final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks + = u.getWakelockStats(); + for (int iw=wakelocks.size()-1; iw>=0; iw--) { + final Uid.Wakelock wl = wakelocks.valueAt(iw); + + final Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL); + if (fullWakeTimer != null) { + fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(rawRealtime, + which); + } + + final Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL); + if (partialWakeTimer != null) { + partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked( + rawRealtime, which); } } } - long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which); - long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which); - long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which); - long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which); - long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which); - long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which); - long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which); - long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which); + final long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which); + final long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which); + final long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which); + final long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which); + final long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which); + final long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which); + final long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which); + final long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which); // Dump network stats dumpLine(pw, 0 /* uid */, category, GLOBAL_NETWORK_DATA, @@ -2544,7 +2542,7 @@ public abstract class BatteryStats implements Parcelable { } if (reqUid < 0) { - Map<String, ? extends Timer> kernelWakelocks = getKernelWakelockStats(); + final Map<String, ? extends Timer> kernelWakelocks = getKernelWakelockStats(); if (kernelWakelocks.size() > 0) { for (Map.Entry<String, ? extends Timer> ent : kernelWakelocks.entrySet()) { sb.setLength(0); @@ -2553,7 +2551,7 @@ public abstract class BatteryStats implements Parcelable { sb.toString()); } } - Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats(); + final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats(); if (wakeupReasons.size() > 0) { for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) { // Not doing the regular wake lock formatting to remain compatible @@ -2566,10 +2564,10 @@ public abstract class BatteryStats implements Parcelable { } } - BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly); + final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly); helper.create(this); helper.refreshStats(which, UserHandle.USER_ALL); - List<BatterySipper> sippers = helper.getUsageList(); + final List<BatterySipper> sippers = helper.getUsageList(); if (sippers != null && sippers.size() > 0) { dumpLine(pw, 0 /* uid */, category, POWER_USE_SUMMARY_DATA, BatteryStatsHelper.makemAh(helper.getPowerProfile().getBatteryCapacity()), @@ -2577,7 +2575,7 @@ public abstract class BatteryStats implements Parcelable { BatteryStatsHelper.makemAh(helper.getMinDrainedPower()), BatteryStatsHelper.makemAh(helper.getMaxDrainedPower())); for (int i=0; i<sippers.size(); i++) { - BatterySipper bs = sippers.get(i); + final BatterySipper bs = sippers.get(i); int uid = 0; String label; switch (bs.drainType) { @@ -2629,22 +2627,22 @@ public abstract class BatteryStats implements Parcelable { if (reqUid >= 0 && uid != reqUid) { continue; } - Uid u = uidStats.valueAt(iu); + final Uid u = uidStats.valueAt(iu); // Dump Network stats per uid, if any - long mobileBytesRx = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which); - long mobileBytesTx = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which); - long wifiBytesRx = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which); - long wifiBytesTx = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which); - long mobilePacketsRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which); - long mobilePacketsTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which); - long mobileActiveTime = u.getMobileRadioActiveTime(which); - int mobileActiveCount = u.getMobileRadioActiveCount(which); - long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which); - long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which); - long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which); - long wifiScanTime = u.getWifiScanTime(rawRealtime, which); - int wifiScanCount = u.getWifiScanCount(which); - long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which); + final long mobileBytesRx = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which); + final long mobileBytesTx = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which); + final long wifiBytesRx = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which); + final long wifiBytesTx = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which); + final long mobilePacketsRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which); + final long mobilePacketsTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which); + final long mobileActiveTime = u.getMobileRadioActiveTime(which); + final int mobileActiveCount = u.getMobileRadioActiveCount(which); + final long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which); + final long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which); + final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which); + final long wifiScanTime = u.getWifiScanTime(rawRealtime, which); + final int wifiScanCount = u.getWifiScanCount(which); + final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which); if (mobileBytesRx > 0 || mobileBytesTx > 0 || wifiBytesRx > 0 || wifiBytesTx > 0 || mobilePacketsRx > 0 || mobilePacketsTx > 0 || wifiPacketsRx > 0 @@ -2675,93 +2673,90 @@ public abstract class BatteryStats implements Parcelable { } } - Map<String, ? extends Uid.Wakelock> wakelocks = u.getWakelockStats(); - if (wakelocks.size() > 0) { - for (Map.Entry<String, ? extends Uid.Wakelock> ent : wakelocks.entrySet()) { - Uid.Wakelock wl = ent.getValue(); - String linePrefix = ""; - sb.setLength(0); - linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL), - rawRealtime, "f", which, linePrefix); - linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), - rawRealtime, "p", which, linePrefix); - linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), - rawRealtime, "w", which, linePrefix); - - // Only log if we had at lease one wakelock... - if (sb.length() > 0) { - String name = ent.getKey(); - if (name.indexOf(',') >= 0) { - name = name.replace(',', '_'); - } - dumpLine(pw, uid, category, WAKELOCK_DATA, name, sb.toString()); + final ArrayMap<String, ? extends Uid.Wakelock> wakelocks = u.getWakelockStats(); + for (int iw=wakelocks.size()-1; iw>=0; iw--) { + final Uid.Wakelock wl = wakelocks.valueAt(iw); + String linePrefix = ""; + sb.setLength(0); + linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL), + rawRealtime, "f", which, linePrefix); + linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), + rawRealtime, "p", which, linePrefix); + linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), + rawRealtime, "w", which, linePrefix); + + // Only log if we had at lease one wakelock... + if (sb.length() > 0) { + String name = wakelocks.keyAt(iw); + if (name.indexOf(',') >= 0) { + name = name.replace(',', '_'); } + dumpLine(pw, uid, category, WAKELOCK_DATA, name, sb.toString()); } } - Map<String, ? extends Timer> syncs = u.getSyncStats(); - if (syncs.size() > 0) { - for (Map.Entry<String, ? extends Timer> ent : syncs.entrySet()) { - Timer timer = ent.getValue(); - // Convert from microseconds to milliseconds with rounding - long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; - int count = timer.getCountLocked(which); - if (totalTime != 0) { - dumpLine(pw, uid, category, SYNC_DATA, ent.getKey(), totalTime, count); - } + final ArrayMap<String, ? extends Timer> syncs = u.getSyncStats(); + for (int isy=syncs.size()-1; isy>=0; isy--) { + final Timer timer = syncs.valueAt(isy); + // Convert from microseconds to milliseconds with rounding + final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; + final int count = timer.getCountLocked(which); + if (totalTime != 0) { + dumpLine(pw, uid, category, SYNC_DATA, syncs.keyAt(isy), totalTime, count); } } - Map<String, ? extends Timer> jobs = u.getJobStats(); - if (jobs.size() > 0) { - for (Map.Entry<String, ? extends Timer> ent : jobs.entrySet()) { - Timer timer = ent.getValue(); - // Convert from microseconds to milliseconds with rounding - long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; - int count = timer.getCountLocked(which); - if (totalTime != 0) { - dumpLine(pw, uid, category, JOB_DATA, ent.getKey(), totalTime, count); - } + final ArrayMap<String, ? extends Timer> jobs = u.getJobStats(); + for (int ij=jobs.size()-1; ij>=0; ij--) { + final Timer timer = jobs.valueAt(ij); + // Convert from microseconds to milliseconds with rounding + final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; + final int count = timer.getCountLocked(which); + if (totalTime != 0) { + dumpLine(pw, uid, category, JOB_DATA, jobs.keyAt(ij), totalTime, count); } } - SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats(); - int NSE = sensors.size(); + final SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats(); + final int NSE = sensors.size(); for (int ise=0; ise<NSE; ise++) { - Uid.Sensor se = sensors.valueAt(ise); - int sensorNumber = sensors.keyAt(ise); - Timer timer = se.getSensorTime(); + final Uid.Sensor se = sensors.valueAt(ise); + final int sensorNumber = sensors.keyAt(ise); + final Timer timer = se.getSensorTime(); if (timer != null) { // Convert from microseconds to milliseconds with rounding - long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; - int count = timer.getCountLocked(which); + final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) + / 1000; + final int count = timer.getCountLocked(which); if (totalTime != 0) { dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count); } } } - Timer vibTimer = u.getVibratorOnTimer(); + final Timer vibTimer = u.getVibratorOnTimer(); if (vibTimer != null) { // Convert from microseconds to milliseconds with rounding - long totalTime = (vibTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; - int count = vibTimer.getCountLocked(which); + final long totalTime = (vibTimer.getTotalTimeLocked(rawRealtime, which) + 500) + / 1000; + final int count = vibTimer.getCountLocked(which); if (totalTime != 0) { dumpLine(pw, uid, category, VIBRATOR_DATA, totalTime, count); } } - Timer fgTimer = u.getForegroundActivityTimer(); + final Timer fgTimer = u.getForegroundActivityTimer(); if (fgTimer != null) { // Convert from microseconds to milliseconds with rounding - long totalTime = (fgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; - int count = fgTimer.getCountLocked(which); + final long totalTime = (fgTimer.getTotalTimeLocked(rawRealtime, which) + 500) + / 1000; + final int count = fgTimer.getCountLocked(which); if (totalTime != 0) { dumpLine(pw, uid, category, FOREGROUND_DATA, totalTime, count); } } - Object[] stateTimes = new Object[Uid.NUM_PROCESS_STATE]; + final Object[] stateTimes = new Object[Uid.NUM_PROCESS_STATE]; long totalStateTime = 0; for (int ips=0; ips<Uid.NUM_PROCESS_STATE; ips++) { totalStateTime += u.getProcessStateTime(ips, rawRealtime, which); @@ -2771,50 +2766,48 @@ public abstract class BatteryStats implements Parcelable { dumpLine(pw, uid, category, STATE_TIME_DATA, stateTimes); } - Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats(); - if (processStats.size() > 0) { - for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent - : processStats.entrySet()) { - Uid.Proc ps = ent.getValue(); - - final long userMillis = ps.getUserTime(which); - final long systemMillis = ps.getSystemTime(which); - final long foregroundMillis = ps.getForegroundTime(which); - final int starts = ps.getStarts(which); - final int numCrashes = ps.getNumCrashes(which); - final int numAnrs = ps.getNumAnrs(which); - - if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0 - || starts != 0 || numAnrs != 0 || numCrashes != 0) { - dumpLine(pw, uid, category, PROCESS_DATA, ent.getKey(), userMillis, - systemMillis, foregroundMillis, starts, numAnrs, numCrashes); - } + final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats + = u.getProcessStats(); + for (int ipr=processStats.size()-1; ipr>=0; ipr--) { + final Uid.Proc ps = processStats.valueAt(ipr); + + final long userMillis = ps.getUserTime(which); + final long systemMillis = ps.getSystemTime(which); + final long foregroundMillis = ps.getForegroundTime(which); + final int starts = ps.getStarts(which); + final int numCrashes = ps.getNumCrashes(which); + final int numAnrs = ps.getNumAnrs(which); + + if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0 + || starts != 0 || numAnrs != 0 || numCrashes != 0) { + dumpLine(pw, uid, category, PROCESS_DATA, processStats.keyAt(ipr), userMillis, + systemMillis, foregroundMillis, starts, numAnrs, numCrashes); } } - Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats(); - if (packageStats.size() > 0) { - for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent - : packageStats.entrySet()) { - - Uid.Pkg ps = ent.getValue(); - int wakeups = ps.getWakeups(which); - Map<String, ? extends Uid.Pkg.Serv> serviceStats = ps.getServiceStats(); - for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent - : serviceStats.entrySet()) { - BatteryStats.Uid.Pkg.Serv ss = sent.getValue(); - long startTime = ss.getStartTime(batteryUptime, which); - int starts = ss.getStarts(which); - int launches = ss.getLaunches(which); - if (startTime != 0 || starts != 0 || launches != 0) { - dumpLine(pw, uid, category, APK_DATA, - wakeups, // wakeup alarms - ent.getKey(), // Apk - sent.getKey(), // service - startTime / 1000, // time spent started, in ms - starts, - launches); - } + final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats + = u.getPackageStats(); + for (int ipkg=packageStats.size()-1; ipkg>=0; ipkg--) { + final Uid.Pkg ps = packageStats.valueAt(ipkg); + int wakeups = 0; + final ArrayMap<String, ? extends Counter> alarms = ps.getWakeupAlarmStats(); + for (int iwa=alarms.size()-1; iwa>=0; iwa--) { + wakeups += alarms.valueAt(iwa).getCountLocked(which); + } + final ArrayMap<String, ? extends Uid.Pkg.Serv> serviceStats = ps.getServiceStats(); + for (int isvc=serviceStats.size()-1; isvc>=0; isvc--) { + final BatteryStats.Uid.Pkg.Serv ss = serviceStats.valueAt(isvc); + final long startTime = ss.getStartTime(batteryUptime, which); + final int starts = ss.getStarts(which); + final int launches = ss.getLaunches(which); + if (startTime != 0 || starts != 0 || launches != 0) { + dumpLine(pw, uid, category, APK_DATA, + wakeups, // wakeup alarms + packageStats.keyAt(ipkg), // Apk + serviceStats.keyAt(isvc), // service + startTime / 1000, // time spent started, in ms + starts, + launches); } } } @@ -2863,9 +2856,9 @@ public abstract class BatteryStats implements Parcelable { final long batteryTimeRemaining = computeBatteryTimeRemaining(rawRealtime); final long chargeTimeRemaining = computeChargeTimeRemaining(rawRealtime); - StringBuilder sb = new StringBuilder(128); + final StringBuilder sb = new StringBuilder(128); - SparseArray<? extends Uid> uidStats = getUidStats(); + final SparseArray<? extends Uid> uidStats = getUidStats(); final int NU = uidStats.size(); sb.setLength(0); @@ -2992,7 +2985,7 @@ public abstract class BatteryStats implements Parcelable { sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime)); sb.append(") "); sb.append(getPhoneOnCount(which)); sb.append("x"); } - int connChanges = getNumConnectivityChange(which); + final int connChanges = getNumConnectivityChange(which); if (connChanges != 0) { pw.print(prefix); pw.print(" Connectivity changes: "); pw.println(connChanges); @@ -3002,50 +2995,48 @@ public abstract class BatteryStats implements Parcelable { long fullWakeLockTimeTotalMicros = 0; long partialWakeLockTimeTotalMicros = 0; - final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>(); + final ArrayList<TimerEntry> timers = new ArrayList<>(); for (int iu = 0; iu < NU; iu++) { - Uid u = uidStats.valueAt(iu); - - Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats(); - if (wakelocks.size() > 0) { - for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent - : wakelocks.entrySet()) { - Uid.Wakelock wl = ent.getValue(); - - Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL); - if (fullWakeTimer != null) { - fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked( - rawRealtime, which); - } + final Uid u = uidStats.valueAt(iu); - Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL); - if (partialWakeTimer != null) { - long totalTimeMicros = partialWakeTimer.getTotalTimeLocked( - rawRealtime, which); - if (totalTimeMicros > 0) { - if (reqUid < 0) { - // Only show the ordered list of all wake - // locks if the caller is not asking for data - // about a specific uid. - timers.add(new TimerEntry(ent.getKey(), u.getUid(), - partialWakeTimer, totalTimeMicros)); - } - partialWakeLockTimeTotalMicros += totalTimeMicros; + final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks + = u.getWakelockStats(); + for (int iw=wakelocks.size()-1; iw>=0; iw--) { + final Uid.Wakelock wl = wakelocks.valueAt(iw); + + final Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL); + if (fullWakeTimer != null) { + fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked( + rawRealtime, which); + } + + final Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL); + if (partialWakeTimer != null) { + final long totalTimeMicros = partialWakeTimer.getTotalTimeLocked( + rawRealtime, which); + if (totalTimeMicros > 0) { + if (reqUid < 0) { + // Only show the ordered list of all wake + // locks if the caller is not asking for data + // about a specific uid. + timers.add(new TimerEntry(wakelocks.keyAt(iw), u.getUid(), + partialWakeTimer, totalTimeMicros)); } + partialWakeLockTimeTotalMicros += totalTimeMicros; } } } } - long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which); - long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which); - long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which); - long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which); - long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which); - long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which); - long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which); - long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which); + final long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which); + final long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which); + final long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which); + final long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which); + final long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which); + final long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which); + final long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which); + final long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which); if (fullWakeLockTimeTotalMicros != 0) { sb.setLength(0); @@ -3242,9 +3233,9 @@ public abstract class BatteryStats implements Parcelable { if (!didOne) sb.append(" (no activity)"); pw.println(sb.toString()); - final long wifiIdleTimeMs = getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which); - final long wifiRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which); - final long wifiTxTimeMs = getBluetoothControllerActivity(CONTROLLER_TX_TIME, which); + final long wifiIdleTimeMs = getWifiControllerActivity(CONTROLLER_IDLE_TIME, which); + final long wifiRxTimeMs = getWifiControllerActivity(CONTROLLER_RX_TIME, which); + final long wifiTxTimeMs = getWifiControllerActivity(CONTROLLER_TX_TIME, which); final long wifiTotalTimeMs = wifiIdleTimeMs + wifiRxTimeMs + wifiTxTimeMs; sb.setLength(0); @@ -3367,7 +3358,7 @@ public abstract class BatteryStats implements Parcelable { pw.println(); } - BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly); + final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly); helper.create(this); helper.refreshStats(which, UserHandle.USER_ALL); List<BatterySipper> sippers = helper.getUsageList(); @@ -3382,7 +3373,7 @@ public abstract class BatteryStats implements Parcelable { } pw.println(); for (int i=0; i<sippers.size(); i++) { - BatterySipper bs = sippers.get(i); + final BatterySipper bs = sippers.get(i); switch (bs.drainType) { case IDLE: pw.print(prefix); pw.print(" Idle: "); printmAh(pw, bs.value); @@ -3439,7 +3430,7 @@ public abstract class BatteryStats implements Parcelable { pw.print(prefix); pw.println(" Per-app mobile ms per packet:"); long totalTime = 0; for (int i=0; i<sippers.size(); i++) { - BatterySipper bs = sippers.get(i); + final BatterySipper bs = sippers.get(i); sb.setLength(0); sb.append(prefix); sb.append(" Uid "); UserHandle.formatUid(sb, bs.uidObj.getUid()); @@ -3476,12 +3467,14 @@ public abstract class BatteryStats implements Parcelable { }; if (reqUid < 0) { - Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats(); + final Map<String, ? extends BatteryStats.Timer> kernelWakelocks + = getKernelWakelockStats(); if (kernelWakelocks.size() > 0) { - final ArrayList<TimerEntry> ktimers = new ArrayList<TimerEntry>(); - for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) { - BatteryStats.Timer timer = ent.getValue(); - long totalTimeMillis = computeWakeLock(timer, rawRealtime, which); + final ArrayList<TimerEntry> ktimers = new ArrayList<>(); + for (Map.Entry<String, ? extends BatteryStats.Timer> ent + : kernelWakelocks.entrySet()) { + final BatteryStats.Timer timer = ent.getValue(); + final long totalTimeMillis = computeWakeLock(timer, rawRealtime, which); if (totalTimeMillis > 0) { ktimers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis)); } @@ -3490,7 +3483,7 @@ public abstract class BatteryStats implements Parcelable { Collections.sort(ktimers, timerComparator); pw.print(prefix); pw.println(" All kernel wake locks:"); for (int i=0; i<ktimers.size(); i++) { - TimerEntry timer = ktimers.get(i); + final TimerEntry timer = ktimers.get(i); String linePrefix = ": "; sb.setLength(0); sb.append(prefix); @@ -3526,12 +3519,12 @@ public abstract class BatteryStats implements Parcelable { pw.println(); } - Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats(); + final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats(); if (wakeupReasons.size() > 0) { pw.print(prefix); pw.println(" All wakeup reasons:"); - final ArrayList<TimerEntry> reasons = new ArrayList<TimerEntry>(); + final ArrayList<TimerEntry> reasons = new ArrayList<>(); for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) { - Timer timer = ent.getValue(); + final Timer timer = ent.getValue(); reasons.add(new TimerEntry(ent.getKey(), 0, timer, timer.getCountLocked(which))); } @@ -3557,7 +3550,7 @@ public abstract class BatteryStats implements Parcelable { continue; } - Uid u = uidStats.valueAt(iu); + final Uid u = uidStats.valueAt(iu); pw.print(prefix); pw.print(" "); @@ -3565,20 +3558,20 @@ public abstract class BatteryStats implements Parcelable { pw.println(":"); boolean uidActivity = false; - long mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which); - long mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which); - long wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which); - long wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which); - long mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which); - long mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which); - long uidMobileActiveTime = u.getMobileRadioActiveTime(which); - int uidMobileActiveCount = u.getMobileRadioActiveCount(which); - long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which); - long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which); - long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which); - long wifiScanTime = u.getWifiScanTime(rawRealtime, which); - int wifiScanCount = u.getWifiScanCount(which); - long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which); + final long mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which); + final long mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which); + final long wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which); + final long wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which); + final long mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which); + final long mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which); + final long uidMobileActiveTime = u.getMobileRadioActiveTime(which); + final int uidMobileActiveCount = u.getMobileRadioActiveCount(which); + final long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which); + final long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which); + final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which); + final long wifiScanTime = u.getWifiScanTime(rawRealtime, which); + final int wifiScanCount = u.getWifiScanCount(which); + final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which); if (mobileRxBytes > 0 || mobileTxBytes > 0 || mobileRxPackets > 0 || mobileTxPackets > 0) { @@ -3636,7 +3629,7 @@ public abstract class BatteryStats implements Parcelable { if (u.hasUserActivity()) { boolean hasData = false; for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) { - int val = u.getUserActivityCount(i, which); + final int val = u.getUserActivityCount(i, which); if (val != 0) { if (!hasData) { sb.setLength(0); @@ -3655,125 +3648,121 @@ public abstract class BatteryStats implements Parcelable { } } - Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats(); - if (wakelocks.size() > 0) { - long totalFull = 0, totalPartial = 0, totalWindow = 0; - int count = 0; - for (Map.Entry<String, ? extends Uid.Wakelock> ent : wakelocks.entrySet()) { - Uid.Wakelock wl = ent.getValue(); - String linePrefix = ": "; + final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks + = u.getWakelockStats(); + long totalFullWakelock = 0, totalPartialWakelock = 0, totalWindowWakelock = 0; + int countWakelock = 0; + for (int iw=wakelocks.size()-1; iw>=0; iw--) { + final Uid.Wakelock wl = wakelocks.valueAt(iw); + String linePrefix = ": "; + sb.setLength(0); + sb.append(prefix); + sb.append(" Wake lock "); + sb.append(wakelocks.keyAt(iw)); + linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime, + "full", which, linePrefix); + linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime, + "partial", which, linePrefix); + linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime, + "window", which, linePrefix); + if (true || !linePrefix.equals(": ")) { + sb.append(" realtime"); + // Only print out wake locks that were held + pw.println(sb.toString()); + uidActivity = true; + countWakelock++; + } + totalFullWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL), + rawRealtime, which); + totalPartialWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL), + rawRealtime, which); + totalWindowWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW), + rawRealtime, which); + } + if (countWakelock > 1) { + if (totalFullWakelock != 0 || totalPartialWakelock != 0 + || totalWindowWakelock != 0) { sb.setLength(0); sb.append(prefix); - sb.append(" Wake lock "); - sb.append(ent.getKey()); - linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime, - "full", which, linePrefix); - linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime, - "partial", which, linePrefix); - linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime, - "window", which, linePrefix); - if (true || !linePrefix.equals(": ")) { - sb.append(" realtime"); - // Only print out wake locks that were held - pw.println(sb.toString()); - uidActivity = true; - count++; + sb.append(" TOTAL wake: "); + boolean needComma = false; + if (totalFullWakelock != 0) { + needComma = true; + formatTimeMs(sb, totalFullWakelock); + sb.append("full"); } - totalFull += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL), - rawRealtime, which); - totalPartial += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL), - rawRealtime, which); - totalWindow += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW), - rawRealtime, which); - } - if (count > 1) { - if (totalFull != 0 || totalPartial != 0 || totalWindow != 0) { - sb.setLength(0); - sb.append(prefix); - sb.append(" TOTAL wake: "); - boolean needComma = false; - if (totalFull != 0) { - needComma = true; - formatTimeMs(sb, totalFull); - sb.append("full"); - } - if (totalPartial != 0) { - if (needComma) { - sb.append(", "); - } - needComma = true; - formatTimeMs(sb, totalPartial); - sb.append("partial"); + if (totalPartialWakelock != 0) { + if (needComma) { + sb.append(", "); } - if (totalWindow != 0) { - if (needComma) { - sb.append(", "); - } - needComma = true; - formatTimeMs(sb, totalWindow); - sb.append("window"); + needComma = true; + formatTimeMs(sb, totalPartialWakelock); + sb.append("partial"); + } + if (totalWindowWakelock != 0) { + if (needComma) { + sb.append(", "); } - sb.append(" realtime"); - pw.println(sb.toString()); + needComma = true; + formatTimeMs(sb, totalWindowWakelock); + sb.append("window"); } + sb.append(" realtime"); + pw.println(sb.toString()); } } - Map<String, ? extends Timer> syncs = u.getSyncStats(); - if (syncs.size() > 0) { - for (Map.Entry<String, ? extends Timer> ent : syncs.entrySet()) { - Timer timer = ent.getValue(); - // Convert from microseconds to milliseconds with rounding - long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; - int count = timer.getCountLocked(which); - sb.setLength(0); - sb.append(prefix); - sb.append(" Sync "); - sb.append(ent.getKey()); - sb.append(": "); - if (totalTime != 0) { - formatTimeMs(sb, totalTime); - sb.append("realtime ("); - sb.append(count); - sb.append(" times)"); - } else { - sb.append("(not used)"); - } - pw.println(sb.toString()); - uidActivity = true; + final ArrayMap<String, ? extends Timer> syncs = u.getSyncStats(); + for (int isy=syncs.size()-1; isy>=0; isy--) { + final Timer timer = syncs.valueAt(isy); + // Convert from microseconds to milliseconds with rounding + final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; + final int count = timer.getCountLocked(which); + sb.setLength(0); + sb.append(prefix); + sb.append(" Sync "); + sb.append(syncs.keyAt(isy)); + sb.append(": "); + if (totalTime != 0) { + formatTimeMs(sb, totalTime); + sb.append("realtime ("); + sb.append(count); + sb.append(" times)"); + } else { + sb.append("(not used)"); } + pw.println(sb.toString()); + uidActivity = true; } - Map<String, ? extends Timer> jobs = u.getJobStats(); - if (jobs.size() > 0) { - for (Map.Entry<String, ? extends Timer> ent : jobs.entrySet()) { - Timer timer = ent.getValue(); - // Convert from microseconds to milliseconds with rounding - long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; - int count = timer.getCountLocked(which); - sb.setLength(0); - sb.append(prefix); - sb.append(" Job "); - sb.append(ent.getKey()); - sb.append(": "); - if (totalTime != 0) { - formatTimeMs(sb, totalTime); - sb.append("realtime ("); - sb.append(count); - sb.append(" times)"); - } else { - sb.append("(not used)"); - } - pw.println(sb.toString()); - uidActivity = true; + final ArrayMap<String, ? extends Timer> jobs = u.getJobStats(); + for (int ij=jobs.size()-1; ij>=0; ij--) { + final Timer timer = jobs.valueAt(ij); + // Convert from microseconds to milliseconds with rounding + final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; + final int count = timer.getCountLocked(which); + sb.setLength(0); + sb.append(prefix); + sb.append(" Job "); + sb.append(jobs.keyAt(ij)); + sb.append(": "); + if (totalTime != 0) { + formatTimeMs(sb, totalTime); + sb.append("realtime ("); + sb.append(count); + sb.append(" times)"); + } else { + sb.append("(not used)"); } + pw.println(sb.toString()); + uidActivity = true; } - SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats(); - int NSE = sensors.size(); + final SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats(); + final int NSE = sensors.size(); for (int ise=0; ise<NSE; ise++) { - Uid.Sensor se = sensors.valueAt(ise); - int sensorNumber = sensors.keyAt(ise); + final Uid.Sensor se = sensors.valueAt(ise); + final int sensorNumber = sensors.keyAt(ise); sb.setLength(0); sb.append(prefix); sb.append(" Sensor "); @@ -3785,12 +3774,12 @@ public abstract class BatteryStats implements Parcelable { } sb.append(": "); - Timer timer = se.getSensorTime(); + final Timer timer = se.getSensorTime(); if (timer != null) { // Convert from microseconds to milliseconds with rounding - long totalTime = (timer.getTotalTimeLocked( + final long totalTime = (timer.getTotalTimeLocked( rawRealtime, which) + 500) / 1000; - int count = timer.getCountLocked(which); + final int count = timer.getCountLocked(which); //timer.logState(); if (totalTime != 0) { formatTimeMs(sb, totalTime); @@ -3808,12 +3797,12 @@ public abstract class BatteryStats implements Parcelable { uidActivity = true; } - Timer vibTimer = u.getVibratorOnTimer(); + final Timer vibTimer = u.getVibratorOnTimer(); if (vibTimer != null) { // Convert from microseconds to milliseconds with rounding - long totalTime = (vibTimer.getTotalTimeLocked( + final long totalTime = (vibTimer.getTotalTimeLocked( rawRealtime, which) + 500) / 1000; - int count = vibTimer.getCountLocked(which); + final int count = vibTimer.getCountLocked(which); //timer.logState(); if (totalTime != 0) { sb.setLength(0); @@ -3828,11 +3817,12 @@ public abstract class BatteryStats implements Parcelable { } } - Timer fgTimer = u.getForegroundActivityTimer(); + final Timer fgTimer = u.getForegroundActivityTimer(); if (fgTimer != null) { // Convert from microseconds to milliseconds with rounding - long totalTime = (fgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; - int count = fgTimer.getCountLocked(which); + final long totalTime = (fgTimer.getTotalTimeLocked(rawRealtime, which) + 500) + / 1000; + final int count = fgTimer.getCountLocked(which); if (totalTime != 0) { sb.setLength(0); sb.append(prefix); @@ -3862,125 +3852,121 @@ public abstract class BatteryStats implements Parcelable { } } - Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats(); - if (processStats.size() > 0) { - for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent - : processStats.entrySet()) { - Uid.Proc ps = ent.getValue(); - long userTime; - long systemTime; - long foregroundTime; - int starts; - int numExcessive; - - userTime = ps.getUserTime(which); - systemTime = ps.getSystemTime(which); - foregroundTime = ps.getForegroundTime(which); - starts = ps.getStarts(which); - final int numCrashes = ps.getNumCrashes(which); - final int numAnrs = ps.getNumAnrs(which); - numExcessive = which == STATS_SINCE_CHARGED - ? ps.countExcessivePowers() : 0; - - if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0 - || numExcessive != 0 || numCrashes != 0 || numAnrs != 0) { - sb.setLength(0); - sb.append(prefix); sb.append(" Proc "); - sb.append(ent.getKey()); sb.append(":\n"); - sb.append(prefix); sb.append(" CPU: "); - formatTimeMs(sb, userTime); sb.append("usr + "); - formatTimeMs(sb, systemTime); sb.append("krn ; "); - formatTimeMs(sb, foregroundTime); sb.append("fg"); - if (starts != 0 || numCrashes != 0 || numAnrs != 0) { - sb.append("\n"); sb.append(prefix); sb.append(" "); - boolean hasOne = false; - if (starts != 0) { - hasOne = true; - sb.append(starts); sb.append(" starts"); - } - if (numCrashes != 0) { - if (hasOne) { - sb.append(", "); - } - hasOne = true; - sb.append(numCrashes); sb.append(" crashes"); - } - if (numAnrs != 0) { - if (hasOne) { - sb.append(", "); - } - sb.append(numAnrs); sb.append(" anrs"); + final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats + = u.getProcessStats(); + for (int ipr=processStats.size()-1; ipr>=0; ipr--) { + final Uid.Proc ps = processStats.valueAt(ipr); + long userTime; + long systemTime; + long foregroundTime; + int starts; + int numExcessive; + + userTime = ps.getUserTime(which); + systemTime = ps.getSystemTime(which); + foregroundTime = ps.getForegroundTime(which); + starts = ps.getStarts(which); + final int numCrashes = ps.getNumCrashes(which); + final int numAnrs = ps.getNumAnrs(which); + numExcessive = which == STATS_SINCE_CHARGED + ? ps.countExcessivePowers() : 0; + + if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0 + || numExcessive != 0 || numCrashes != 0 || numAnrs != 0) { + sb.setLength(0); + sb.append(prefix); sb.append(" Proc "); + sb.append(processStats.keyAt(ipr)); sb.append(":\n"); + sb.append(prefix); sb.append(" CPU: "); + formatTimeMs(sb, userTime); sb.append("usr + "); + formatTimeMs(sb, systemTime); sb.append("krn ; "); + formatTimeMs(sb, foregroundTime); sb.append("fg"); + if (starts != 0 || numCrashes != 0 || numAnrs != 0) { + sb.append("\n"); sb.append(prefix); sb.append(" "); + boolean hasOne = false; + if (starts != 0) { + hasOne = true; + sb.append(starts); sb.append(" starts"); + } + if (numCrashes != 0) { + if (hasOne) { + sb.append(", "); } + hasOne = true; + sb.append(numCrashes); sb.append(" crashes"); } - pw.println(sb.toString()); - for (int e=0; e<numExcessive; e++) { - Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e); - if (ew != null) { - pw.print(prefix); pw.print(" * Killed for "); - if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) { - pw.print("wake lock"); - } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) { - pw.print("cpu"); - } else { - pw.print("unknown"); - } - pw.print(" use: "); - TimeUtils.formatDuration(ew.usedTime, pw); - pw.print(" over "); - TimeUtils.formatDuration(ew.overTime, pw); - if (ew.overTime != 0) { - pw.print(" ("); - pw.print((ew.usedTime*100)/ew.overTime); - pw.println("%)"); - } + if (numAnrs != 0) { + if (hasOne) { + sb.append(", "); } + sb.append(numAnrs); sb.append(" anrs"); } - uidActivity = true; } + pw.println(sb.toString()); + for (int e=0; e<numExcessive; e++) { + Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e); + if (ew != null) { + pw.print(prefix); pw.print(" * Killed for "); + if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) { + pw.print("wake lock"); + } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) { + pw.print("cpu"); + } else { + pw.print("unknown"); + } + pw.print(" use: "); + TimeUtils.formatDuration(ew.usedTime, pw); + pw.print(" over "); + TimeUtils.formatDuration(ew.overTime, pw); + if (ew.overTime != 0) { + pw.print(" ("); + pw.print((ew.usedTime*100)/ew.overTime); + pw.println("%)"); + } + } + } + uidActivity = true; } } - Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats(); - if (packageStats.size() > 0) { - for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent - : packageStats.entrySet()) { - pw.print(prefix); pw.print(" Apk "); pw.print(ent.getKey()); pw.println(":"); - boolean apkActivity = false; - Uid.Pkg ps = ent.getValue(); - int wakeups = ps.getWakeups(which); - if (wakeups != 0) { - pw.print(prefix); pw.print(" "); - pw.print(wakeups); pw.println(" wakeup alarms"); + final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats + = u.getPackageStats(); + for (int ipkg=packageStats.size()-1; ipkg>=0; ipkg--) { + pw.print(prefix); pw.print(" Apk "); pw.print(packageStats.keyAt(ipkg)); + pw.println(":"); + boolean apkActivity = false; + final Uid.Pkg ps = packageStats.valueAt(ipkg); + final ArrayMap<String, ? extends Counter> alarms = ps.getWakeupAlarmStats(); + for (int iwa=alarms.size()-1; iwa>=0; iwa--) { + pw.print(prefix); pw.print(" Wakeup alarm "); + pw.print(alarms.keyAt(iwa)); pw.print(": "); + pw.print(alarms.valueAt(iwa).getCountLocked(which)); + pw.println(" times"); + apkActivity = true; + } + final ArrayMap<String, ? extends Uid.Pkg.Serv> serviceStats = ps.getServiceStats(); + for (int isvc=serviceStats.size()-1; isvc>=0; isvc--) { + final BatteryStats.Uid.Pkg.Serv ss = serviceStats.valueAt(isvc); + final long startTime = ss.getStartTime(batteryUptime, which); + final int starts = ss.getStarts(which); + final int launches = ss.getLaunches(which); + if (startTime != 0 || starts != 0 || launches != 0) { + sb.setLength(0); + sb.append(prefix); sb.append(" Service "); + sb.append(serviceStats.keyAt(isvc)); sb.append(":\n"); + sb.append(prefix); sb.append(" Created for: "); + formatTimeMs(sb, startTime / 1000); + sb.append("uptime\n"); + sb.append(prefix); sb.append(" Starts: "); + sb.append(starts); + sb.append(", launches: "); sb.append(launches); + pw.println(sb.toString()); apkActivity = true; } - Map<String, ? extends Uid.Pkg.Serv> serviceStats = ps.getServiceStats(); - if (serviceStats.size() > 0) { - for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent - : serviceStats.entrySet()) { - BatteryStats.Uid.Pkg.Serv ss = sent.getValue(); - long startTime = ss.getStartTime(batteryUptime, which); - int starts = ss.getStarts(which); - int launches = ss.getLaunches(which); - if (startTime != 0 || starts != 0 || launches != 0) { - sb.setLength(0); - sb.append(prefix); sb.append(" Service "); - sb.append(sent.getKey()); sb.append(":\n"); - sb.append(prefix); sb.append(" Created for: "); - formatTimeMs(sb, startTime / 1000); - sb.append("uptime\n"); - sb.append(prefix); sb.append(" Starts: "); - sb.append(starts); - sb.append(", launches: "); sb.append(launches); - pw.println(sb.toString()); - apkActivity = true; - } - } - } - if (!apkActivity) { - pw.print(prefix); pw.println(" (nothing executed)"); - } - uidActivity = true; } + if (!apkActivity) { + pw.print(prefix); pw.println(" (nothing executed)"); + } + uidActivity = true; } if (!uidActivity) { pw.print(prefix); pw.println(" (nothing executed)"); @@ -4498,7 +4484,6 @@ public abstract class BatteryStats implements Parcelable { return true; } - public static final int DUMP_UNPLUGGED_ONLY = 1<<0; public static final int DUMP_CHARGED_ONLY = 1<<1; public static final int DUMP_DAILY_ONLY = 1<<2; public static final int DUMP_HISTORY_ONLY = 1<<3; @@ -4647,7 +4632,7 @@ public abstract class BatteryStats implements Parcelable { prepareForDumpLocked(); final boolean filtering = (flags - & (DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0; + & (DUMP_HISTORY_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0; if ((flags&DUMP_HISTORY_ONLY) != 0 || !filtering) { final long historyTotalSize = getHistoryTotalSize(); @@ -4691,7 +4676,7 @@ public abstract class BatteryStats implements Parcelable { } } - if (filtering && (flags&(DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) { + if (filtering && (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) { return; } @@ -4769,7 +4754,7 @@ public abstract class BatteryStats implements Parcelable { LevelStepTracker csteps = getDailyChargeLevelStepTracker(); ArrayList<PackageChange> pkgc = getDailyPackageChanges(); if (dsteps.mNumStepDurations > 0 || csteps.mNumStepDurations > 0 || pkgc != null) { - if ((flags&DUMP_DAILY_ONLY) != 0) { + if ((flags&DUMP_DAILY_ONLY) != 0 || !filtering) { if (dumpDurationSteps(pw, " ", " Current daily discharge step durations:", dsteps, false)) { dumpDailyLevelStepSummary(pw, " ", "Discharge", dsteps, @@ -4801,7 +4786,7 @@ public abstract class BatteryStats implements Parcelable { pw.print(" to "); pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", dit.mEndTime).toString()); pw.println(":"); - if ((flags&DUMP_DAILY_ONLY) != 0) { + if ((flags&DUMP_DAILY_ONLY) != 0 || !filtering) { if (dumpDurationSteps(pw, " ", " Discharge step durations:", dit.mDischargeSteps, false)) { dumpDailyLevelStepSummary(pw, " ", "Discharge", dit.mDischargeSteps, @@ -4830,11 +4815,6 @@ public abstract class BatteryStats implements Parcelable { (flags&DUMP_DEVICE_WIFI_ONLY) != 0); pw.println(); } - if (!filtering || (flags&DUMP_UNPLUGGED_ONLY) != 0) { - pw.println("Statistics since last unplugged:"); - dumpLocked(context, pw, "", STATS_SINCE_UNPLUGGED, reqUid, - (flags&DUMP_DEVICE_WIFI_ONLY) != 0); - } } @SuppressWarnings("unused") @@ -4848,7 +4828,7 @@ public abstract class BatteryStats implements Parcelable { long now = getHistoryBaseTime() + SystemClock.elapsedRealtime(); final boolean filtering = (flags & - (DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0; + (DUMP_HISTORY_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0; if ((flags&DUMP_INCLUDE_HISTORY) != 0 || (flags&DUMP_HISTORY_ONLY) != 0) { if (startIteratingHistoryLocked()) { @@ -4874,7 +4854,7 @@ public abstract class BatteryStats implements Parcelable { } } - if (filtering && (flags&(DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) { + if (filtering && (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) { return; } @@ -4924,9 +4904,5 @@ public abstract class BatteryStats implements Parcelable { dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1, (flags&DUMP_DEVICE_WIFI_ONLY) != 0); } - if (!filtering || (flags&DUMP_UNPLUGGED_ONLY) != 0) { - dumpCheckinLocked(context, pw, STATS_SINCE_UNPLUGGED, -1, - (flags&DUMP_DEVICE_WIFI_ONLY) != 0); - } } } diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index 418641f..804d3d0 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -51,6 +51,7 @@ interface IPowerManager void setStayOnSetting(int val); void boostScreenBrightness(long time); + boolean isScreenBrightnessBoosted(); // temporarily overrides the screen brightness settings to allow the user to // see the effect of a settings change without applying it immediately diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 81745b3..01c9a21 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -712,6 +712,22 @@ public final class PowerManager { } /** + * Returns whether the screen brightness is currently boosted to maximum, caused by a call + * to {@link #boostScreenBrightness(long)}. + * @return {@code True} if the screen brightness is currently boosted. {@code False} otherwise. + * + * @hide + */ + @SystemApi + public boolean isScreenBrightnessBoosted() { + try { + return mService.isScreenBrightnessBoosted(); + } catch (RemoteException e) { + return false; + } + } + + /** * Sets the brightness of the backlights (screen, keyboard, button). * <p> * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission. @@ -917,6 +933,16 @@ public final class PowerManager { public static final String EXTRA_POWER_SAVE_MODE = "mode"; /** + * Intent that is broadcast when the state of {@link #isScreenBrightnessBoosted()} has changed. + * This broadcast is only sent to registered receivers. + * + * @hide + **/ + @SystemApi + public static final String ACTION_SCREEN_BRIGHTNESS_BOOST_CHANGED + = "android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED"; + + /** * A wake lock is a mechanism to indicate that your application needs * to have the device stay on. * <p> diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java index ccf2cfa..f32e8cf 100644 --- a/core/java/android/preference/Preference.java +++ b/core/java/android/preference/Preference.java @@ -706,8 +706,10 @@ public class Preference implements Comparable<Preference> { * @param iconResId The icon as a resource ID. */ public void setIcon(@DrawableRes int iconResId) { - mIconResId = iconResId; - setIcon(mContext.getDrawable(iconResId)); + if (mIconResId != iconResId) { + mIconResId = iconResId; + setIcon(mContext.getDrawable(iconResId)); + } } /** diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 74b0a1c..e4a6f07 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -4809,6 +4809,14 @@ public final class ContactsContract { Uri.withAppendedPath(AUTHORITY_URI, "raw_contact_entities"); /** + * The content:// style URI for this table in corp profile + * + * @hide + */ + public static final Uri CORP_CONTENT_URI = + Uri.withAppendedPath(AUTHORITY_URI, "raw_contact_entities_corp"); + + /** * The content:// style URI for this table, specific to the user's profile. */ public static final Uri PROFILE_CONTENT_URI = diff --git a/core/java/android/security/IKeystoreService.aidl b/core/java/android/security/IKeystoreService.aidl index ac6bbb7..d24bc13 100644 --- a/core/java/android/security/IKeystoreService.aidl +++ b/core/java/android/security/IKeystoreService.aidl @@ -19,6 +19,7 @@ package android.security; import android.security.keymaster.ExportResult; import android.security.keymaster.KeyCharacteristics; import android.security.keymaster.KeymasterArguments; +import android.security.keymaster.KeymasterBlob; import android.security.keymaster.OperationResult; import android.security.KeystoreArguments; @@ -61,11 +62,12 @@ interface IKeystoreService { int addRngEntropy(in byte[] data); int generateKey(String alias, in KeymasterArguments arguments, int uid, int flags, out KeyCharacteristics characteristics); - int getKeyCharacteristics(String alias, in byte[] clientId, - in byte[] appId, out KeyCharacteristics characteristics); + int getKeyCharacteristics(String alias, in KeymasterBlob clientId, in KeymasterBlob appId, + out KeyCharacteristics characteristics); int importKey(String alias, in KeymasterArguments arguments, int format, in byte[] keyData, int uid, int flags, out KeyCharacteristics characteristics); - ExportResult exportKey(String alias, int format, in byte[] clientId, in byte[] appId); + ExportResult exportKey(String alias, int format, in KeymasterBlob clientId, + in KeymasterBlob appId); OperationResult begin(IBinder appToken, String alias, int purpose, boolean pruneable, in KeymasterArguments params, out KeymasterArguments operationParams); OperationResult update(IBinder token, in KeymasterArguments params, in byte[] input); diff --git a/core/java/android/security/NetworkSecurityPolicy.java b/core/java/android/security/NetworkSecurityPolicy.java index c7274e8..0b3bf45 100644 --- a/core/java/android/security/NetworkSecurityPolicy.java +++ b/core/java/android/security/NetworkSecurityPolicy.java @@ -19,48 +19,57 @@ package android.security; /** * Network security policy. * - * @hide + * <p>Network stacks/components should honor this policy to make it possible to centrally control + * the relevant aspects of network security behavior. + * + * <p>The policy currently consists of a single flag: whether cleartext network traffic is + * permitted. See {@link #isCleartextTrafficPermitted()}. */ public class NetworkSecurityPolicy { - private static final NetworkSecurityPolicy INSTANCE = new NetworkSecurityPolicy(); - - private boolean mCleartextTrafficPermitted = true; + private static final NetworkSecurityPolicy INSTANCE = new NetworkSecurityPolicy(); - private NetworkSecurityPolicy() {} + private NetworkSecurityPolicy() {} - /** - * Gets the policy. - */ - public static NetworkSecurityPolicy getInstance() { - return INSTANCE; - } + /** + * Gets the policy for this process. + * + * <p>It's fine to cache this reference. Any changes to the policy will be immediately visible + * through the reference. + */ + public static NetworkSecurityPolicy getInstance() { + return INSTANCE; + } - /** - * Checks whether cleartext network traffic (e.g., HTTP, WebSockets, XMPP, IMAP, SMTP -- without - * TLS or STARTTLS) is permitted for this process. - * - * <p>When cleartext network traffic is not permitted, the platform's components (e.g., HTTP - * stacks, {@code WebView}, {@code MediaPlayer}) will refuse this process's requests to use - * cleartext traffic. Third-party libraries are encouraged to honor this setting as well. - */ - public boolean isCleartextTrafficPermitted() { - synchronized (this) { - return mCleartextTrafficPermitted; + /** + * Returns whether cleartext network traffic (e.g. HTTP, FTP, WebSockets, XMPP, IMAP, SMTP -- + * without TLS or STARTTLS) is permitted for this process. + * + * <p>When cleartext network traffic is not permitted, the platform's components (e.g. HTTP and + * FTP stacks, {@link android.webkit.WebView}, {@link android.media.MediaPlayer}) will refuse + * this process's requests to use cleartext traffic. Third-party libraries are strongly + * encouraged to honor this setting as well. + * + * <p>This flag is honored on a best effort basis because it's impossible to prevent all + * cleartext traffic from Android applications given the level of access provided to them. For + * example, there's no expectation that the {@link java.net.Socket} API will honor this flag + * because it cannot determine whether its traffic is in cleartext. However, most network + * traffic from applications is handled by higher-level network stacks/components which can + * honor this aspect of the policy. + */ + public boolean isCleartextTrafficPermitted() { + return libcore.net.NetworkSecurityPolicy.isCleartextTrafficPermitted(); } - } - /** - * Sets whether cleartext network traffic is permitted for this process. - * - * <p>This method is used by the platform early on in the application's initialization to set the - * policy. - * - * @hide - */ - public void setCleartextTrafficPermitted(boolean permitted) { - synchronized (this) { - mCleartextTrafficPermitted = permitted; + /** + * Sets whether cleartext network traffic is permitted for this process. + * + * <p>This method is used by the platform early on in the application's initialization to set + * the policy. + * + * @hide + */ + public void setCleartextTrafficPermitted(boolean permitted) { + libcore.net.NetworkSecurityPolicy.setCleartextTrafficPermitted(permitted); } - } } diff --git a/core/java/android/security/keymaster/KeymasterBlob.aidl b/core/java/android/security/keymaster/KeymasterBlob.aidl new file mode 100644 index 0000000..8f70f7c --- /dev/null +++ b/core/java/android/security/keymaster/KeymasterBlob.aidl @@ -0,0 +1,20 @@ +/** + * 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.keymaster; + +/* @hide */ +parcelable KeymasterBlob; diff --git a/core/java/android/security/keymaster/KeymasterBlob.java b/core/java/android/security/keymaster/KeymasterBlob.java new file mode 100644 index 0000000..cb95604 --- /dev/null +++ b/core/java/android/security/keymaster/KeymasterBlob.java @@ -0,0 +1,55 @@ +/** + * 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.keymaster; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * @hide + */ +public class KeymasterBlob implements Parcelable { + public byte[] blob; + + public KeymasterBlob(byte[] blob) { + this.blob = blob; + } + public static final Parcelable.Creator<KeymasterBlob> CREATOR = new + Parcelable.Creator<KeymasterBlob>() { + public KeymasterBlob createFromParcel(Parcel in) { + return new KeymasterBlob(in); + } + + public KeymasterBlob[] newArray(int length) { + return new KeymasterBlob[length]; + } + }; + + protected KeymasterBlob(Parcel in) { + blob = in.createByteArray(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeByteArray(blob); + } +} diff --git a/core/java/android/security/keymaster/KeymasterBlobArgument.java b/core/java/android/security/keymaster/KeymasterBlobArgument.java index 9af4445..7d587bf 100644 --- a/core/java/android/security/keymaster/KeymasterBlobArgument.java +++ b/core/java/android/security/keymaster/KeymasterBlobArgument.java @@ -26,6 +26,13 @@ class KeymasterBlobArgument extends KeymasterArgument { public KeymasterBlobArgument(int tag, byte[] blob) { super(tag); + switch (KeymasterDefs.getTagType(tag)) { + case KeymasterDefs.KM_BIGNUM: + case KeymasterDefs.KM_BYTES: + break; // OK. + default: + throw new IllegalArgumentException("Bad blob tag " + tag); + } this.blob = blob; } diff --git a/core/java/android/security/keymaster/KeymasterBooleanArgument.java b/core/java/android/security/keymaster/KeymasterBooleanArgument.java index 5481e8f..9c03674 100644 --- a/core/java/android/security/keymaster/KeymasterBooleanArgument.java +++ b/core/java/android/security/keymaster/KeymasterBooleanArgument.java @@ -28,6 +28,12 @@ class KeymasterBooleanArgument extends KeymasterArgument { public KeymasterBooleanArgument(int tag) { super(tag); + switch (KeymasterDefs.getTagType(tag)) { + case KeymasterDefs.KM_BOOL: + break; // OK. + default: + throw new IllegalArgumentException("Bad bool tag " + tag); + } } public KeymasterBooleanArgument(int tag, Parcel in) { diff --git a/core/java/android/security/keymaster/KeymasterDateArgument.java b/core/java/android/security/keymaster/KeymasterDateArgument.java index 310f546..bffd24d 100644 --- a/core/java/android/security/keymaster/KeymasterDateArgument.java +++ b/core/java/android/security/keymaster/KeymasterDateArgument.java @@ -27,6 +27,12 @@ class KeymasterDateArgument extends KeymasterArgument { public KeymasterDateArgument(int tag, Date date) { super(tag); + switch (KeymasterDefs.getTagType(tag)) { + case KeymasterDefs.KM_DATE: + break; // OK. + default: + throw new IllegalArgumentException("Bad date tag " + tag); + } this.date = date; } diff --git a/core/java/android/security/keymaster/KeymasterIntArgument.java b/core/java/android/security/keymaster/KeymasterIntArgument.java index c3738d7..da81715 100644 --- a/core/java/android/security/keymaster/KeymasterIntArgument.java +++ b/core/java/android/security/keymaster/KeymasterIntArgument.java @@ -26,6 +26,15 @@ class KeymasterIntArgument extends KeymasterArgument { public KeymasterIntArgument(int tag, int value) { super(tag); + switch (KeymasterDefs.getTagType(tag)) { + case KeymasterDefs.KM_INT: + case KeymasterDefs.KM_INT_REP: + case KeymasterDefs.KM_ENUM: + case KeymasterDefs.KM_ENUM_REP: + break; // OK. + default: + throw new IllegalArgumentException("Bad int tag " + tag); + } this.value = value; } diff --git a/core/java/android/security/keymaster/KeymasterLongArgument.java b/core/java/android/security/keymaster/KeymasterLongArgument.java index 3c565b8..9d2be09 100644 --- a/core/java/android/security/keymaster/KeymasterLongArgument.java +++ b/core/java/android/security/keymaster/KeymasterLongArgument.java @@ -26,6 +26,12 @@ class KeymasterLongArgument extends KeymasterArgument { public KeymasterLongArgument(int tag, long value) { super(tag); + switch (KeymasterDefs.getTagType(tag)) { + case KeymasterDefs.KM_LONG: + break; // OK. + default: + throw new IllegalArgumentException("Bad long tag " + tag); + } this.value = value; } diff --git a/core/java/android/service/fingerprint/Fingerprint.aidl b/core/java/android/service/fingerprint/Fingerprint.aidl new file mode 100644 index 0000000..c9fd989 --- /dev/null +++ b/core/java/android/service/fingerprint/Fingerprint.aidl @@ -0,0 +1,19 @@ +/* + * 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.service.fingerprint; + +// @hide +parcelable Fingerprint; diff --git a/core/java/android/service/fingerprint/Fingerprint.java b/core/java/android/service/fingerprint/Fingerprint.java new file mode 100644 index 0000000..37552eb --- /dev/null +++ b/core/java/android/service/fingerprint/Fingerprint.java @@ -0,0 +1,93 @@ +/* + * 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.service.fingerprint; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Container for fingerprint metadata. + * @hide + */ +public final class Fingerprint implements Parcelable { + private CharSequence mName; + private int mGroupId; + private int mFingerId; + private long mDeviceId; // physical device this is associated with + + public Fingerprint(CharSequence name, int groupId, int fingerId, long deviceId) { + mName = name; + mGroupId = groupId; + mFingerId = fingerId; + mDeviceId = deviceId; + } + + private Fingerprint(Parcel in) { + mName = in.readString(); + mGroupId = in.readInt(); + mFingerId = in.readInt(); + mDeviceId = in.readLong(); + } + + /** + * Gets the human-readable name for the given fingerprint. + * @return name given to finger + */ + public CharSequence getName() { return mName; } + + /** + * Gets the device-specific finger id. Used by Settings to map a name to a specific + * fingerprint template. + * @return device-specific id for this finger + * @hide + */ + public int getFingerId() { return mFingerId; } + + /** + * Gets the group id specified when the fingerprint was enrolled. + * @return group id for the set of fingerprints this one belongs to. + * @hide + */ + public int getGroupId() { return mGroupId; } + + /** + * Device this fingerprint belongs to. + * @hide + */ + public long getDeviceId() { return mDeviceId; } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel out, int flags) { + out.writeString(mName.toString()); + out.writeInt(mGroupId); + out.writeInt(mFingerId); + out.writeLong(mDeviceId); + } + + public static final Parcelable.Creator<Fingerprint> CREATOR + = new Parcelable.Creator<Fingerprint>() { + public Fingerprint createFromParcel(Parcel in) { + return new Fingerprint(in); + } + + public Fingerprint[] newArray(int size) { + return new Fingerprint[size]; + } + }; +};
\ No newline at end of file diff --git a/core/java/android/service/fingerprint/FingerprintManager.java b/core/java/android/service/fingerprint/FingerprintManager.java index 6375668..bb90e40 100644 --- a/core/java/android/service/fingerprint/FingerprintManager.java +++ b/core/java/android/service/fingerprint/FingerprintManager.java @@ -20,17 +20,25 @@ import android.app.ActivityManagerNative; import android.content.ContentResolver; import android.content.Context; import android.os.Binder; +import android.os.CancellationSignal; import android.os.Handler; import android.os.IBinder; +import android.os.Parcel; +import android.os.Parcelable; import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; +import android.service.fingerprint.FingerprintManager.EnrollmentCallback; import android.util.Log; import android.util.Slog; +import java.security.Signature; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import javax.crypto.Cipher; + /** * A class that coordinates access to the fingerprint hardware. * @hide @@ -45,9 +53,6 @@ public class FingerprintManager { private static final int MSG_ERROR = 103; private static final int MSG_REMOVED = 104; - // Errors generated by layers above HAL - public static final int FINGERPRINT_ERROR_NO_RECEIVER = -10; - // Message types. Must agree with HAL (fingerprint.h) public static final int FINGERPRINT_ERROR = -1; public static final int FINGERPRINT_ACQUIRED = 1; @@ -60,254 +65,499 @@ public class FingerprintManager { public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; public static final int FINGERPRINT_ERROR_TIMEOUT = 3; public static final int FINGERPRINT_ERROR_NO_SPACE = 4; + public static final int FINGERPRINT_ERROR_CANCELED = 5; + public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000; - // FINGERPRINT_ACQUIRED messages. Must agree with HAL (fingerprint.h) + // Image acquisition messages. Must agree with HAL (fingerprint.h) public static final int FINGERPRINT_ACQUIRED_GOOD = 0; public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1; public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2; - public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 4; - public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 8; - public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 16; + public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3; + public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4; + public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5; + public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000; private IFingerprintService mService; - private FingerprintManagerReceiver mClientReceiver; private Context mContext; private IBinder mToken = new Binder(); + private AuthenticationCallback mAuthenticationCallback; + private EnrollmentCallback mEnrollmentCallback; + private RemovalCallback mRemovalCallback; + private CryptoObject mCryptoObject; + private Fingerprint mRemovalFingerprint; + private boolean mListening; - private Handler mHandler = new Handler() { - public void handleMessage(android.os.Message msg) { - if (mClientReceiver != null) { - switch(msg.what) { - case MSG_ENROLL_RESULT: - mClientReceiver.onEnrollResult(msg.arg1, msg.arg2); - break; - case MSG_ACQUIRED: - mClientReceiver.onAcquired(msg.arg1); - break; - case MSG_PROCESSED: - mClientReceiver.onProcessed(msg.arg1); - break; - case MSG_ERROR: - mClientReceiver.onError(msg.arg1); - break; - case MSG_REMOVED: - mClientReceiver.onRemoved(msg.arg1); - } - } - } + /** + * A wrapper class for a limited number of crypto objects supported by FingerprintManager. + */ + public static class CryptoObject { + CryptoObject(Signature signature) { mSignature = signature; } + CryptoObject(Cipher cipher) { mCipher = cipher; } + private Signature mSignature; + private Cipher mCipher; }; - public static final class FingerprintItem { - public CharSequence name; - public int id; - FingerprintItem(CharSequence name, int id) { - this.name = name; - this.id = id; + /** + * Container for callback data from {@link FingerprintManager#authenticate(CryptoObject, + * AuthenticationCallback, CancellationSignal, int)} + */ + public static final class AuthenticationResult { + private Fingerprint mFingerprint; + private CryptoObject mCryptoObject; + + public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint) { + mCryptoObject = crypto; + mFingerprint = fingerprint; } - } + + /** + * Obtain the crypto object associated with this transaction + * @return crypto object provided to {@link FingerprintManager#authenticate(CryptoObject, + * AuthenticationCallback, CancellationSignal, int)} + */ + public CryptoObject getCryptoObject() { return mCryptoObject; } + + /** + * Obtain the Fingerprint associated with this operation. Applications are discouraged + * from associating specific fingers with specific applications or operations. Hence this + * is not public. + * @hide + */ + public Fingerprint getFingerprint() { return mFingerprint; } + }; /** - * @hide + * Callback structure provided to {@link FingerprintManager#authenticate(CryptoObject, + * AuthenticationCallback, CancellationSignal, int)}. Users of {@link #FingerprintManager()} + * must provide an implementation of this to {@link FingerprintManager#authenticate( + * CryptoObject, AuthenticationCallback, CancellationSignal, int) for listening to fingerprint + * events. */ - public FingerprintManager(Context context, IFingerprintService service) { - mContext = context; - mService = service; - if (mService == null) { - Slog.v(TAG, "FingerprintManagerService was null"); - } - } + public static abstract class AuthenticationCallback { + /** + * Called when an unrecoverable error has been encountered and the operation is complete. + * No further callbacks will be made on this object. + * @param errMsgId an integer identifying the error message. + * @param errString a human-readible error string that can be shown in UI. + */ + public abstract void onAuthenticationError(int errMsgId, CharSequence errString); - private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() { + /** + * Called when a recoverable error has been encountered during authentication. The help + * string is provided to give the user guidance for what went wrong, such as + * "Sensor dirty, please clean it." + * @param helpMsgId an integer identifying the error message. + * @param helpString a human-readible string that can be shown in UI. + */ + public abstract void onAuthenticationHelp(int helpMsgId, CharSequence helpString); - public void onEnrollResult(int fingerprintId, int remaining) { - mHandler.obtainMessage(MSG_ENROLL_RESULT, fingerprintId, remaining).sendToTarget(); - } + /** + * Called when a fingerprint is recognized. + * @param result an object containing authentication-related data. + */ + public abstract void onAuthenticationSucceeded(AuthenticationResult result); + }; - public void onAcquired(int acquireInfo) { - mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0).sendToTarget(); - } + /** + * Callback structure provided to {@link FingerprintManager#enroll(long, EnrollmentCallback, + * CancellationSignal, int). Users of {@link #FingerprintManager()} + * must provide an implementation of this to {@link FingerprintManager#enroll(long, + * EnrollmentCallback, CancellationSignal, int) for listening to fingerprint events. + */ + public static abstract class EnrollmentCallback { + /** + * Called when an unrecoverable error has been encountered and the operation is complete. + * No further callbacks will be made on this object. + * @param errMsgId an integer identifying the error message. + * @param errString a human-readible error string that can be shown in UI. + */ + public abstract void onEnrollmentError(int errMsgId, CharSequence errString); - public void onProcessed(int fingerprintId) { - mHandler.obtainMessage(MSG_PROCESSED, fingerprintId, 0).sendToTarget(); - } + /** + * Called when a recoverable error has been encountered during enrollment. The help + * string is provided to give the user guidance for what went wrong, such as + * "Sensor dirty, please clean it" or what they need to do next, such as + * "Touch sensor again." + * @param helpMsgId an integer identifying the error message. + * @param helpString a human-readible string that can be shown in UI. + */ + public abstract void onEnrollmentHelp(int helpMsgId, CharSequence helpString); - public void onError(int error) { - mHandler.obtainMessage(MSG_ERROR, error, 0).sendToTarget(); - } + /** + * Called as each enrollment step progresses. Enrollment is considered complete when + * remaining reaches 0. This function will not be called if enrollment fails. See + * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} + * @param remaining the number of remaining steps. + */ + public abstract void onEnrollmentProgress(int remaining); + }; - public void onRemoved(int fingerprintId) { - mHandler.obtainMessage(MSG_REMOVED, fingerprintId, 0).sendToTarget(); - } + /** + * Callback structure provided to {@link FingerprintManager#remove(int). Users of + * {@link #FingerprintManager()} may optionally provide an implementation of this to + * {@link FingerprintManager#remove(int, int, RemovalCallback)} for listening to + * fingerprint template removal events. + */ + public static abstract class RemovalCallback { + /** + * Called when the given fingerprint can't be removed. + * @param fp the fingerprint that the call attempted to remove. + * @param errMsgId an associated error message id. + * @param errString an error message indicating why the fingerprint id can't be removed. + */ + public abstract void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString); + + /** + * Called when a given fingerprint is successfully removed. + * @param fingerprint the fingerprint template that was removed. + */ + public abstract void onRemovalSucceeded(Fingerprint fingerprint); }; /** - * Determine whether the user has at least one fingerprint enrolled and enabled. + * Request authentication of a crypto object. This call warms up the fingerprint hardware + * and starts scanning for a fingerprint. It terminates when + * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or + * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult) is called, at + * which point the object is no longer valid. The operation can be canceled by using the + * provided cancel object. * - * @return true if at least one is enrolled and enabled + * @param crypto object associated with the call or null if none required. + * @param callback an object to receive authentication events + * @param cancel an object that can be used to cancel authentication + * @param flags optional flags */ - public boolean enrolledAndEnabled() { - ContentResolver res = mContext.getContentResolver(); - return Settings.Secure.getInt(res, "fingerprint_enabled", 0) != 0 - && FingerprintUtils.getFingerprintIdsForUser(res, getCurrentUserId()).length > 0; + public void authenticate(CryptoObject crypto, AuthenticationCallback callback, + CancellationSignal cancel, int flags) { + if (callback == null) { + throw new IllegalArgumentException("Must supply an authentication callback"); + } + + // TODO: handle cancel + + if (mService != null) try { + mAuthenticationCallback = callback; + mCryptoObject = crypto; + long sessionId = 0; // TODO: get from crypto object + startListening(); + mService.authenticate(mToken, sessionId, getCurrentUserId(), flags); + } catch (RemoteException e) { + Log.v(TAG, "Remote exception while authenticating: ", e); + stopListening(); + } } /** - * Start the enrollment process. Timeout dictates how long to wait for the user to - * enroll a fingerprint. - * - * @param timeout + * Request fingerprint enrollment. This call warms up the fingerprint hardware + * and starts scanning for fingerprints. Progress will be indicated by callbacks to the + * {@link EnrollmentCallback} object. It terminates when + * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} or + * {@link EnrollmentCallback#onEnrollmentProgress(int) is called with remaining == 0, at + * which point the object is no longer valid. The operation can be canceled by using the + * provided cancel object. + * @param challenge a unique id provided by a recent verification of device credentials + * (e.g. pin, pattern or password). + * @param callback an object to receive enrollment events + * @param cancel an object that can be used to cancel enrollment + * @param flags optional flags */ - public void enroll(long timeout) { - if (mServiceReceiver == null) { - sendError(FINGERPRINT_ERROR_NO_RECEIVER, 0, 0); - return; + public void enroll(long challenge, EnrollmentCallback callback, + CancellationSignal cancel, int flags) { + if (callback == null) { + throw new IllegalArgumentException("Must supply an enrollment callback"); } + + // TODO: handle cancel + if (mService != null) try { - mService.enroll(mToken, timeout, getCurrentUserId()); + mEnrollmentCallback = callback; + startListening(); + mService.enroll(mToken, getCurrentUserId(), flags); } catch (RemoteException e) { - Log.v(TAG, "Remote exception while enrolling: ", e); - sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0); + Log.v(TAG, "Remote exception in enroll: ", e); + stopListening(); } } /** - * Remove the given fingerprintId from the system. FingerprintId of 0 has special meaning - * which is to delete all fingerprint data for the current user. Use with caution. - * @param fingerprintId + * Remove given fingerprint template from fingerprint hardware and/or protected storage. + * @param fp the fingerprint item to remove + * @param callback an optional callback to verify that fingerprint templates have been + * successfully removed. May be null of no callback is required. + * @hide */ - public void remove(int fingerprintId) { - if (mServiceReceiver == null) { - sendError(FINGERPRINT_ERROR_NO_RECEIVER, 0, 0); - return; - } - if (mService != null) { - try { - mService.remove(mToken, fingerprintId, getCurrentUserId()); - } catch (RemoteException e) { - Log.v(TAG, "Remote exception during remove of fingerprintId: " + fingerprintId, e); - } - } else { - Log.w(TAG, "remove(): Service not connected!"); - sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0); + public void remove(Fingerprint fp, RemovalCallback callback) { + if (mService != null) try { + mRemovalCallback = callback; + mRemovalFingerprint = fp; + startListening(); + mService.remove(mToken, fp.getFingerId(), getCurrentUserId()); + } catch (RemoteException e) { + Log.v(TAG, "Remote in remove: ", e); + stopListening(); } } /** - * Starts listening for fingerprint events. When a finger is scanned or recognized, the - * client will be notified via the callback. + * Renames the given fingerprint template + * @param fpId the fingerprint id + * @param newName the new name + * @hide */ - public void startListening(FingerprintManagerReceiver receiver) { - mClientReceiver = receiver; + public void rename(int fpId, String newName) { + // Renames the given fpId if (mService != null) { try { - mService.startListening(mToken, mServiceReceiver, getCurrentUserId()); + mService.rename(fpId, getCurrentUserId(), newName); } catch (RemoteException e) { - Log.v(TAG, "Remote exception in startListening(): ", e); + Log.v(TAG, "Remote exception in rename(): ", e); } } else { - Log.w(TAG, "startListening(): Service not connected!"); - sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0); + Log.w(TAG, "rename(): Service not connected!"); } } - private int getCurrentUserId() { - try { - return ActivityManagerNative.getDefault().getCurrentUser().id; + /** + * Obtain the list of enrolled fingerprints templates. + * @return list of current fingerprint items + */ + public List<Fingerprint> getEnrolledFingerprints() { + if (mService != null) try { + return mService.getEnrolledFingerprints(getCurrentUserId()); } catch (RemoteException e) { - Log.w(TAG, "Failed to get current user id\n"); - return UserHandle.USER_NULL; + Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e); } + return null; } /** - * Stops the client from listening to fingerprint events. + * Determine if fingerprint hardware is present and functional. + * @return true if hardware is present and functional, false otherwise. + * @hide */ - public void stopListening() { + public boolean isHardwareDetected() { if (mService != null) { try { - mService.stopListening(mToken, getCurrentUserId()); - mClientReceiver = null; + long deviceId = 0; /* TODO: plumb hardware id to FPMS */ + return mService.isHardwareDetected(deviceId); } catch (RemoteException e) { - Log.v(TAG, "Remote exception in stopListening(): ", e); + Log.v(TAG, "Remote exception in isFingerprintHardwareDetected(): ", e); } } else { - Log.w(TAG, "stopListening(): Service not connected!"); - sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0); + Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!"); } + return false; } - public void enrollCancel() { - if (mServiceReceiver == null) { - sendError(FINGERPRINT_ERROR_NO_RECEIVER, 0, 0); - return; + private Handler mHandler = new Handler() { + public void handleMessage(android.os.Message msg) { + switch(msg.what) { + case MSG_ENROLL_RESULT: + sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */); + break; + case MSG_ACQUIRED: + sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */); + break; + case MSG_PROCESSED: + sendProcessedResult((Fingerprint) msg.obj); + break; + case MSG_ERROR: + sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */); + break; + case MSG_REMOVED: + sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */, + msg.arg2 /* groupId */); + } } - if (mService != null) { - try { - mService.enrollCancel(mToken, getCurrentUserId()); - mClientReceiver = null; - } catch (RemoteException e) { - Log.v(TAG, "Remote exception in enrollCancel(): ", e); - sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0); + + private void sendRemovedResult(long deviceId, int fingerId, int groupId) { + if (mRemovalCallback != null) { + int reqFingerId = mRemovalFingerprint.getFingerId(); + int reqGroupId = mRemovalFingerprint.getGroupId(); + if (fingerId != reqFingerId) { + Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId); + } + if (fingerId != reqFingerId) { + Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId); + } + mRemovalCallback.onRemovalSucceeded(mRemovalFingerprint); } - } else { - Log.w(TAG, "enrollCancel(): Service not connected!"); } - } - private void sendError(int msg, int arg1, int arg2) { - mHandler.obtainMessage(msg, arg1, arg2); - } + private void sendErrorResult(long deviceId, int errMsgId) { + if (mEnrollmentCallback != null) { + mEnrollmentCallback.onEnrollmentError(errMsgId, getErrorString(errMsgId)); + } else if (mAuthenticationCallback != null) { + mAuthenticationCallback.onAuthenticationError(errMsgId, getErrorString(errMsgId)); + } else if (mRemovalCallback != null) { + mRemovalCallback.onRemovalError(mRemovalFingerprint, errMsgId, + getErrorString(errMsgId)); + } + } + + private void sendEnrollResult(Fingerprint fp, int remaining) { + if (mEnrollmentCallback != null) { + mEnrollmentCallback.onEnrollmentProgress(remaining); + } + } + + private void sendProcessedResult(Fingerprint fp) { + if (mAuthenticationCallback != null) { + AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp); + mAuthenticationCallback.onAuthenticationSucceeded(result); + } + } + + private void sendAcquiredResult(long deviceId, int acquireInfo) { + final String msg = getAcquiredString(acquireInfo); + if (msg == null) return; + + if (mEnrollmentCallback != null) { + mEnrollmentCallback.onEnrollmentHelp(acquireInfo, msg); + } else if (mAuthenticationCallback != null) { + mAuthenticationCallback.onAuthenticationHelp(acquireInfo, msg); + } + } + + private String getErrorString(int errMsg) { + switch (errMsg) { + case FINGERPRINT_ERROR_UNABLE_TO_PROCESS: + return mContext.getString( + com.android.internal.R.string.fingerprint_error_unable_to_process); + case FINGERPRINT_ERROR_HW_UNAVAILABLE: + return mContext.getString( + com.android.internal.R.string.fingerprint_error_hw_not_available); + case FINGERPRINT_ERROR_NO_SPACE: + return mContext.getString( + com.android.internal.R.string.fingerprint_error_no_space); + case FINGERPRINT_ERROR_TIMEOUT: + return mContext.getString( + com.android.internal.R.string.fingerprint_error_timeout); + default: + if (errMsg >= FINGERPRINT_ERROR_VENDOR_BASE) { + int msgNumber = errMsg - FINGERPRINT_ERROR_VENDOR_BASE; + String[] msgArray = mContext.getResources().getStringArray( + com.android.internal.R.array.fingerprint_error_vendor); + if (msgNumber < msgArray.length) { + return msgArray[msgNumber]; + } + } + return null; + } + } + + private String getAcquiredString(int acquireInfo) { + switch (acquireInfo) { + case FINGERPRINT_ACQUIRED_GOOD: + return null; + case FINGERPRINT_ACQUIRED_PARTIAL: + return mContext.getString( + com.android.internal.R.string.fingerprint_acquired_partial); + case FINGERPRINT_ACQUIRED_INSUFFICIENT: + return mContext.getString( + com.android.internal.R.string.fingerprint_acquired_insufficient); + case FINGERPRINT_ACQUIRED_IMAGER_DIRTY: + return mContext.getString( + com.android.internal.R.string.fingerprint_acquired_imager_dirty); + case FINGERPRINT_ACQUIRED_TOO_SLOW: + return mContext.getString( + com.android.internal.R.string.fingerprint_acquired_too_slow); + case FINGERPRINT_ACQUIRED_TOO_FAST: + return mContext.getString( + com.android.internal.R.string.fingerprint_acquired_too_fast); + default: + if (acquireInfo >= FINGERPRINT_ACQUIRED_VENDOR_BASE) { + int msgNumber = acquireInfo - FINGERPRINT_ACQUIRED_VENDOR_BASE; + String[] msgArray = mContext.getResources().getStringArray( + com.android.internal.R.array.fingerprint_acquired_vendor); + if (msgNumber < msgArray.length) { + return msgArray[msgNumber]; + } + } + return null; + } + } + }; /** - * @return list of current fingerprint items * @hide */ - public List<FingerprintItem> getEnrolledFingerprints() { - int[] ids = FingerprintUtils.getFingerprintIdsForUser(mContext.getContentResolver(), - getCurrentUserId()); - List<FingerprintItem> result = new ArrayList<FingerprintItem>(); - for (int i = 0; i < ids.length; i++) { - // TODO: persist names in Settings - FingerprintItem item = new FingerprintItem("Finger" + ids[i], ids[i]); - result.add(item); + public FingerprintManager(Context context, IFingerprintService service) { + mContext = context; + mService = service; + if (mService == null) { + Slog.v(TAG, "FingerprintManagerService was null"); + } + } + + private int getCurrentUserId() { + try { + return ActivityManagerNative.getDefault().getCurrentUser().id; + } catch (RemoteException e) { + Log.w(TAG, "Failed to get current user id\n"); + return UserHandle.USER_NULL; } - return result; } /** - * Determine if fingerprint hardware is present and functional. - * @return true if hardware is present and functional, false otherwise. - * @hide + * Stops the client from listening to fingerprint events. */ - public boolean isHardwareDetected() { + private void stopListening() { if (mService != null) { try { - return mService.isHardwareDetected(); + if (mListening) { + mService.removeListener(mToken, mServiceReceiver); + mListening = false; + } } catch (RemoteException e) { - Log.v(TAG, "Remote exception in isFingerprintHardwareDetected(): ", e); + Log.v(TAG, "Remote exception in stopListening(): ", e); } } else { - Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!"); + Log.w(TAG, "stopListening(): Service not connected!"); } - return false; } /** - * Renames the given fingerprint template - * @param fpId the fingerprint id - * @param newName the new name - * @hide + * Starts listening for fingerprint events for this client. */ - public void rename(int fpId, String newName) { - // Renames the given fpId + private void startListening() { if (mService != null) { try { - mService.rename(fpId, newName); + if (!mListening) { + mService.addListener(mToken, mServiceReceiver, getCurrentUserId()); + mListening = true; + } } catch (RemoteException e) { - Log.v(TAG, "Remote exception in rename(): ", e); + Log.v(TAG, "Remote exception in startListening(): ", e); } } else { - Log.w(TAG, "rename(): Service not connected!"); + Log.w(TAG, "startListening(): Service not connected!"); } } + + private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() { + + public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) { + mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0, + new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget(); + } + + public void onAcquired(long deviceId, int acquireInfo) { + mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0, deviceId).sendToTarget(); + } + + public void onProcessed(long deviceId, int fingerId, int groupId) { + mHandler.obtainMessage(MSG_PROCESSED, + new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget(); + } + + public void onError(long deviceId, int error) { + mHandler.obtainMessage(MSG_ERROR, error, 0, deviceId).sendToTarget(); + } + + public void onRemoved(long deviceId, int fingerId, int groupId) { + mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget(); + } + }; + }
\ No newline at end of file diff --git a/core/java/android/service/fingerprint/FingerprintManagerReceiver.java b/core/java/android/service/fingerprint/FingerprintManagerReceiver.java deleted file mode 100644 index 85677ba..0000000 --- a/core/java/android/service/fingerprint/FingerprintManagerReceiver.java +++ /dev/null @@ -1,76 +0,0 @@ -package android.service.fingerprint; -/** - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @hide - */ -public class FingerprintManagerReceiver { - /** - * Fingerprint enrollment progress update. Enrollment is considered complete if - * remaining hits 0 without {@link #onError(int)} being called. - * - * @param fingerprintId the fingerprint we're currently enrolling - * @param remaining the number of samples required to complete enrollment. It's up to - * the hardware to define what each step in enrollment means. Some hardware - * requires multiple samples of the same part of the finger. Others require sampling of - * different parts of the finger. The enrollment flow can use remaining to - * mean "step x" of the process or "just need another sample." - */ - public void onEnrollResult(int fingerprintId, int remaining) { } - - /** - * Fingerprint touch detected, but not processed yet. Clients will use this message to - * determine a good or bad scan before the fingerprint is processed. This is meant for the - * client to provide feedback about the scan or alert the user that recognition is to follow. - * - * @param acquiredInfo one of: - * {@link FingerprintManager#FINGERPRINT_ACQUIRED_GOOD}, - * {@link FingerprintManager#FINGERPRINT_ACQUIRED_PARTIAL}, - * {@link FingerprintManager#FINGERPRINT_ACQUIRED_INSUFFICIENT}, - * {@link FingerprintManager#FINGERPRINT_ACQUIRED_IMAGER_DIRTY}, - * {@link FingerprintManager#FINGERPRINT_ACQUIRED_TOO_SLOW}, - * {@link FingerprintManager#FINGERPRINT_ACQUIRED_TOO_FAST} - */ - public void onAcquired(int acquiredInfo) { } - - /** - * Fingerprint has been detected and processed. A non-zero return indicates a valid - * fingerprint was detected. - * - * @param fingerprintId the finger id, or 0 if not recognized. - */ - public void onProcessed(int fingerprintId) { } - - /** - * An error was detected during scan or enrollment. One of - * {@link FingerprintManager#FINGERPRINT_ERROR_HW_UNAVAILABLE}, - * {@link FingerprintManager#FINGERPRINT_ERROR_UNABLE_TO_PROCESS} or - * {@link FingerprintManager#FINGERPRINT_ERROR_TIMEOUT} - * {@link FingerprintManager#FINGERPRINT_ERROR_NO_SPACE} - * - * @param error one of the above error codes - */ - public void onError(int error) { } - - /** - * The given fingerprint template was successfully removed by the driver. - * See {@link FingerprintManager#remove(int)} - * - * @param fingerprintId id of template to remove. - */ - public void onRemoved(int fingerprintId) { } -}
\ No newline at end of file diff --git a/core/java/android/service/fingerprint/FingerprintUtils.java b/core/java/android/service/fingerprint/FingerprintUtils.java index cc17b99..62acbb9 100644 --- a/core/java/android/service/fingerprint/FingerprintUtils.java +++ b/core/java/android/service/fingerprint/FingerprintUtils.java @@ -67,7 +67,7 @@ class FingerprintUtils { return toIntArray(tmp); } - public static void addFingerprintIdForUser(int fingerId, ContentResolver res, int userId) { + public static void addFingerprintIdForUser(ContentResolver res, int fingerId, int userId) { // FingerId 0 has special meaning. if (fingerId == 0) { Log.w(TAG, "Tried to add fingerId 0"); diff --git a/core/java/android/service/fingerprint/IFingerprintService.aidl b/core/java/android/service/fingerprint/IFingerprintService.aidl index 9b4750b..e5d3ad4 100644 --- a/core/java/android/service/fingerprint/IFingerprintService.aidl +++ b/core/java/android/service/fingerprint/IFingerprintService.aidl @@ -17,31 +17,42 @@ package android.service.fingerprint; import android.os.Bundle; import android.service.fingerprint.IFingerprintServiceReceiver; +import android.service.fingerprint.Fingerprint; +import java.util.List; /** * Communication channel from client to the fingerprint service. * @hide */ interface IFingerprintService { - // Any errors resulting from this call will be returned to the listener - void enroll(IBinder token, long timeout, int userId); + // Authenticate the given sessionId with a fingerprint + void authenticate(IBinder token, long sessionId, int groupId, int flags); - // Any errors resulting from this call will be returned to the listener - void enrollCancel(IBinder token, int userId); + // Start fingerprint enrollment + void enroll(IBinder token, int groupId, int flags); // Any errors resulting from this call will be returned to the listener - void remove(IBinder token, int fingerprintId, int userId); + void remove(IBinder token, int fingerId, int groupId); + + // Rename the fingerprint specified by fingerId and groupId to the given name + void rename(int fingerId, int groupId, String name); - // Start listening for fingerprint events. This has the side effect of starting - // the hardware if not already started. - void startListening(IBinder token, IFingerprintServiceReceiver receiver, int userId); + // Get a list of enrolled fingerprints in the given group. + List<Fingerprint> getEnrolledFingerprints(int groupId); - // Stops listening for fingerprints - void stopListening(IBinder token, int userId); + // Register listener for an instance of FingerprintManager + void addListener(IBinder token, IFingerprintServiceReceiver receiver, int userId); + + // Unregister listener for an instance of FingerprintManager + void removeListener(IBinder token, IFingerprintServiceReceiver receiver); // Determine if HAL is loaded and ready - boolean isHardwareDetected(); + boolean isHardwareDetected(long deviceId); + + // Gets the number of hardware devices + // int getHardwareDeviceCount(); + + // Gets the unique device id for hardware enumerated at i + // long getHardwareDevice(int i); - // Rename the given fingerprint id - void rename(int fpId, String name); } diff --git a/core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl b/core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl index af4128f..f025064 100644 --- a/core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl +++ b/core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl @@ -23,9 +23,9 @@ import android.os.UserHandle; * @hide */ oneway interface IFingerprintServiceReceiver { - void onEnrollResult(int fingerprintId, int remaining); - void onAcquired(int acquiredInfo); - void onProcessed(int fingerprintId); - void onError(int error); - void onRemoved(int fingerprintId); + void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining); + void onAcquired(long deviceId, int acquiredInfo); + void onProcessed(long deviceId, int fingerId, int groupId); + void onError(long deviceId, int error); + void onRemoved(long deviceId, int fingerId, int groupId); } diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index d46b6f5..1674950 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -155,7 +155,6 @@ public abstract class WallpaperService extends Service { WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS; int mCurWindowFlags = mWindowFlags; int mCurWindowPrivateFlags = mWindowPrivateFlags; - int mOutsetBottomPx; final Rect mVisibleInsets = new Rect(); final Rect mWinFrame = new Rect(); final Rect mOverscanInsets = new Rect(); @@ -624,18 +623,9 @@ public abstract class WallpaperService extends Service { mLayout.token = mWindowToken; if (!mCreated) { - // Retrieve watch round and outset info - final WindowManager windowService = (WindowManager)getSystemService( - Context.WINDOW_SERVICE); + // Retrieve watch round info TypedArray windowStyle = obtainStyledAttributes( com.android.internal.R.styleable.Window); - final Display display = windowService.getDefaultDisplay(); - final boolean shouldUseBottomOutset = - display.getDisplayId() == Display.DEFAULT_DISPLAY; - if (shouldUseBottomOutset) { - mOutsetBottomPx = ScreenShapeHelper.getWindowOutsetBottomPx( - getResources().getDisplayMetrics(), windowStyle); - } mWindowIsRound = ScreenShapeHelper.getWindowIsRound(getResources()); windowStyle.recycle(); @@ -770,10 +760,7 @@ public abstract class WallpaperService extends Service { mDispatchedStableInsets.set(mStableInsets); mFinalSystemInsets.set(mDispatchedOverscanInsets); mFinalStableInsets.set(mDispatchedStableInsets); - if (mOutsetBottomPx != 0) { - mFinalSystemInsets.bottom = - mIWallpaperEngine.mDisplayPadding.bottom + mOutsetBottomPx; - } + mFinalSystemInsets.bottom = mIWallpaperEngine.mDisplayPadding.bottom; WindowInsets insets = new WindowInsets(mFinalSystemInsets, null, mFinalStableInsets, mWindowIsRound); onApplyWindowInsets(insets); diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java index 8cf1b4b..7bebbfb 100644 --- a/core/java/android/text/Html.java +++ b/core/java/android/text/Html.java @@ -244,13 +244,18 @@ public class Html { next++; } - withinParagraph(out, text, i, next - nl, nl, next == end); + if (withinParagraph(out, text, i, next - nl, nl, next == end)) { + /* Paragraph should be closed */ + out.append("</p>\n"); + out.append(getOpenParaTagWithDirection(text, next, end)); + } } out.append("</p>\n"); } - private static void withinParagraph(StringBuilder out, Spanned text, + /* Returns true if the caller should close and reopen the paragraph. */ + private static boolean withinParagraph(StringBuilder out, Spanned text, int start, int end, int nl, boolean last) { int next; @@ -363,17 +368,14 @@ public class Html { } } - String p = last ? "" : "</p>\n" + getOpenParaTagWithDirection(text, start, end); - if (nl == 1) { out.append("<br>\n"); - } else if (nl == 2) { - out.append(p); + return false; } else { for (int i = 2; i < nl; i++) { out.append("<br>"); } - out.append(p); + return !last; } } diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java index fcf1828..928bf16 100644 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -1153,7 +1153,10 @@ public abstract class Layout { return end - 1; } - if (ch != ' ' && ch != '\t') { + // Note: keep this in sync with Minikin LineBreaker::isLineEndSpace() + if (!(ch == ' ' || ch == '\t' || ch == 0x1680 || + (0x2000 <= ch && ch <= 0x200A && ch != 0x2007) || + ch == 0x205F || ch == 0x3000)) { break; } diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index ee39e27..b47418f 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -170,8 +170,9 @@ public class StaticLayout extends Layout { * Measurement and break iteration is done in native code. The protocol for using * the native code is as follows. * - * For each paragraph, do a nSetText of the paragraph text. Then, for each run within the - * paragraph: + * For each paragraph, do a nSetText of the paragraph text. Also do nSetLineWidth. + * + * Then, for each run within the paragraph: * - setLocale (this must be done at least for the first run, optional afterwards) * - one of the following, depending on the type of run: * + addStyleRun (a text run, to be measured in native code) @@ -459,7 +460,26 @@ public class StaticLayout extends Layout { byte[] chdirs = measured.mLevels; int dir = measured.mDir; boolean easy = measured.mEasy; - nSetText(b.mNativePtr, chs, paraEnd - paraStart); + + // tab stop locations + int[] variableTabStops = null; + if (spanned != null) { + TabStopSpan[] spans = getParagraphSpans(spanned, paraStart, + paraEnd, TabStopSpan.class); + if (spans.length > 0) { + int[] stops = new int[spans.length]; + for (int i = 0; i < spans.length; i++) { + stops[i] = spans[i].getTabStop(); + } + Arrays.sort(stops, 0, stops.length); + variableTabStops = stops; + } + } + + int breakStrategy = 0; // 0 = kBreakStrategy_Greedy + nSetupParagraph(b.mNativePtr, chs, paraEnd - paraStart, + firstWidth, firstWidthLineCount, restWidth, + variableTabStops, TAB_INCREMENT, breakStrategy); // measurement has to be done before performing line breaking // but we don't want to recompute fontmetrics or span ranges the @@ -505,25 +525,9 @@ public class StaticLayout extends Layout { spanEndCacheCount++; } - // tab stop locations - int[] variableTabStops = null; - if (spanned != null) { - TabStopSpan[] spans = getParagraphSpans(spanned, paraStart, - paraEnd, TabStopSpan.class); - if (spans.length > 0) { - int[] stops = new int[spans.length]; - for (int i = 0; i < spans.length; i++) { - stops[i] = spans[i].getTabStop(); - } - Arrays.sort(stops, 0, stops.length); - variableTabStops = stops; - } - } - nGetWidths(b.mNativePtr, widths); - int breakCount = nComputeLineBreaks(b.mNativePtr, paraEnd - paraStart, firstWidth, - firstWidthLineCount, restWidth, variableTabStops, TAB_INCREMENT, false, lineBreaks, - lineBreaks.breaks, lineBreaks.widths, lineBreaks.flags, lineBreaks.breaks.length); + int breakCount = nComputeLineBreaks(b.mNativePtr, lineBreaks, lineBreaks.breaks, + lineBreaks.widths, lineBreaks.flags, lineBreaks.breaks.length); int[] breaks = lineBreaks.breaks; float[] lineWidths = lineBreaks.widths; @@ -966,7 +970,10 @@ public class StaticLayout extends Layout { private static native void nFinishBuilder(long nativePtr); private static native void nSetLocale(long nativePtr, String locale); - private static native void nSetText(long nativePtr, char[] text, int length); + // Set up paragraph text and settings; done as one big method to minimize jni crossings + private static native void nSetupParagraph(long nativePtr, char[] text, int length, + float firstWidth, int firstWidthLineCount, float restWidth, + int[] variableTabStops, int defaultTabStop, int breakStrategy); private static native float nAddStyleRun(long nativePtr, long nativePaint, long nativeTypeface, int start, int end, boolean isRtl); @@ -983,9 +990,7 @@ public class StaticLayout extends Layout { // the arrays inside the LineBreaks objects are passed in as well // to reduce the number of JNI calls in the common case where the // arrays do not have to be resized - private static native int nComputeLineBreaks(long nativePtr, - int length, float firstWidth, int firstWidthLineCount, float restWidth, - int[] variableTabStops, int defaultTabStop, boolean optimize, LineBreaks recycle, + private static native int nComputeLineBreaks(long nativePtr, LineBreaks recycle, int[] recycleBreaks, float[] recycleWidths, boolean[] recycleFlags, int recycleLength); private int mLineCount; diff --git a/core/java/android/text/style/URLSpan.java b/core/java/android/text/style/URLSpan.java index d29bfb6..0669b6f 100644 --- a/core/java/android/text/style/URLSpan.java +++ b/core/java/android/text/style/URLSpan.java @@ -16,6 +16,7 @@ package android.text.style; +import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.net.Uri; @@ -23,6 +24,7 @@ import android.os.Parcel; import android.provider.Browser; import android.text.ParcelableSpan; import android.text.TextUtils; +import android.util.Log; import android.view.View; public class URLSpan extends ClickableSpan implements ParcelableSpan { @@ -59,6 +61,10 @@ public class URLSpan extends ClickableSpan implements ParcelableSpan { Context context = widget.getContext(); Intent intent = new Intent(Intent.ACTION_VIEW, uri); intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()); - context.startActivity(intent); + try { + context.startActivity(intent); + } catch (ActivityNotFoundException e) { + Log.w("URLSpan", "Actvity was not found for intent, " + intent.toString()); + } } } diff --git a/core/java/android/util/IntArray.java b/core/java/android/util/IntArray.java index e8d3947..9326203 100644 --- a/core/java/android/util/IntArray.java +++ b/core/java/android/util/IntArray.java @@ -18,6 +18,7 @@ package android.util; import com.android.internal.util.ArrayUtils; +import java.util.Arrays; import libcore.util.EmptyArray; /** @@ -78,6 +79,24 @@ public class IntArray implements Cloneable { } /** + * Searches the array for the specified value using the binary search algorithm. The array must + * be sorted (as by the {@link Arrays#sort(int[], int, int)} method) prior to making this call. + * If it is not sorted, the results are undefined. If the range contains multiple elements with + * the specified value, there is no guarantee which one will be found. + * + * @param value The value to search for. + * @return index of the search key, if it is contained in the array; otherwise, <i>(-(insertion + * point) - 1)</i>. The insertion point is defined as the point at which the key would + * be inserted into the array: the index of the first element greater than the key, or + * {@link #size()} if all elements in the array are less than the specified key. + * Note that this guarantees that the return value will be >= 0 if and only if the key + * is found. + */ + public int binarySearch(int value) { + return ContainerHelpers.binarySearch(mValues, mSize, value); + } + + /** * Adds the values in the specified array to this array. */ public void addAll(IntArray values) { @@ -159,4 +178,11 @@ public class IntArray implements Cloneable { public int size() { return mSize; } + + /** + * Returns a new array with the contents of this IntArray. + */ + public int[] toArray() { + return Arrays.copyOf(mValues, mSize); + } } diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index 59ec058..ad34f02 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -723,6 +723,12 @@ public class TextureView extends View { mSurface.release(); } mSurface = surfaceTexture; + + // If the view is visible, update the listener in the new surface to use + // the existing listener in the view. + if (((mViewFlags & VISIBILITY_MASK) == VISIBLE)) { + mSurface.setOnFrameAvailableListener(mUpdateListener, mAttachInfo.mHandler); + } mUpdateSurface = true; invalidateParentIfNeeded(); } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index f5de8e3..cfcc6fe 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -83,6 +83,7 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityEventSource; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.accessibility.AccessibilityNodeProvider; import android.view.animation.Animation; import android.view.animation.AnimationUtils; @@ -3168,6 +3169,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private Drawable mBackground; private TintInfo mBackgroundTint; + @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_") + private ForegroundInfo mForegroundInfo; + /** * RenderNode used for backgrounds. * <p> @@ -3182,13 +3186,23 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private String mTransitionName; - private static class TintInfo { + static class TintInfo { ColorStateList mTintList; PorterDuff.Mode mTintMode; boolean mHasTintMode; boolean mHasTintList; } + private static class ForegroundInfo { + private Drawable mDrawable; + private TintInfo mTintInfo; + private int mGravity = Gravity.FILL; + private boolean mInsidePadding = true; + private boolean mBoundsChanged = true; + private final Rect mSelfBounds = new Rect(); + private final Rect mOverlayBounds = new Rect(); + } + static class ListenerInfo { /** * Listener used to dispatch focus change events. @@ -4056,6 +4070,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback, setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider, PROVIDER_BACKGROUND)); break; + case R.styleable.View_foreground: + setForeground(a.getDrawable(attr)); + break; + case R.styleable.View_foregroundGravity: + setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY)); + break; + case R.styleable.View_foregroundTintMode: + setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null)); + break; + case R.styleable.View_foregroundTint: + setForegroundTintList(a.getColorStateList(attr)); + break; + case R.styleable.View_foregroundInsidePadding: + if (mForegroundInfo == null) { + mForegroundInfo = new ForegroundInfo(); + } + mForegroundInfo.mInsidePadding = a.getBoolean(attr, + mForegroundInfo.mInsidePadding); + break; } } @@ -4813,10 +4846,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @hide */ protected boolean performButtonActionOnTouchDown(MotionEvent event) { - if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) { - if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) { - return true; - } + if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE && + (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) { + showContextMenu(event.getX(), event.getY(), event.getMetaState()); + mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT; + return true; } return false; } @@ -5781,6 +5815,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH); } + + info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN); } private View findLabelForView(View view, int labeledId) { @@ -8228,6 +8264,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return true; } } break; + case R.id.accessibility_action_show_on_screen: { + if (mAttachInfo != null) { + final Rect r = mAttachInfo.mTmpInvalRect; + getDrawingRect(r); + return requestRectangleOnScreen(r, true); + } + } break; } return false; } @@ -8801,6 +8844,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (dr != null && visible != dr.isVisible()) { dr.setVisible(visible, false); } + final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; + if (fg != null && visible != fg.isVisible()) { + fg.setVisible(visible, false); + } } /** @@ -9917,6 +9964,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } mBackgroundSizeChanged = true; + if (mForegroundInfo != null) { + mForegroundInfo.mBoundsChanged = true; + } final AttachInfo ai = mAttachInfo; if (ai != null) { @@ -10755,6 +10805,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidate(true); } mBackgroundSizeChanged = true; + if (mForegroundInfo != null) { + mForegroundInfo.mBoundsChanged = true; + } invalidateParentIfNeeded(); if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { // View was rejected last time it was drawn by its parent; this may have changed @@ -10820,6 +10873,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidate(true); } mBackgroundSizeChanged = true; + if (mForegroundInfo != null) { + mForegroundInfo.mBoundsChanged = true; + } invalidateParentIfNeeded(); if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { // View was rejected last time it was drawn by its parent; this may have changed @@ -10879,6 +10935,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidate(true); } mBackgroundSizeChanged = true; + if (mForegroundInfo != null) { + mForegroundInfo.mBoundsChanged = true; + } invalidateParentIfNeeded(); if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { // View was rejected last time it was drawn by its parent; this may have changed @@ -10935,6 +10994,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidate(true); } mBackgroundSizeChanged = true; + if (mForegroundInfo != null) { + mForegroundInfo.mBoundsChanged = true; + } invalidateParentIfNeeded(); if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { // View was rejected last time it was drawn by its parent; this may have changed @@ -15313,13 +15375,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // Step 4, draw the children dispatchDraw(canvas); - // Step 6, draw decorations (scrollbars) - onDrawScrollBars(canvas); - + // Overlay is part of the content and draws beneath Foreground if (mOverlay != null && !mOverlay.isEmpty()) { mOverlay.getOverlayView().dispatchDraw(canvas); } + // Step 6, draw decorations (foreground, scrollbars) + onDrawForeground(canvas); + // we're done... return; } @@ -15461,12 +15524,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, canvas.restoreToCount(saveCount); - // Step 6, draw decorations (scrollbars) - onDrawScrollBars(canvas); - + // Overlay is part of the content and draws beneath Foreground if (mOverlay != null && !mOverlay.isEmpty()) { mOverlay.getOverlayView().dispatchDraw(canvas); } + + // Step 6, draw decorations (foreground, scrollbars) + onDrawForeground(canvas); } /** @@ -15849,6 +15913,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mPrivateFlags |= drawn; mBackgroundSizeChanged = true; + if (mForegroundInfo != null) { + mForegroundInfo.mBoundsChanged = true; + } notifySubtreeAccessibilityStateChangedIfNeeded(); } @@ -15992,6 +16059,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (mBackground != null) { mBackground.setLayoutDirection(layoutDirection); } + if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) { + mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection); + } mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED; onResolveDrawables(layoutDirection); } @@ -16047,7 +16117,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @CallSuper protected boolean verifyDrawable(Drawable who) { - return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who); + return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who) + || (mForegroundInfo != null && mForegroundInfo.mDrawable == who); } /** @@ -16065,9 +16136,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, protected void drawableStateChanged() { final int[] state = getDrawableState(); - final Drawable d = mBackground; - if (d != null && d.isStateful()) { - d.setState(state); + final Drawable bg = mBackground; + if (bg != null && bg.isStateful()) { + bg.setState(state); + } + + final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; + if (fg != null && fg.isStateful()) { + fg.setState(state); } if (mScrollCache != null) { @@ -16099,6 +16175,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (mBackground != null) { mBackground.setHotspot(x, y); } + if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) { + mForegroundInfo.mDrawable.setHotspot(x, y); + } dispatchDrawableHotspotChanged(x, y); } @@ -16270,6 +16349,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (mStateListAnimator != null) { mStateListAnimator.jumpToCurrentState(); } + if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) { + mForegroundInfo.mDrawable.jumpToCurrentState(); + } } /** @@ -16554,6 +16636,249 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Returns the drawable used as the foreground of this View. The + * foreground drawable, if non-null, is always drawn on top of the view's content. + * + * @return a Drawable or null if no foreground was set + * + * @see #onDrawForeground(Canvas) + */ + public Drawable getForeground() { + return mForegroundInfo != null ? mForegroundInfo.mDrawable : null; + } + + /** + * Supply a Drawable that is to be rendered on top of all of the content in the view. + * + * @param foreground the Drawable to be drawn on top of the children + * + * @attr ref android.R.styleable#View_foreground + */ + public void setForeground(Drawable foreground) { + if (mForegroundInfo == null) { + if (foreground == null) { + // Nothing to do. + return; + } + mForegroundInfo = new ForegroundInfo(); + } + + if (foreground == mForegroundInfo.mDrawable) { + // Nothing to do + return; + } + + if (mForegroundInfo.mDrawable != null) { + mForegroundInfo.mDrawable.setCallback(null); + unscheduleDrawable(mForegroundInfo.mDrawable); + } + + mForegroundInfo.mDrawable = foreground; + mForegroundInfo.mBoundsChanged = true; + if (foreground != null) { + setWillNotDraw(false); + foreground.setCallback(this); + foreground.setLayoutDirection(getLayoutDirection()); + if (foreground.isStateful()) { + foreground.setState(getDrawableState()); + } + applyForegroundTint(); + } + requestLayout(); + invalidate(); + } + + /** + * Magic bit used to support features of framework-internal window decor implementation details. + * This used to live exclusively in FrameLayout. + * + * @return true if the foreground should draw inside the padding region or false + * if it should draw inset by the view's padding + * @hide internal use only; only used by FrameLayout and internal screen layouts. + */ + public boolean isForegroundInsidePadding() { + return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true; + } + + /** + * Describes how the foreground is positioned. + * + * @return foreground gravity. + * + * @see #setForegroundGravity(int) + * + * @attr ref android.R.styleable#View_foregroundGravity + */ + public int getForegroundGravity() { + return mForegroundInfo != null ? mForegroundInfo.mGravity + : Gravity.START | Gravity.TOP; + } + + /** + * Describes how the foreground is positioned. Defaults to START and TOP. + * + * @param gravity see {@link android.view.Gravity} + * + * @see #getForegroundGravity() + * + * @attr ref android.R.styleable#View_foregroundGravity + */ + public void setForegroundGravity(int gravity) { + if (mForegroundInfo == null) { + mForegroundInfo = new ForegroundInfo(); + } + + if (mForegroundInfo.mGravity != gravity) { + if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) { + gravity |= Gravity.START; + } + + if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) { + gravity |= Gravity.TOP; + } + + mForegroundInfo.mGravity = gravity; + requestLayout(); + } + } + + /** + * Applies a tint to the foreground drawable. Does not modify the current tint + * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. + * <p> + * Subsequent calls to {@link #setForeground(Drawable)} will automatically + * mutate the drawable and apply the specified tint and tint mode using + * {@link Drawable#setTintList(ColorStateList)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * + * @attr ref android.R.styleable#View_foregroundTint + * @see #getForegroundTintList() + * @see Drawable#setTintList(ColorStateList) + */ + public void setForegroundTintList(@Nullable ColorStateList tint) { + if (mForegroundInfo == null) { + mForegroundInfo = new ForegroundInfo(); + } + if (mForegroundInfo.mTintInfo == null) { + mForegroundInfo.mTintInfo = new TintInfo(); + } + mForegroundInfo.mTintInfo.mTintList = tint; + mForegroundInfo.mTintInfo.mHasTintList = true; + + applyForegroundTint(); + } + + /** + * Return the tint applied to the foreground drawable, if specified. + * + * @return the tint applied to the foreground drawable + * @attr ref android.R.styleable#View_foregroundTint + * @see #setForegroundTintList(ColorStateList) + */ + @Nullable + public ColorStateList getForegroundTintList() { + return mForegroundInfo != null && mForegroundInfo.mTintInfo != null + ? mBackgroundTint.mTintList : null; + } + + /** + * Specifies the blending mode used to apply the tint specified by + * {@link #setForegroundTintList(ColorStateList)}} to the background + * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}. + * + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * @attr ref android.R.styleable#View_foregroundTintMode + * @see #getForegroundTintMode() + * @see Drawable#setTintMode(PorterDuff.Mode) + */ + public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) { + if (mBackgroundTint == null) { + mBackgroundTint = new TintInfo(); + } + mBackgroundTint.mTintMode = tintMode; + mBackgroundTint.mHasTintMode = true; + + applyBackgroundTint(); + } + + /** + * Return the blending mode used to apply the tint to the foreground + * drawable, if specified. + * + * @return the blending mode used to apply the tint to the foreground + * drawable + * @attr ref android.R.styleable#View_foregroundTintMode + * @see #setBackgroundTintMode(PorterDuff.Mode) + */ + @Nullable + public PorterDuff.Mode getForegroundTintMode() { + return mForegroundInfo != null && mForegroundInfo.mTintInfo != null + ? mForegroundInfo.mTintInfo.mTintMode : null; + } + + private void applyForegroundTint() { + if (mForegroundInfo != null && mForegroundInfo.mDrawable != null + && mForegroundInfo.mTintInfo != null) { + final TintInfo tintInfo = mForegroundInfo.mTintInfo; + if (tintInfo.mHasTintList || tintInfo.mHasTintMode) { + mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate(); + + if (tintInfo.mHasTintList) { + mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList); + } + + if (tintInfo.mHasTintMode) { + mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode); + } + + // The drawable (or one of its children) may not have been + // stateful before applying the tint, so let's try again. + if (mForegroundInfo.mDrawable.isStateful()) { + mForegroundInfo.mDrawable.setState(getDrawableState()); + } + } + } + } + + /** + * Draw any foreground content for this view. + * + * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground} + * drawable or other view-specific decorations. The foreground is drawn on top of the + * primary view content.</p> + * + * @param canvas canvas to draw into + */ + public void onDrawForeground(Canvas canvas) { + onDrawScrollBars(canvas); + + final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; + if (foreground != null) { + if (mForegroundInfo.mBoundsChanged) { + mForegroundInfo.mBoundsChanged = false; + final Rect selfBounds = mForegroundInfo.mSelfBounds; + final Rect overlayBounds = mForegroundInfo.mOverlayBounds; + + if (mForegroundInfo.mInsidePadding) { + selfBounds.set(0, 0, getWidth(), getHeight()); + } else { + selfBounds.set(getPaddingLeft(), getPaddingTop(), + getWidth() - getPaddingRight(), getHeight() - getPaddingBottom()); + } + + final int ld = getLayoutDirection(); + Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(), + foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld); + foreground.setBounds(overlayBounds); + } + + foreground.draw(canvas); + } + } + + /** * Sets the padding. The view may add on the space required to display * the scrollbars, depending on the style and visibility of the scrollbars. * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop}, @@ -18090,6 +18415,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // parts from this transparent region. applyDrawableToTransparentRegion(mBackground, region); } + final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; + if (foreground != null) { + applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region); + } } return true; } diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 6096d7d..77082b0 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -29,6 +29,8 @@ import android.util.LongArray; import android.util.Pools.SynchronizedPool; import android.view.View; +import com.android.internal.R; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -3402,6 +3404,15 @@ public class AccessibilityNodeInfo implements Parcelable { new AccessibilityAction( AccessibilityNodeInfo.ACTION_SET_TEXT, null); + /** + * Action that requests the node make its bounding rectangle visible + * on the screen, scrolling if necessary just enough. + * + * @see View#requestRectangleOnScreen(Rect) + */ + public static final AccessibilityAction ACTION_SHOW_ON_SCREEN = + new AccessibilityAction(R.id.accessibility_action_show_on_screen, null); + private static final ArraySet<AccessibilityAction> sStandardActions = new ArraySet<AccessibilityAction>(); static { sStandardActions.add(ACTION_FOCUS); @@ -3426,6 +3437,7 @@ public class AccessibilityNodeInfo implements Parcelable { sStandardActions.add(ACTION_COLLAPSE); sStandardActions.add(ACTION_DISMISS); sStandardActions.add(ACTION_SET_TEXT); + sStandardActions.add(ACTION_SHOW_ON_SCREEN); } private final int mActionId; diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java index 4737e9b..0b18bb8 100644 --- a/core/java/android/webkit/WebChromeClient.java +++ b/core/java/android/webkit/WebChromeClient.java @@ -284,13 +284,19 @@ public class WebChromeClient { * currently set for that origin. The host application should invoke the * specified callback with the desired permission state. See * {@link GeolocationPermissions} for details. + * + * If this method isn't overridden, the callback is invoked with permission + * denied state. + * * @param origin The origin of the web content attempting to use the * Geolocation API. * @param callback The callback to use to set the permission state for the * origin. */ public void onGeolocationPermissionsShowPrompt(String origin, - GeolocationPermissions.Callback callback) {} + GeolocationPermissions.Callback callback) { + callback.invoke(origin, false, false); + } /** * Notify the host application that a request for Geolocation permissions, diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 87fcd81..6e24837 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -4664,8 +4664,8 @@ public class Editor { // Otherwise the user inserted the composition. String newText = TextUtils.substring(source, start, end); - EditOperation edit = new EditOperation(mEditor, false, "", dstart, newText); - recordEdit(edit); + EditOperation edit = new EditOperation(mEditor, "", dstart, newText); + recordEdit(edit, false /* forceMerge */); return true; } @@ -4684,11 +4684,15 @@ public class Editor { // Build a new operation with all the information from this edit. String newText = TextUtils.substring(source, start, end); String oldText = TextUtils.substring(dest, dstart, dend); - EditOperation edit = new EditOperation(mEditor, forceMerge, oldText, dstart, newText); - recordEdit(edit); + EditOperation edit = new EditOperation(mEditor, oldText, dstart, newText); + recordEdit(edit, forceMerge); } - private void recordEdit(EditOperation edit) { + /** + * Fetches the last undo operation and checks to see if a new edit should be merged into it. + * If forceMerge is true then the new edit is always merged. + */ + private void recordEdit(EditOperation edit, boolean forceMerge) { // Fetch the last edit operation and attempt to merge in the new edit. final UndoManager um = mEditor.mUndoManager; um.beginUpdate("Edit text"); @@ -4698,6 +4702,11 @@ public class Editor { // Add this as the first edit. if (DEBUG_UNDO) Log.d(TAG, "filter: adding first op " + edit); um.addOperation(edit, UndoManager.MERGE_MODE_NONE); + } else if (forceMerge) { + // Forced merges take priority because they could be the result of a non-user-edit + // change and this case should not create a new undo operation. + if (DEBUG_UNDO) Log.d(TAG, "filter: force merge " + edit); + lastEdit.forceMergeWith(edit); } else if (!mIsUserEdit) { // An application directly modified the Editable outside of a text edit. Treat this // as a new change and don't attempt to merge. @@ -4773,7 +4782,6 @@ public class Editor { private static final int TYPE_REPLACE = 2; private int mType; - private boolean mForceMerge; private String mOldText; private int mOldTextStart; private String mNewText; @@ -4784,13 +4792,10 @@ public class Editor { /** * Constructs an edit operation from a text input operation on editor that replaces the - * oldText starting at dstart with newText. If forceMerge is true then always forcibly - * merge this operation with any previous one. + * oldText starting at dstart with newText. */ - public EditOperation(Editor editor, boolean forceMerge, String oldText, int dstart, - String newText) { + public EditOperation(Editor editor, String oldText, int dstart, String newText) { super(editor.mUndoOwner); - mForceMerge = forceMerge; mOldText = oldText; mNewText = newText; @@ -4817,7 +4822,6 @@ public class Editor { public EditOperation(Parcel src, ClassLoader loader) { super(src, loader); mType = src.readInt(); - mForceMerge = src.readInt() != 0; mOldText = src.readString(); mOldTextStart = src.readInt(); mNewText = src.readString(); @@ -4829,7 +4833,6 @@ public class Editor { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mType); - dest.writeInt(mForceMerge ? 1 : 0); dest.writeString(mOldText); dest.writeInt(mOldTextStart); dest.writeString(mNewText); @@ -4881,10 +4884,6 @@ public class Editor { Log.d(TAG, "mergeWith old " + this); Log.d(TAG, "mergeWith new " + edit); } - if (edit.mForceMerge) { - forceMergeWith(edit); - return true; - } switch (mType) { case TYPE_INSERT: return mergeInsertWith(edit); @@ -4942,7 +4941,7 @@ public class Editor { * Forcibly creates a single merged edit operation by simulating the entire text * contents being replaced. */ - private void forceMergeWith(EditOperation edit) { + public void forceMergeWith(EditOperation edit) { if (DEBUG_UNDO) Log.d(TAG, "forceMerge"); Editor editor = getOwnerData(); diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java index f6d198b..0602944 100644 --- a/core/java/android/widget/FrameLayout.java +++ b/core/java/android/widget/FrameLayout.java @@ -53,8 +53,6 @@ import com.android.internal.R; * only if {@link #setMeasureAllChildren(boolean) setConsiderGoneChildrenWhenMeasuring()} * is set to true. * - * @attr ref android.R.styleable#FrameLayout_foreground - * @attr ref android.R.styleable#FrameLayout_foregroundGravity * @attr ref android.R.styleable#FrameLayout_measureAllChildren */ @RemoteView @@ -64,13 +62,6 @@ public class FrameLayout extends ViewGroup { @ViewDebug.ExportedProperty(category = "measurement") boolean mMeasureAllChildren = false; - @ViewDebug.ExportedProperty(category = "drawing") - private Drawable mForeground; - private ColorStateList mForegroundTintList = null; - private PorterDuff.Mode mForegroundTintMode = null; - private boolean mHasForegroundTint = false; - private boolean mHasForegroundTintMode = false; - @ViewDebug.ExportedProperty(category = "padding") private int mForegroundPaddingLeft = 0; @@ -85,15 +76,6 @@ public class FrameLayout extends ViewGroup { private final Rect mSelfBounds = new Rect(); private final Rect mOverlayBounds = new Rect(); - - @ViewDebug.ExportedProperty(category = "drawing") - private int mForegroundGravity = Gravity.FILL; - - /** {@hide} */ - @ViewDebug.ExportedProperty(category = "drawing") - protected boolean mForegroundInPadding = true; - - boolean mForegroundBoundsChanged = false; private final ArrayList<View> mMatchParentChildren = new ArrayList<View>(1); @@ -115,48 +97,12 @@ public class FrameLayout extends ViewGroup { final TypedArray a = context.obtainStyledAttributes( attrs, com.android.internal.R.styleable.FrameLayout, defStyleAttr, defStyleRes); - - mForegroundGravity = a.getInt( - com.android.internal.R.styleable.FrameLayout_foregroundGravity, mForegroundGravity); - - final Drawable d = a.getDrawable(com.android.internal.R.styleable.FrameLayout_foreground); - if (d != null) { - setForeground(d); - } if (a.getBoolean(com.android.internal.R.styleable.FrameLayout_measureAllChildren, false)) { setMeasureAllChildren(true); } - if (a.hasValue(R.styleable.FrameLayout_foregroundTintMode)) { - mForegroundTintMode = Drawable.parseTintMode(a.getInt( - R.styleable.FrameLayout_foregroundTintMode, -1), mForegroundTintMode); - mHasForegroundTintMode = true; - } - - if (a.hasValue(R.styleable.FrameLayout_foregroundTint)) { - mForegroundTintList = a.getColorStateList(R.styleable.FrameLayout_foregroundTint); - mHasForegroundTint = true; - } - - mForegroundInPadding = a.getBoolean(R.styleable.FrameLayout_foregroundInsidePadding, true); - a.recycle(); - - applyForegroundTint(); - } - - /** - * Describes how the foreground is positioned. - * - * @return foreground gravity. - * - * @see #setForegroundGravity(int) - * - * @attr ref android.R.styleable#FrameLayout_foregroundGravity - */ - public int getForegroundGravity() { - return mForegroundGravity; } /** @@ -166,25 +112,18 @@ public class FrameLayout extends ViewGroup { * * @see #getForegroundGravity() * - * @attr ref android.R.styleable#FrameLayout_foregroundGravity + * @attr ref android.R.styleable#View_foregroundGravity */ @android.view.RemotableViewMethod public void setForegroundGravity(int foregroundGravity) { - if (mForegroundGravity != foregroundGravity) { - if ((foregroundGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) { - foregroundGravity |= Gravity.START; - } - - if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) { - foregroundGravity |= Gravity.TOP; - } - - mForegroundGravity = foregroundGravity; - + if (getForegroundGravity() != foregroundGravity) { + super.setForegroundGravity(foregroundGravity); - if (mForegroundGravity == Gravity.FILL && mForeground != null) { + // calling get* again here because the set above may apply default constraints + final Drawable foreground = getForeground(); + if (getForegroundGravity() == Gravity.FILL && foreground != null) { Rect padding = new Rect(); - if (mForeground.getPadding(padding)) { + if (foreground.getPadding(padding)) { mForegroundPaddingLeft = padding.left; mForegroundPaddingTop = padding.top; mForegroundPaddingRight = padding.right; @@ -201,53 +140,6 @@ public class FrameLayout extends ViewGroup { } } - @Override - protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) { - super.onVisibilityChanged(changedView, visibility); - - final Drawable dr = mForeground; - if (dr != null) { - final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE; - if (visible != dr.isVisible()) { - dr.setVisible(visible, false); - } - } - } - - /** - * {@inheritDoc} - */ - @Override - protected boolean verifyDrawable(Drawable who) { - return super.verifyDrawable(who) || (who == mForeground); - } - - @Override - public void jumpDrawablesToCurrentState() { - super.jumpDrawablesToCurrentState(); - if (mForeground != null) mForeground.jumpToCurrentState(); - } - - /** - * {@inheritDoc} - */ - @Override - protected void drawableStateChanged() { - super.drawableStateChanged(); - if (mForeground != null && mForeground.isStateful()) { - mForeground.setState(getDrawableState()); - } - } - - @Override - public void drawableHotspotChanged(float x, float y) { - super.drawableHotspotChanged(x, y); - - if (mForeground != null) { - mForeground.setHotspot(x, y); - } - } - /** * Returns a set of layout parameters with a width of * {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}, @@ -258,161 +150,23 @@ public class FrameLayout extends ViewGroup { return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); } - /** - * Supply a Drawable that is to be rendered on top of all of the child - * views in the frame layout. Any padding in the Drawable will be taken - * into account by ensuring that the children are inset to be placed - * inside of the padding area. - * - * @param d The Drawable to be drawn on top of the children. - * - * @attr ref android.R.styleable#FrameLayout_foreground - */ - public void setForeground(Drawable d) { - if (mForeground != d) { - if (mForeground != null) { - mForeground.setCallback(null); - unscheduleDrawable(mForeground); - } - - mForeground = d; - mForegroundPaddingLeft = 0; - mForegroundPaddingTop = 0; - mForegroundPaddingRight = 0; - mForegroundPaddingBottom = 0; - - if (d != null) { - setWillNotDraw(false); - d.setCallback(this); - d.setLayoutDirection(getLayoutDirection()); - if (d.isStateful()) { - d.setState(getDrawableState()); - } - applyForegroundTint(); - if (mForegroundGravity == Gravity.FILL) { - Rect padding = new Rect(); - if (d.getPadding(padding)) { - mForegroundPaddingLeft = padding.left; - mForegroundPaddingTop = padding.top; - mForegroundPaddingRight = padding.right; - mForegroundPaddingBottom = padding.bottom; - } - } - } else { - setWillNotDraw(true); - } - requestLayout(); - invalidate(); - } - } - - /** - * Returns the drawable used as the foreground of this FrameLayout. The - * foreground drawable, if non-null, is always drawn on top of the children. - * - * @return A Drawable or null if no foreground was set. - */ - public Drawable getForeground() { - return mForeground; - } - - /** - * Applies a tint to the foreground drawable. Does not modify the current - * tint mode, which is {@link PorterDuff.Mode#SRC_IN} by default. - * <p> - * Subsequent calls to {@link #setForeground(Drawable)} will automatically - * mutate the drawable and apply the specified tint and tint mode using - * {@link Drawable#setTintList(ColorStateList)}. - * - * @param tint the tint to apply, may be {@code null} to clear tint - * - * @attr ref android.R.styleable#FrameLayout_foregroundTint - * @see #getForegroundTintList() - * @see Drawable#setTintList(ColorStateList) - */ - public void setForegroundTintList(@Nullable ColorStateList tint) { - mForegroundTintList = tint; - mHasForegroundTint = true; - - applyForegroundTint(); - } - - /** - * @return the tint applied to the foreground drawable - * @attr ref android.R.styleable#FrameLayout_foregroundTint - * @see #setForegroundTintList(ColorStateList) - */ - @Nullable - public ColorStateList getForegroundTintList() { - return mForegroundTintList; - } - - /** - * Specifies the blending mode used to apply the tint specified by - * {@link #setForegroundTintList(ColorStateList)}} to the foreground drawable. - * The default mode is {@link PorterDuff.Mode#SRC_IN}. - * - * @param tintMode the blending mode used to apply the tint, may be - * {@code null} to clear tint - * @attr ref android.R.styleable#FrameLayout_foregroundTintMode - * @see #getForegroundTintMode() - * @see Drawable#setTintMode(PorterDuff.Mode) - */ - public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) { - mForegroundTintMode = tintMode; - mHasForegroundTintMode = true; - - applyForegroundTint(); - } - - /** - * @return the blending mode used to apply the tint to the foreground - * drawable - * @attr ref android.R.styleable#FrameLayout_foregroundTintMode - * @see #setForegroundTintMode(PorterDuff.Mode) - */ - @Nullable - public PorterDuff.Mode getForegroundTintMode() { - return mForegroundTintMode; - } - - private void applyForegroundTint() { - if (mForeground != null && (mHasForegroundTint || mHasForegroundTintMode)) { - mForeground = mForeground.mutate(); - - if (mHasForegroundTint) { - mForeground.setTintList(mForegroundTintList); - } - - if (mHasForegroundTintMode) { - mForeground.setTintMode(mForegroundTintMode); - } - - // The drawable (or one of its children) may not have been - // stateful before applying the tint, so let's try again. - if (mForeground.isStateful()) { - mForeground.setState(getDrawableState()); - } - } - } - int getPaddingLeftWithForeground() { - return mForegroundInPadding ? Math.max(mPaddingLeft, mForegroundPaddingLeft) : + return isForegroundInsidePadding() ? Math.max(mPaddingLeft, mForegroundPaddingLeft) : mPaddingLeft + mForegroundPaddingLeft; } int getPaddingRightWithForeground() { - return mForegroundInPadding ? Math.max(mPaddingRight, mForegroundPaddingRight) : + return isForegroundInsidePadding() ? Math.max(mPaddingRight, mForegroundPaddingRight) : mPaddingRight + mForegroundPaddingRight; } private int getPaddingTopWithForeground() { - return mForegroundInPadding ? Math.max(mPaddingTop, mForegroundPaddingTop) : + return isForegroundInsidePadding() ? Math.max(mPaddingTop, mForegroundPaddingTop) : mPaddingTop + mForegroundPaddingTop; } private int getPaddingBottomWithForeground() { - return mForegroundInPadding ? Math.max(mPaddingBottom, mForegroundPaddingBottom) : + return isForegroundInsidePadding() ? Math.max(mPaddingBottom, mForegroundPaddingBottom) : mPaddingBottom + mForegroundPaddingBottom; } @@ -527,8 +281,6 @@ public class FrameLayout extends ViewGroup { final int parentTop = getPaddingTopWithForeground(); final int parentBottom = bottom - top - getPaddingBottomWithForeground(); - mForegroundBoundsChanged = true; - for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() != GONE) { @@ -585,62 +337,6 @@ public class FrameLayout extends ViewGroup { } /** - * {@inheritDoc} - */ - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); - mForegroundBoundsChanged = true; - } - - /** - * {@inheritDoc} - */ - @Override - public void draw(Canvas canvas) { - super.draw(canvas); - - if (mForeground != null) { - final Drawable foreground = mForeground; - - if (mForegroundBoundsChanged) { - mForegroundBoundsChanged = false; - final Rect selfBounds = mSelfBounds; - final Rect overlayBounds = mOverlayBounds; - - final int w = mRight-mLeft; - final int h = mBottom-mTop; - - if (mForegroundInPadding) { - selfBounds.set(0, 0, w, h); - } else { - selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom); - } - - final int layoutDirection = getLayoutDirection(); - Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(), - foreground.getIntrinsicHeight(), selfBounds, overlayBounds, - layoutDirection); - foreground.setBounds(overlayBounds); - } - - foreground.draw(canvas); - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean gatherTransparentRegion(Region region) { - boolean opaque = super.gatherTransparentRegion(region); - if (region != null && mForeground != null) { - applyDrawableToTransparentRegion(mForeground, region); - } - return opaque; - } - - /** * Sets whether to consider all children, or just those in * the VISIBLE or INVISIBLE state, when measuring. Defaults to false. * diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java index af5a8bf..b187c1c 100644 --- a/core/java/android/widget/Gallery.java +++ b/core/java/android/widget/Gallery.java @@ -1209,13 +1209,13 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList switch (keyCode) { case KeyEvent.KEYCODE_DPAD_LEFT: - if (movePrevious()) { + if (moveDirection(-1)) { playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT); return true; } break; case KeyEvent.KEYCODE_DPAD_RIGHT: - if (moveNext()) { + if (moveDirection(1)) { playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT); return true; } @@ -1255,18 +1255,12 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList return super.onKeyUp(keyCode, event); } - boolean movePrevious() { - if (mItemCount > 0 && mSelectedPosition > 0) { - scrollToChild(mSelectedPosition - mFirstPosition - 1); - return true; - } else { - return false; - } - } + boolean moveDirection(int direction) { + direction = isLayoutRtl() ? -direction : direction; + int targetPosition = mSelectedPosition + direction; - boolean moveNext() { - if (mItemCount > 0 && mSelectedPosition < mItemCount - 1) { - scrollToChild(mSelectedPosition - mFirstPosition + 1); + if (mItemCount > 0 && targetPosition >= 0 && targetPosition < mItemCount) { + scrollToChild(targetPosition - mFirstPosition); return true; } else { return false; diff --git a/core/java/com/android/internal/logging/EventLogTags.logtags b/core/java/com/android/internal/logging/EventLogTags.logtags new file mode 100644 index 0000000..9e178df --- /dev/null +++ b/core/java/com/android/internal/logging/EventLogTags.logtags @@ -0,0 +1,7 @@ +# See system/core/logcat/event.logtags for a description of the format of this file. + +option java_package com.android.internal.logging; + +# interaction logs +524287 sysui_view_visibility (category|1|5),(visible|1|6) +524288 sysui_action (category|1|5),(type|1|6) diff --git a/core/java/com/android/internal/logging/MetricsConstants.java b/core/java/com/android/internal/logging/MetricsConstants.java new file mode 100644 index 0000000..e5cba84 --- /dev/null +++ b/core/java/com/android/internal/logging/MetricsConstants.java @@ -0,0 +1,153 @@ +/* + * 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 com.android.internal.logging; + +/** + * Constants for mestrics logs. + * + * @hide + */ +public interface MetricsConstants { + // These constants must match those in the analytic pipeline. + public static final int ACCESSIBILITY = 2; + public static final int ACCESSIBILITY_CAPTION_PROPERTIES = 3; + public static final int ACCESSIBILITY_SERVICE = 4; + public static final int ACCESSIBILITY_TOGGLE_DALTONIZER = 5; + public static final int ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE = 6; + public static final int ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION = 7; + public static final int ACCOUNT = 8; + public static final int ACCOUNTS_ACCOUNT_SYNC = 9; + public static final int ACCOUNTS_CHOOSE_ACCOUNT_ACTIVITY = 10; + public static final int ACCOUNTS_MANAGE_ACCOUNTS = 11; + public static final int APN = 12; + public static final int APN_EDITOR = 13; + public static final int APPLICATION = 16; + public static final int APPLICATIONS_APP_LAUNCH = 17; + public static final int APPLICATIONS_APP_PERMISSION = 18; + public static final int APPLICATIONS_APP_STORAGE = 19; + public static final int APPLICATIONS_INSTALLED_APP_DETAILS = 20; + public static final int APPLICATIONS_PROCESS_STATS_DETAIL = 21; + public static final int APPLICATIONS_PROCESS_STATS_MEM_DETAIL = 22; + public static final int APPLICATIONS_PROCESS_STATS_UI = 23; + public static final int APP_OPS_DETAILS = 14; + public static final int APP_OPS_SUMMARY = 15; + public static final int BLUETOOTH = 24; + public static final int BLUETOOTH_DEVICE_PICKER = 25; + public static final int BLUETOOTH_DEVICE_PROFILES = 26; + public static final int CHOOSE_LOCK_GENERIC = 27; + public static final int CHOOSE_LOCK_PASSWORD = 28; + public static final int CHOOSE_LOCK_PATTERN = 29; + public static final int CONFIRM_LOCK_PASSWORD = 30; + public static final int CONFIRM_LOCK_PATTERN = 31; + public static final int CRYPT_KEEPER = 32; + public static final int CRYPT_KEEPER_CONFIRM = 33; + public static final int DASHBOARD_SEARCH_RESULTS = 34; + public static final int DASHBOARD_SUMMARY = 35; + public static final int DATA_USAGE = 36; + public static final int DATA_USAGE_SUMMARY = 37; + public static final int DATE_TIME = 38; + public static final int DEVELOPMENT = 39; + public static final int DEVICEINFO = 40; + public static final int DEVICEINFO_IMEI_INFORMATION = 41; + public static final int DEVICEINFO_MEMORY = 42; + public static final int DEVICEINFO_SIM_STATUS = 43; + public static final int DEVICEINFO_STATUS = 44; + public static final int DEVICEINFO_USB = 45; + public static final int DISPLAY = 46; + public static final int DREAM = 47; + public static final int ENCRYPTION = 48; + public static final int FINGERPRINT = 49; + public static final int FINGERPRINT_ENROLL = 50; + public static final int FUELGAUGE_BATTERY_HISTORY_DETAIL = 51; + public static final int FUELGAUGE_BATTERY_SAVER = 52; + public static final int FUELGAUGE_POWER_USAGE_DETAIL = 53; + public static final int FUELGAUGE_POWER_USAGE_SUMMARY = 54; + public static final int HOME = 55; + public static final int ICC_LOCK = 56; + public static final int INPUTMETHOD_KEYBOARD = 58; + public static final int INPUTMETHOD_LANGUAGE = 57; + public static final int INPUTMETHOD_SPELL_CHECKERS = 59; + public static final int INPUTMETHOD_SUBTYPE_ENABLER = 60; + public static final int INPUTMETHOD_USER_DICTIONARY = 61; + public static final int INPUTMETHOD_USER_DICTIONARY_ADD_WORD = 62; + public static final int LOCATION = 63; + public static final int LOCATION_MODE = 64; + public static final int MAIN_SETTINGS = 1; + public static final int MANAGE_APPLICATIONS = 65; + public static final int MASTER_CLEAR = 66; + public static final int MASTER_CLEAR_CONFIRM = 67; + public static final int NET_DATA_USAGE_METERED = 68; + public static final int NFC_BEAM = 69; + public static final int NFC_PAYMENT = 70; + public static final int NOTIFICATION = 71; + public static final int NOTIFICATION_APP_NOTIFICATION = 72; + public static final int NOTIFICATION_OTHER_SOUND = 73; + public static final int NOTIFICATION_REDACTION = 74; + public static final int NOTIFICATION_STATION = 75; + public static final int NOTIFICATION_ZEN_MODE = 76; + public static final int OWNER_INFO = 77; + public static final int PRINT_JOB_SETTINGS = 78; + public static final int PRINT_SERVICE_SETTINGS = 79; + public static final int PRINT_SETTINGS = 80; + public static final int PRIVACY = 81; + public static final int PROXY_SELECTOR = 82; + public static final int QS_AIRPLANEMODE = 112; + public static final int QS_BLUETOOTH = 113; + public static final int QS_CAST = 114; + public static final int QS_CELLULAR = 115; + public static final int QS_COLORINVERSION = 116; + public static final int QS_DATAUSAGEDETAIL = 117; + public static final int QS_DND = 118; + public static final int QS_FLASHLIGHT = 119; + public static final int QS_HOTSPOT = 120; + public static final int QS_INTENT = 121; + public static final int QS_LOCATION = 122; + public static final int QS_PANEL = 111; + public static final int QS_ROTATIONLOCK = 123; + public static final int QS_USERDETAIL = 125; + public static final int QS_USERDETAILITE = 124; + public static final int QS_WIFI = 126; + public static final int RESET_NETWORK = 83; + public static final int RESET_NETWORK_CONFIRM = 84; + public static final int RUNNING_SERVICE_DETAILS = 85; + public static final int SCREEN_PINNING = 86; + public static final int SECURITY = 87; + public static final int SIM = 88; + public static final int TESTING = 89; + public static final int TETHER = 90; + public static final int TRUSTED_CREDENTIALS = 92; + public static final int TRUST_AGENT = 91; + public static final int TTS_ENGINE_SETTINGS = 93; + public static final int TTS_TEXT_TO_SPEECH = 94; + public static final int TYPE_UNKNOWN = 0; + public static final int USAGE_ACCESS = 95; + public static final int USER = 96; + public static final int USERS_APP_RESTRICTIONS = 97; + public static final int USER_DETAILS = 98; + public static final int VIEW_UNKNOWN = 0; + public static final int VOICE_INPUT = 99; + public static final int VPN = 100; + public static final int WALLPAPER_TYPE = 101; + public static final int WFD_WIFI_DISPLAY = 102; + public static final int WIFI = 103; + public static final int WIFI_ADVANCED = 104; + public static final int WIFI_APITEST = 107; + public static final int WIFI_CALLING = 105; + public static final int WIFI_INFO = 108; + public static final int WIFI_P2P = 109; + public static final int WIFI_SAVED_ACCESS_POINTS = 106; + public static final int WIRELESS = 110; +} diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java new file mode 100644 index 0000000..2de7394 --- /dev/null +++ b/core/java/com/android/internal/logging/MetricsLogger.java @@ -0,0 +1,47 @@ +/* + * 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 com.android.internal.logging; + + +import android.content.Context; +import android.os.Build; + +/** + * Log all the things. + * + * @hide + */ +public class MetricsLogger implements MetricsConstants { + // These constants are temporary, they should migrate to MetricsConstants. + public static final int APPLICATIONS_ADVANCED = 132; + public static final int LOCATION_SCANNING = 133; + public static final int MANAGE_APPLICATIONS_ALL = 134; + public static final int MANAGE_APPLICATIONS_NOTIFICATIONS = 135; + + public static void visible(Context context, int category) throws IllegalArgumentException { + if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) { + throw new IllegalArgumentException("Must define metric category"); + } + EventLogTags.writeSysuiViewVisibility(category, 100); + } + + public static void hidden(Context context, int category) { + if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) { + throw new IllegalArgumentException("Must define metric category"); + } + EventLogTags.writeSysuiViewVisibility(category, 0); + } +} diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index eaa0dc7..93dc995 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -16,18 +16,14 @@ package com.android.internal.os; -import static android.net.NetworkStats.UID_ALL; -import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED; - +import android.annotation.Nullable; import android.app.ActivityManager; import android.bluetooth.BluetoothActivityEnergyInfo; -import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkStats; -import android.net.wifi.IWifiManager; import android.net.wifi.WifiActivityEnergyInfo; import android.net.wifi.WifiManager; import android.os.BadParcelableException; @@ -42,8 +38,6 @@ import android.os.Parcel; import android.os.ParcelFormatException; import android.os.Parcelable; import android.os.Process; -import android.os.RemoteException; -import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; import android.os.WorkSource; @@ -65,13 +59,14 @@ import android.util.TimeUtils; import android.util.Xml; import android.view.Display; -import com.android.internal.annotations.GuardedBy; import com.android.internal.net.NetworkStatsFactory; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastPrintWriter; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.JournaledFile; import com.android.internal.util.XmlUtils; +import com.android.server.NetworkManagementSocketTagger; +import libcore.util.EmptyArray; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -109,7 +104,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 121 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 122 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -132,6 +127,9 @@ public final class BatteryStatsImpl extends BatteryStats { static final int MSG_REPORT_POWER_CHANGE = 2; static final long DELAY_UPDATE_WAKELOCKS = 5*1000; + private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader(); + private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats(); + public interface BatteryCallback { public void batteryNeedsCpuUpdate(); public void batteryPowerChanged(boolean onBattery); @@ -160,7 +158,12 @@ public final class BatteryStatsImpl extends BatteryStats { } } + public interface ExternalStatsSync { + void scheduleSync(); + } + public final MyHandler mHandler; + private final ExternalStatsSync mExternalSync; private BatteryCallback mCallback; @@ -330,7 +333,7 @@ public final class BatteryStatsImpl extends BatteryStats { int mPhoneSignalStrengthBin = -1; int mPhoneSignalStrengthBinRaw = -1; - final StopwatchTimer[] mPhoneSignalStrengthsTimer = + final StopwatchTimer[] mPhoneSignalStrengthsTimer = new StopwatchTimer[SignalStrength.NUM_SIGNAL_STRENGTH_BINS]; StopwatchTimer mPhoneSignalScanningTimer; @@ -445,18 +448,17 @@ public final class BatteryStatsImpl extends BatteryStats { private int mLoadedNumConnectivityChange; private int mUnpluggedNumConnectivityChange; + private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry(); + /* * Holds a SamplingTimer associated with each kernel wakelock name being tracked. */ - private final HashMap<String, SamplingTimer> mKernelWakelockStats = - new HashMap<String, SamplingTimer>(); + private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>(); public Map<String, ? extends Timer> getKernelWakelockStats() { return mKernelWakelockStats; } - private static int sKernelWakelockUpdateVersion = 0; - String mLastWakeupReason = null; long mLastWakeupUptimeMs = 0; private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>(); @@ -465,56 +467,12 @@ public final class BatteryStatsImpl extends BatteryStats { return mWakeupReasonStats; } - private static final int[] PROC_WAKELOCKS_FORMAT = new int[] { - Process.PROC_TAB_TERM|Process.PROC_OUT_STRING| // 0: name - Process.PROC_QUOTES, - Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 1: count - Process.PROC_TAB_TERM, - Process.PROC_TAB_TERM, - Process.PROC_TAB_TERM, - Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 5: totalTime - }; - - private static final int[] WAKEUP_SOURCES_FORMAT = new int[] { - Process.PROC_TAB_TERM|Process.PROC_OUT_STRING, // 0: name - Process.PROC_TAB_TERM|Process.PROC_COMBINE| - Process.PROC_OUT_LONG, // 1: count - Process.PROC_TAB_TERM|Process.PROC_COMBINE, - Process.PROC_TAB_TERM|Process.PROC_COMBINE, - Process.PROC_TAB_TERM|Process.PROC_COMBINE, - Process.PROC_TAB_TERM|Process.PROC_COMBINE, - Process.PROC_TAB_TERM|Process.PROC_COMBINE - |Process.PROC_OUT_LONG, // 6: totalTime - }; - - private final String[] mProcWakelocksName = new String[3]; - private final long[] mProcWakelocksData = new long[3]; - - /* - * Used as a buffer for reading in data from /proc/wakelocks before it is processed and added - * to mKernelWakelockStats. - */ - private final Map<String, KernelWakelockStats> mProcWakelockFileStats = - new HashMap<String, KernelWakelockStats>(); - - private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory(); - private NetworkStats mCurMobileSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50); - private NetworkStats mLastMobileSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50); - private NetworkStats mCurWifiSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50); - private NetworkStats mLastWifiSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50); - private NetworkStats mTmpNetworkStats; - private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry(); - - @GuardedBy("this") - private String[] mMobileIfaces = new String[0]; - @GuardedBy("this") - private String[] mWifiIfaces = new String[0]; - public BatteryStatsImpl() { mFile = null; mCheckinFile = null; mDailyFile = null; mHandler = null; + mExternalSync = null; clearHistoryLocked(); } @@ -524,7 +482,7 @@ public final class BatteryStatsImpl extends BatteryStats { } static class TimeBase { - private final ArrayList<TimeBaseObs> mObservers = new ArrayList<TimeBaseObs>(); + private final ArrayList<TimeBaseObs> mObservers = new ArrayList<>(); private long mUptime; private long mRealtime; @@ -1779,147 +1737,6 @@ public final class BatteryStatsImpl extends BatteryStats { return timer; } - private final Map<String, KernelWakelockStats> readKernelWakelockStats() { - - FileInputStream is; - byte[] buffer = new byte[32*1024]; - int len; - boolean wakeup_sources; - - try { - try { - is = new FileInputStream("/d/wakeup_sources"); - wakeup_sources = true; - } catch (java.io.FileNotFoundException e) { - try { - is = new FileInputStream("/proc/wakelocks"); - wakeup_sources = false; - } catch (java.io.FileNotFoundException e2) { - return null; - } - } - - len = is.read(buffer); - is.close(); - } catch (java.io.IOException e) { - return null; - } - - if (len > 0) { - if (len >= buffer.length) { - Slog.wtf(TAG, "Kernel wake locks exceeded buffer size " + buffer.length); - } - int i; - for (i=0; i<len; i++) { - if (buffer[i] == '\0') { - len = i; - break; - } - } - } - - return parseProcWakelocks(buffer, len, wakeup_sources); - } - - private final Map<String, KernelWakelockStats> parseProcWakelocks( - byte[] wlBuffer, int len, boolean wakeup_sources) { - String name; - int count; - long totalTime; - int startIndex; - int endIndex; - int numUpdatedWlNames = 0; - - // Advance past the first line. - int i; - for (i = 0; i < len && wlBuffer[i] != '\n' && wlBuffer[i] != '\0'; i++); - startIndex = endIndex = i + 1; - - synchronized(this) { - Map<String, KernelWakelockStats> m = mProcWakelockFileStats; - - sKernelWakelockUpdateVersion++; - while (endIndex < len) { - for (endIndex=startIndex; - endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0'; - endIndex++); - endIndex++; // endIndex is an exclusive upper bound. - // Don't go over the end of the buffer, Process.parseProcLine might - // write to wlBuffer[endIndex] - if (endIndex >= (len - 1) ) { - return m; - } - - String[] nameStringArray = mProcWakelocksName; - long[] wlData = mProcWakelocksData; - // Stomp out any bad characters since this is from a circular buffer - // A corruption is seen sometimes that results in the vm crashing - // This should prevent crashes and the line will probably fail to parse - for (int j = startIndex; j < endIndex; j++) { - if ((wlBuffer[j] & 0x80) != 0) wlBuffer[j] = (byte) '?'; - } - boolean parsed = Process.parseProcLine(wlBuffer, startIndex, endIndex, - wakeup_sources ? WAKEUP_SOURCES_FORMAT : - PROC_WAKELOCKS_FORMAT, - nameStringArray, wlData, null); - - name = nameStringArray[0]; - count = (int) wlData[1]; - - if (wakeup_sources) { - // convert milliseconds to microseconds - totalTime = wlData[2] * 1000; - } else { - // convert nanoseconds to microseconds with rounding. - totalTime = (wlData[2] + 500) / 1000; - } - - if (parsed && name.length() > 0) { - if (!m.containsKey(name)) { - m.put(name, new KernelWakelockStats(count, totalTime, - sKernelWakelockUpdateVersion)); - numUpdatedWlNames++; - } else { - KernelWakelockStats kwlStats = m.get(name); - if (kwlStats.mVersion == sKernelWakelockUpdateVersion) { - kwlStats.mCount += count; - kwlStats.mTotalTime += totalTime; - } else { - kwlStats.mCount = count; - kwlStats.mTotalTime = totalTime; - kwlStats.mVersion = sKernelWakelockUpdateVersion; - numUpdatedWlNames++; - } - } - } - startIndex = endIndex; - } - - if (m.size() != numUpdatedWlNames) { - // Don't report old data. - Iterator<KernelWakelockStats> itr = m.values().iterator(); - while (itr.hasNext()) { - if (itr.next().mVersion != sKernelWakelockUpdateVersion) { - itr.remove(); - } - } - } - return m; - } - } - - private class KernelWakelockStats { - public int mCount; - public long mTotalTime; - public int mVersion; - - KernelWakelockStats(int count, long totalTime, int version) { - mCount = count; - mTotalTime = totalTime; - mVersion = version; - } - } - /* * Get the KernelWakelockTimer associated with name, and create a new one if one * doesn't already exist. @@ -3391,7 +3208,7 @@ public final class BatteryStatsImpl extends BatteryStats { mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime); } else { mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs); - updateNetworkActivityLocked(NET_UPDATE_MOBILE, realElapsedRealtimeMs); + updateMobileRadioStateLocked(realElapsedRealtimeMs); mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs); } } @@ -3729,6 +3546,7 @@ public final class BatteryStatsImpl extends BatteryStats { addHistoryRecordLocked(elapsedRealtime, uptime); mWifiOn = true; mWifiOnTimer.startRunningLocked(elapsedRealtime); + scheduleSyncExternalStatsLocked(); } } @@ -3742,6 +3560,7 @@ public final class BatteryStatsImpl extends BatteryStats { addHistoryRecordLocked(elapsedRealtime, uptime); mWifiOn = false; mWifiOnTimer.stopRunningLocked(elapsedRealtime); + scheduleSyncExternalStatsLocked(); } } @@ -3904,6 +3723,7 @@ public final class BatteryStatsImpl extends BatteryStats { int uid = mapUid(ws.get(i)); getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime); } + scheduleSyncExternalStatsLocked(); } else { Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running"); } @@ -3942,6 +3762,7 @@ public final class BatteryStatsImpl extends BatteryStats { int uid = mapUid(ws.get(i)); getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime); } + scheduleSyncExternalStatsLocked(); } else { Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running"); } @@ -3956,6 +3777,7 @@ public final class BatteryStatsImpl extends BatteryStats { } mWifiState = wifiState; mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime); + scheduleSyncExternalStatsLocked(); } } @@ -4027,6 +3849,7 @@ public final class BatteryStatsImpl extends BatteryStats { addHistoryRecordLocked(elapsedRealtime, uptime); mBluetoothOn = true; mBluetoothOnTimer.startRunningLocked(elapsedRealtime); + scheduleSyncExternalStatsLocked(); } } @@ -4040,6 +3863,7 @@ public final class BatteryStatsImpl extends BatteryStats { addHistoryRecordLocked(elapsedRealtime, uptime); mBluetoothOn = false; mBluetoothOnTimer.stopRunningLocked(elapsedRealtime); + scheduleSyncExternalStatsLocked(); } } @@ -4066,6 +3890,7 @@ public final class BatteryStatsImpl extends BatteryStats { if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: " + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(elapsedRealtime, uptime); + scheduleSyncExternalStatsLocked(); } mWifiFullLockNesting++; getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime); @@ -4081,6 +3906,7 @@ public final class BatteryStatsImpl extends BatteryStats { if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: " + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(elapsedRealtime, uptime); + scheduleSyncExternalStatsLocked(); } getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(elapsedRealtime); } @@ -4138,6 +3964,7 @@ public final class BatteryStatsImpl extends BatteryStats { if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: " + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(elapsedRealtime, uptime); + scheduleSyncExternalStatsLocked(); } mWifiMulticastNesting++; getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime); @@ -4153,6 +3980,7 @@ public final class BatteryStatsImpl extends BatteryStats { if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: " + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(elapsedRealtime, uptime); + scheduleSyncExternalStatsLocked(); } getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(elapsedRealtime); } @@ -4260,7 +4088,8 @@ public final class BatteryStatsImpl extends BatteryStats { // During device boot, qtaguid isn't enabled until after the inital // loading of battery stats. Now that they're enabled, take our initial // snapshot for future delta calculation. - updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime()); + updateMobileRadioStateLocked(SystemClock.elapsedRealtime()); + updateWifiStateLocked(null); } @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) { @@ -4607,17 +4436,17 @@ public final class BatteryStatsImpl extends BatteryStats { } @Override - public Map<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() { + public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() { return mWakelockStats.getMap(); } @Override - public Map<String, ? extends BatteryStats.Timer> getSyncStats() { + public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() { return mSyncStats.getMap(); } @Override - public Map<String, ? extends BatteryStats.Timer> getJobStats() { + public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() { return mJobStats.getMap(); } @@ -4627,12 +4456,12 @@ public final class BatteryStatsImpl extends BatteryStats { } @Override - public Map<String, ? extends BatteryStats.Uid.Proc> getProcessStats() { + public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() { return mProcessStats; } @Override - public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() { + public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() { return mPackageStats; } @@ -5950,7 +5779,7 @@ public final class BatteryStatsImpl extends BatteryStats { Slog.w(TAG, "File corrupt: too many excessive power entries " + N); return false; } - + mExcessivePower = new ArrayList<ExcessivePower>(); for (int i=0; i<N; i++) { ExcessivePower ew = new ExcessivePower(); @@ -6153,40 +5982,20 @@ public final class BatteryStatsImpl extends BatteryStats { */ public final class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs { /** - * Number of times this package has done something that could wake up the - * device from sleep. - */ - int mWakeups; - - /** - * Number of things that could wake up the device loaded from a - * previous save. - */ - int mLoadedWakeups; - - /** - * Number of things that could wake up the device as of the - * last run. - */ - int mLastWakeups; - - /** - * Number of things that could wake up the device as of the - * last run. + * Number of times wakeup alarms have occurred for this app. */ - int mUnpluggedWakeups; + ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>(); /** * The statics we have collected for this package's services. */ - final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>(); + final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>(); Pkg() { mOnBatteryScreenOffTimeBase.add(this); } public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { - mUnpluggedWakeups = mWakeups; } public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { @@ -6197,10 +6006,12 @@ public final class BatteryStatsImpl extends BatteryStats { } void readFromParcelLocked(Parcel in) { - mWakeups = in.readInt(); - mLoadedWakeups = in.readInt(); - mLastWakeups = 0; - mUnpluggedWakeups = in.readInt(); + int numWA = in.readInt(); + mWakeupAlarms.clear(); + for (int i=0; i<numWA; i++) { + String tag = in.readString(); + mWakeupAlarms.put(tag, new Counter(mOnBatteryTimeBase, in)); + } int numServs = in.readInt(); mServiceStats.clear(); @@ -6214,34 +6025,39 @@ public final class BatteryStatsImpl extends BatteryStats { } void writeToParcelLocked(Parcel out) { - out.writeInt(mWakeups); - out.writeInt(mLoadedWakeups); - out.writeInt(mUnpluggedWakeups); - - out.writeInt(mServiceStats.size()); - for (Map.Entry<String, Uid.Pkg.Serv> servEntry : mServiceStats.entrySet()) { - out.writeString(servEntry.getKey()); - Uid.Pkg.Serv serv = servEntry.getValue(); - + int numWA = mWakeupAlarms.size(); + out.writeInt(numWA); + for (int i=0; i<numWA; i++) { + out.writeString(mWakeupAlarms.keyAt(i)); + mWakeupAlarms.valueAt(i).writeToParcel(out); + } + + final int NS = mServiceStats.size(); + out.writeInt(NS); + for (int i=0; i<NS; i++) { + out.writeString(mServiceStats.keyAt(i)); + Uid.Pkg.Serv serv = mServiceStats.valueAt(i); serv.writeToParcelLocked(out); } } @Override - public Map<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() { - return mServiceStats; + public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() { + return mWakeupAlarms; } - @Override - public int getWakeups(int which) { - int val = mWakeups; - if (which == STATS_CURRENT) { - val -= mLoadedWakeups; - } else if (which == STATS_SINCE_UNPLUGGED) { - val -= mUnpluggedWakeups; + public void noteWakeupAlarmLocked(String tag) { + Counter c = mWakeupAlarms.get(tag); + if (c == null) { + c = new Counter(mOnBatteryTimeBase); + mWakeupAlarms.put(tag, c); } + c.stepAtomic(); + } - return val; + @Override + public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() { + return mServiceStats; } /** @@ -6483,14 +6299,6 @@ public final class BatteryStatsImpl extends BatteryStats { } } - public BatteryStatsImpl getBatteryStats() { - return BatteryStatsImpl.this; - } - - public void incWakeupsLocked() { - mWakeups++; - } - final Serv newServiceStatsLocked() { return new Serv(); } @@ -6749,7 +6557,7 @@ public final class BatteryStatsImpl extends BatteryStats { } } - public BatteryStatsImpl(File systemDir, Handler handler) { + public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) { if (systemDir != null) { mFile = new JournaledFile(new File(systemDir, "batterystats.bin"), new File(systemDir, "batterystats.bin.tmp")); @@ -6758,6 +6566,7 @@ public final class BatteryStatsImpl extends BatteryStats { } mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin")); mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml")); + mExternalSync = externalSync; mHandler = new MyHandler(handler.getLooper()); mStartCount++; mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase); @@ -6830,6 +6639,7 @@ public final class BatteryStatsImpl extends BatteryStats { mCheckinFile = null; mDailyFile = null; mHandler = null; + mExternalSync = null; clearHistoryLocked(); readFromParcel(p); } @@ -7501,21 +7311,233 @@ public final class BatteryStatsImpl extends BatteryStats { mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel; } } - + public void pullPendingStateUpdatesLocked() { - updateKernelWakelocksLocked(); - updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime()); - // TODO(adamlesinski): enable when bluedroid stops deadlocking. b/19248786 - // updateBluetoothControllerActivityLocked(); - // TODO(adamlesinski): disabled to avoid deadlock. Need to change how external - // data is pulled/accessed from BatteryStats. b/19729960 - // updateWifiControllerActivityLocked(); if (mOnBatteryInternal) { final boolean screenOn = mScreenState == Display.STATE_ON; updateDischargeScreenLevelsLocked(screenOn, screenOn); } } + private String[] mMobileIfaces = EmptyArray.STRING; + private String[] mWifiIfaces = EmptyArray.STRING; + + private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory(); + + private static final int NETWORK_STATS_LAST = 0; + private static final int NETWORK_STATS_NEXT = 1; + private static final int NETWORK_STATS_DELTA = 2; + + private final NetworkStats[] mMobileNetworkStats = new NetworkStats[] { + new NetworkStats(SystemClock.elapsedRealtime(), 50), + new NetworkStats(SystemClock.elapsedRealtime(), 50), + new NetworkStats(SystemClock.elapsedRealtime(), 50) + }; + + private final NetworkStats[] mWifiNetworkStats = new NetworkStats[] { + new NetworkStats(SystemClock.elapsedRealtime(), 50), + new NetworkStats(SystemClock.elapsedRealtime(), 50), + new NetworkStats(SystemClock.elapsedRealtime(), 50) + }; + + /** + * Retrieves the delta of network stats for the given network ifaces. Uses networkStatsBuffer + * as a buffer of NetworkStats objects to cycle through when computing deltas. + */ + private NetworkStats getNetworkStatsDeltaLocked(String[] ifaces, + NetworkStats[] networkStatsBuffer) + throws IOException { + if (!SystemProperties.getBoolean(NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED, + false)) { + return null; + } + + final NetworkStats stats = mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL, + ifaces, NetworkStats.TAG_NONE, networkStatsBuffer[NETWORK_STATS_NEXT]); + networkStatsBuffer[NETWORK_STATS_DELTA] = NetworkStats.subtract(stats, + networkStatsBuffer[NETWORK_STATS_LAST], null, null, + networkStatsBuffer[NETWORK_STATS_DELTA]); + networkStatsBuffer[NETWORK_STATS_NEXT] = networkStatsBuffer[NETWORK_STATS_LAST]; + networkStatsBuffer[NETWORK_STATS_LAST] = stats; + return networkStatsBuffer[NETWORK_STATS_DELTA]; + } + + /** + * Distribute WiFi energy info and network traffic to apps. + * @param info The energy information from the WiFi controller. + */ + public void updateWifiStateLocked(@Nullable final WifiActivityEnergyInfo info) { + final NetworkStats delta; + try { + delta = getNetworkStatsDeltaLocked(mWifiIfaces, mWifiNetworkStats); + } catch (IOException e) { + Slog.wtf(TAG, "Failed to get wifi network stats", e); + return; + } + + if (!mOnBatteryInternal) { + return; + } + + if (delta != null) { + final int size = delta.size(); + for (int i = 0; i < size; i++) { + final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry); + + if (DEBUG) { + Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes + + " tx=" + entry.txBytes); + } + + if (entry.rxBytes == 0 || entry.txBytes == 0) { + continue; + } + + final Uid u = getUidStatsLocked(mapUid(entry.uid)); + u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes, + entry.rxPackets); + u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes, + entry.txPackets); + + mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked( + entry.rxBytes); + mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked( + entry.txBytes); + mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked( + entry.rxPackets); + mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked( + entry.txPackets); + } + } + + if (info != null) { + // Update WiFi controller stats. + mWifiActivityCounters[CONTROLLER_RX_TIME].addCountLocked( + info.getControllerRxTimeMillis()); + mWifiActivityCounters[CONTROLLER_TX_TIME].addCountLocked( + info.getControllerTxTimeMillis()); + mWifiActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked( + info.getControllerIdleTimeMillis()); + mWifiActivityCounters[CONTROLLER_ENERGY].addCountLocked( + info.getControllerEnergyUsed()); + } + } + + /** + * Distribute Cell radio energy info and network traffic to apps. + */ + public void updateMobileRadioStateLocked(long elapsedRealtimeMs) { + final NetworkStats delta; + + try { + delta = getNetworkStatsDeltaLocked(mMobileIfaces, mMobileNetworkStats); + } catch (IOException e) { + Slog.wtf(TAG, "Failed to get mobile network stats", e); + return; + } + + if (delta == null || !mOnBatteryInternal) { + return; + } + + long radioTime = mMobileRadioActivePerAppTimer.checkpointRunningLocked(elapsedRealtimeMs); + long totalPackets = delta.getTotalPackets(); + + final int size = delta.size(); + for (int i = 0; i < size; i++) { + final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry); + + if (entry.rxBytes == 0 || entry.txBytes == 0) continue; + + final Uid u = getUidStatsLocked(mapUid(entry.uid)); + u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes, + entry.rxPackets); + u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes, + entry.txPackets); + + if (radioTime > 0) { + // Distribute total radio active time in to this app. + long appPackets = entry.rxPackets + entry.txPackets; + long appRadioTime = (radioTime*appPackets)/totalPackets; + u.noteMobileRadioActiveTimeLocked(appRadioTime); + // Remove this app from the totals, so that we don't lose any time + // due to rounding. + radioTime -= appRadioTime; + totalPackets -= appPackets; + } + + mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked( + entry.rxBytes); + mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked( + entry.txBytes); + mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked( + entry.rxPackets); + mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked( + entry.txPackets); + } + + if (radioTime > 0) { + // Whoops, there is some radio time we can't blame on an app! + mMobileRadioActiveUnknownTime.addCountLocked(radioTime); + mMobileRadioActiveUnknownCount.addCountLocked(1); + } + } + + /** + * Distribute Bluetooth energy info and network traffic to apps. + * @param info The energy information from the bluetooth controller. + */ + public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) { + if (info != null && mOnBatteryInternal) { + mBluetoothActivityCounters[CONTROLLER_RX_TIME].addCountLocked( + info.getControllerRxTimeMillis()); + mBluetoothActivityCounters[CONTROLLER_TX_TIME].addCountLocked( + info.getControllerTxTimeMillis()); + mBluetoothActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked( + info.getControllerIdleTimeMillis()); + mBluetoothActivityCounters[CONTROLLER_ENERGY].addCountLocked( + info.getControllerEnergyUsed()); + } + } + + /** + * Read and distribute kernel wake lock use across apps. + */ + public void updateKernelWakelocksLocked() { + final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats( + mTmpWakelockStats); + if (wakelockStats == null) { + // Not crashing might make board bringup easier. + Slog.w(TAG, "Couldn't get kernel wake lock stats"); + return; + } + + for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) { + String name = ent.getKey(); + KernelWakelockStats.Entry kws = ent.getValue(); + + SamplingTimer kwlt = mKernelWakelockStats.get(name); + if (kwlt == null) { + kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase, + true /* track reported val */); + mKernelWakelockStats.put(name, kwlt); + } + kwlt.updateCurrentReportedCount(kws.mCount); + kwlt.updateCurrentReportedTotalTime(kws.mTotalTime); + kwlt.setUpdateVersion(kws.mVersion); + } + + if (wakelockStats.size() != mKernelWakelockStats.size()) { + // Set timers to stale if they didn't appear in /proc/wakelocks this time. + for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { + SamplingTimer st = ent.getValue(); + if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) { + st.setStale(); + } + } + } + } + void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery, final int oldStatus, final int level) { boolean doWrite = false; @@ -7669,340 +7691,132 @@ public final class BatteryStatsImpl extends BatteryStats { } } + private void scheduleSyncExternalStatsLocked() { + if (mExternalSync != null) { + mExternalSync.scheduleSync(); + } + } + // This should probably be exposed in the API, though it's not critical - private static final int BATTERY_PLUGGED_NONE = 0; + public static final int BATTERY_PLUGGED_NONE = 0; - public void setBatteryState(int status, int health, int plugType, int level, + public void setBatteryStateLocked(int status, int health, int plugType, int level, int temp, int volt) { - synchronized(this) { - final boolean onBattery = plugType == BATTERY_PLUGGED_NONE; - final long uptime = SystemClock.uptimeMillis(); - final long elapsedRealtime = SystemClock.elapsedRealtime(); - if (!mHaveBatteryLevel) { - mHaveBatteryLevel = true; - // We start out assuming that the device is plugged in (not - // on battery). If our first report is now that we are indeed - // plugged in, then twiddle our state to correctly reflect that - // since we won't be going through the full setOnBattery(). - if (onBattery == mOnBattery) { - if (onBattery) { - mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG; - } else { - mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG; - } - } - mHistoryCur.batteryStatus = (byte)status; - mHistoryCur.batteryLevel = (byte)level; - mMaxChargeStepLevel = mMinDischargeStepLevel = - mLastChargeStepLevel = mLastDischargeStepLevel = level; - } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) { - recordDailyStatsIfNeededLocked(level >= 100 && onBattery); - } - int oldStatus = mHistoryCur.batteryStatus; - if (onBattery) { - mDischargeCurrentLevel = level; - if (!mRecordingHistory) { - mRecordingHistory = true; - startRecordingHistory(elapsedRealtime, uptime, true); - } - } else if (level < 96) { - if (!mRecordingHistory) { - mRecordingHistory = true; - startRecordingHistory(elapsedRealtime, uptime, true); - } - } - mCurrentBatteryLevel = level; - if (mDischargePlugLevel < 0) { - mDischargePlugLevel = level; - } - if (onBattery != mOnBattery) { - mHistoryCur.batteryLevel = (byte)level; - mHistoryCur.batteryStatus = (byte)status; - mHistoryCur.batteryHealth = (byte)health; - mHistoryCur.batteryPlugType = (byte)plugType; - mHistoryCur.batteryTemperature = (short)temp; - mHistoryCur.batteryVoltage = (char)volt; - setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level); - } else { - boolean changed = false; - if (mHistoryCur.batteryLevel != level) { - mHistoryCur.batteryLevel = (byte)level; - changed = true; - } - if (mHistoryCur.batteryStatus != status) { - mHistoryCur.batteryStatus = (byte)status; - changed = true; - } - if (mHistoryCur.batteryHealth != health) { - mHistoryCur.batteryHealth = (byte)health; - changed = true; - } - if (mHistoryCur.batteryPlugType != plugType) { - mHistoryCur.batteryPlugType = (byte)plugType; - changed = true; - } - if (temp >= (mHistoryCur.batteryTemperature+10) - || temp <= (mHistoryCur.batteryTemperature-10)) { - mHistoryCur.batteryTemperature = (short)temp; - changed = true; - } - if (volt > (mHistoryCur.batteryVoltage+20) - || volt < (mHistoryCur.batteryVoltage-20)) { - mHistoryCur.batteryVoltage = (char)volt; - changed = true; - } - if (changed) { - addHistoryRecordLocked(elapsedRealtime, uptime); - } - long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT) - | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT) - | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT); + final boolean onBattery = plugType == BATTERY_PLUGGED_NONE; + final long uptime = SystemClock.uptimeMillis(); + final long elapsedRealtime = SystemClock.elapsedRealtime(); + if (!mHaveBatteryLevel) { + mHaveBatteryLevel = true; + // We start out assuming that the device is plugged in (not + // on battery). If our first report is now that we are indeed + // plugged in, then twiddle our state to correctly reflect that + // since we won't be going through the full setOnBattery(). + if (onBattery == mOnBattery) { if (onBattery) { - if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) { - mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level, - modeBits, elapsedRealtime); - mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level, - modeBits, elapsedRealtime); - mLastDischargeStepLevel = level; - mMinDischargeStepLevel = level; - mInitStepMode = mCurStepMode; - mModStepMode = 0; - } + mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG; } else { - if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) { - mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel, - modeBits, elapsedRealtime); - mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel, - modeBits, elapsedRealtime); - mLastChargeStepLevel = level; - mMaxChargeStepLevel = level; - mInitStepMode = mCurStepMode; - mModStepMode = 0; - } + mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG; } } - if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) { - // We don't record history while we are plugged in and fully charged. - // The next time we are unplugged, history will be cleared. - mRecordingHistory = DEBUG; + mHistoryCur.batteryStatus = (byte)status; + mHistoryCur.batteryLevel = (byte)level; + mMaxChargeStepLevel = mMinDischargeStepLevel = + mLastChargeStepLevel = mLastDischargeStepLevel = level; + } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) { + recordDailyStatsIfNeededLocked(level >= 100 && onBattery); + } + int oldStatus = mHistoryCur.batteryStatus; + if (onBattery) { + mDischargeCurrentLevel = level; + if (!mRecordingHistory) { + mRecordingHistory = true; + startRecordingHistory(elapsedRealtime, uptime, true); + } + } else if (level < 96) { + if (!mRecordingHistory) { + mRecordingHistory = true; + startRecordingHistory(elapsedRealtime, uptime, true); } } - } - - public void updateKernelWakelocksLocked() { - Map<String, KernelWakelockStats> m = readKernelWakelockStats(); - - if (m == null) { - // Not crashing might make board bringup easier. - Slog.w(TAG, "Couldn't get kernel wake lock stats"); - return; + mCurrentBatteryLevel = level; + if (mDischargePlugLevel < 0) { + mDischargePlugLevel = level; } + if (onBattery != mOnBattery) { + mHistoryCur.batteryLevel = (byte)level; + mHistoryCur.batteryStatus = (byte)status; + mHistoryCur.batteryHealth = (byte)health; + mHistoryCur.batteryPlugType = (byte)plugType; + mHistoryCur.batteryTemperature = (short)temp; + mHistoryCur.batteryVoltage = (char)volt; + setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level); + } else { + boolean changed = false; + if (mHistoryCur.batteryLevel != level) { + mHistoryCur.batteryLevel = (byte)level; + changed = true; - for (Map.Entry<String, KernelWakelockStats> ent : m.entrySet()) { - String name = ent.getKey(); - KernelWakelockStats kws = ent.getValue(); - - SamplingTimer kwlt = mKernelWakelockStats.get(name); - if (kwlt == null) { - kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase, - true /* track reported val */); - mKernelWakelockStats.put(name, kwlt); + // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record + // which will pull external stats. + scheduleSyncExternalStatsLocked(); } - kwlt.updateCurrentReportedCount(kws.mCount); - kwlt.updateCurrentReportedTotalTime(kws.mTotalTime); - kwlt.setUpdateVersion(sKernelWakelockUpdateVersion); - } - - if (m.size() != mKernelWakelockStats.size()) { - // Set timers to stale if they didn't appear in /proc/wakelocks this time. - for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { - SamplingTimer st = ent.getValue(); - if (st.getUpdateVersion() != sKernelWakelockUpdateVersion) { - st.setStale(); - } + if (mHistoryCur.batteryStatus != status) { + mHistoryCur.batteryStatus = (byte)status; + changed = true; } - } - } - - static final int NET_UPDATE_MOBILE = 1<<0; - static final int NET_UPDATE_WIFI = 1<<1; - static final int NET_UPDATE_ALL = 0xffff; - - private void updateNetworkActivityLocked(int which, long elapsedRealtimeMs) { - if (!SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) return; - - if ((which&NET_UPDATE_MOBILE) != 0 && mMobileIfaces.length > 0) { - final NetworkStats snapshot; - final NetworkStats last = mCurMobileSnapshot; - try { - snapshot = mNetworkStatsFactory.readNetworkStatsDetail(UID_ALL, - mMobileIfaces, NetworkStats.TAG_NONE, mLastMobileSnapshot); - } catch (IOException e) { - Log.wtf(TAG, "Failed to read mobile network stats", e); - return; + if (mHistoryCur.batteryHealth != health) { + mHistoryCur.batteryHealth = (byte)health; + changed = true; } - - mCurMobileSnapshot = snapshot; - mLastMobileSnapshot = last; - - if (mOnBatteryInternal) { - final NetworkStats delta = NetworkStats.subtract(snapshot, last, - null, null, mTmpNetworkStats); - mTmpNetworkStats = delta; - - long radioTime = mMobileRadioActivePerAppTimer.checkpointRunningLocked( - elapsedRealtimeMs); - long totalPackets = delta.getTotalPackets(); - - final int size = delta.size(); - for (int i = 0; i < size; i++) { - final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry); - - if (entry.rxBytes == 0 || entry.txBytes == 0) continue; - - final Uid u = getUidStatsLocked(mapUid(entry.uid)); - u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes, - entry.rxPackets); - u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes, - entry.txPackets); - - if (radioTime > 0) { - // Distribute total radio active time in to this app. - long appPackets = entry.rxPackets + entry.txPackets; - long appRadioTime = (radioTime*appPackets)/totalPackets; - u.noteMobileRadioActiveTimeLocked(appRadioTime); - // Remove this app from the totals, so that we don't lose any time - // due to rounding. - radioTime -= appRadioTime; - totalPackets -= appPackets; - } - - mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked( - entry.rxBytes); - mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked( - entry.txBytes); - mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked( - entry.rxPackets); - mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked( - entry.txPackets); - } - - if (radioTime > 0) { - // Whoops, there is some radio time we can't blame on an app! - mMobileRadioActiveUnknownTime.addCountLocked(radioTime); - mMobileRadioActiveUnknownCount.addCountLocked(1); - } + if (mHistoryCur.batteryPlugType != plugType) { + mHistoryCur.batteryPlugType = (byte)plugType; + changed = true; } - } - - if ((which&NET_UPDATE_WIFI) != 0 && mWifiIfaces.length > 0) { - final NetworkStats snapshot; - final NetworkStats last = mCurWifiSnapshot; - try { - snapshot = mNetworkStatsFactory.readNetworkStatsDetail(UID_ALL, - mWifiIfaces, NetworkStats.TAG_NONE, mLastWifiSnapshot); - } catch (IOException e) { - Log.wtf(TAG, "Failed to read wifi network stats", e); - return; + if (temp >= (mHistoryCur.batteryTemperature+10) + || temp <= (mHistoryCur.batteryTemperature-10)) { + mHistoryCur.batteryTemperature = (short)temp; + changed = true; } - - mCurWifiSnapshot = snapshot; - mLastWifiSnapshot = last; - - if (mOnBatteryInternal) { - final NetworkStats delta = NetworkStats.subtract(snapshot, last, - null, null, mTmpNetworkStats); - mTmpNetworkStats = delta; - - final int size = delta.size(); - for (int i = 0; i < size; i++) { - final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry); - - if (DEBUG) { - final NetworkStats.Entry cur = snapshot.getValues(i, null); - Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes - + " tx=" + entry.txBytes + ", cur rx=" + cur.rxBytes - + " tx=" + cur.txBytes); - } - - if (entry.rxBytes == 0 || entry.txBytes == 0) continue; - - final Uid u = getUidStatsLocked(mapUid(entry.uid)); - u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes, - entry.rxPackets); - u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes, - entry.txPackets); - - mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked( - entry.rxBytes); - mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked( - entry.txBytes); - mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked( - entry.rxPackets); - mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked( - entry.txPackets); + if (volt > (mHistoryCur.batteryVoltage+20) + || volt < (mHistoryCur.batteryVoltage-20)) { + mHistoryCur.batteryVoltage = (char)volt; + changed = true; + } + if (changed) { + addHistoryRecordLocked(elapsedRealtime, uptime); + } + long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT) + | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT) + | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT); + if (onBattery) { + if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) { + mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level, + modeBits, elapsedRealtime); + mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level, + modeBits, elapsedRealtime); + mLastDischargeStepLevel = level; + mMinDischargeStepLevel = level; + mInitStepMode = mCurStepMode; + mModStepMode = 0; + } + } else { + if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) { + mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel, + modeBits, elapsedRealtime); + mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel, + modeBits, elapsedRealtime); + mLastChargeStepLevel = level; + mMaxChargeStepLevel = level; + mInitStepMode = mCurStepMode; + mModStepMode = 0; } } } - } - - private void updateBluetoothControllerActivityLocked() { - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if (adapter == null) { - return; - } - - // We read the data even if we are not on battery. Each read clears - // the previous data, so we must always read to make sure the - // data is for the current interval. - BluetoothActivityEnergyInfo info = adapter.getControllerActivityEnergyInfo( - BluetoothAdapter.ACTIVITY_ENERGY_INFO_REFRESHED); - if (info == null || !info.isValid() || !mOnBatteryInternal) { - // Bad info or we are not on battery. - return; - } - - mBluetoothActivityCounters[CONTROLLER_RX_TIME].addCountLocked( - info.getControllerRxTimeMillis()); - mBluetoothActivityCounters[CONTROLLER_TX_TIME].addCountLocked( - info.getControllerTxTimeMillis()); - mBluetoothActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked( - info.getControllerIdleTimeMillis()); - mBluetoothActivityCounters[CONTROLLER_ENERGY].addCountLocked( - info.getControllerEnergyUsed()); - } - - private void updateWifiControllerActivityLocked() { - IWifiManager wifiManager = IWifiManager.Stub.asInterface( - ServiceManager.getService(Context.WIFI_SERVICE)); - if (wifiManager == null) { - return; - } - - WifiActivityEnergyInfo info; - try { - // We read the data even if we are not on battery. Each read clears - // the previous data, so we must always read to make sure the - // data is for the current interval. - info = wifiManager.reportActivityInfo(); - } catch (RemoteException e) { - // Nothing to report, WiFi is dead. - return; + if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) { + // We don't record history while we are plugged in and fully charged. + // The next time we are unplugged, history will be cleared. + mRecordingHistory = DEBUG; } - - if (info == null || !info.isValid() || !mOnBatteryInternal) { - // Bad info or we are not on battery. - return; - } - - mWifiActivityCounters[CONTROLLER_RX_TIME].addCountLocked( - info.getControllerRxTimeMillis()); - mWifiActivityCounters[CONTROLLER_TX_TIME].addCountLocked( - info.getControllerTxTimeMillis()); - mWifiActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked( - info.getControllerIdleTimeMillis()); - mWifiActivityCounters[CONTROLLER_ENERGY].addCountLocked( - info.getControllerEnergyUsed()); } public long getAwakeTimeBattery() { @@ -8938,7 +8752,18 @@ public final class BatteryStatsImpl extends BatteryStats { for (int ip = 0; ip < NP; ip++) { String pkgName = in.readString(); Uid.Pkg p = u.getPackageStatsLocked(pkgName); - p.mWakeups = p.mLoadedWakeups = in.readInt(); + final int NWA = in.readInt(); + if (NWA > 1000) { + Slog.w(TAG, "File corrupt: too many wakeup alarms " + NWA); + return; + } + p.mWakeupAlarms.clear(); + for (int iwa=0; iwa<NWA; iwa++) { + String tag = in.readString(); + Counter c = new Counter(mOnBatteryTimeBase); + c.readSummaryFromParcelLocked(in); + p.mWakeupAlarms.put(tag, c); + } NS = in.readInt(); if (NS > 1000) { Slog.w(TAG, "File corrupt: too many services " + NS); @@ -9263,20 +9088,22 @@ public final class BatteryStatsImpl extends BatteryStats { : u.mPackageStats.entrySet()) { out.writeString(ent.getKey()); Uid.Pkg ps = ent.getValue(); - out.writeInt(ps.mWakeups); + final int NWA = ps.mWakeupAlarms.size(); + out.writeInt(NWA); + for (int iwa=0; iwa<NWA; iwa++) { + out.writeString(ps.mWakeupAlarms.keyAt(iwa)); + ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out); + } NS = ps.mServiceStats.size(); out.writeInt(NS); - if (NS > 0) { - for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent - : ps.mServiceStats.entrySet()) { - out.writeString(sent.getKey()); - BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue(); - long time = ss.getStartTimeToNowLocked( - mOnBatteryTimeBase.getUptime(NOW_SYS)); - out.writeLong(time); - out.writeInt(ss.mStarts); - out.writeInt(ss.mLaunches); - } + for (int is=0; is<NS; is++) { + out.writeString(ps.mServiceStats.keyAt(is)); + BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is); + long time = ss.getStartTimeToNowLocked( + mOnBatteryTimeBase.getUptime(NOW_SYS)); + out.writeLong(time); + out.writeInt(ss.mStarts); + out.writeInt(ss.mLaunches); } } } diff --git a/core/java/com/android/internal/os/KernelWakelockReader.java b/core/java/com/android/internal/os/KernelWakelockReader.java new file mode 100644 index 0000000..768d586 --- /dev/null +++ b/core/java/com/android/internal/os/KernelWakelockReader.java @@ -0,0 +1,192 @@ +/* + * 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 com.android.internal.os; + +import android.os.Process; +import android.util.Slog; + +import java.io.FileInputStream; +import java.util.Iterator; + +/** + * Reads and parses wakelock stats from the kernel (/proc/wakelocks). + */ +public class KernelWakelockReader { + private static final String TAG = "KernelWakelockReader"; + private static int sKernelWakelockUpdateVersion = 0; + private static final String sWakelockFile = "/proc/wakelocks"; + private static final String sWakeupSourceFile = "/d/wakeup_sources"; + + private static final int[] PROC_WAKELOCKS_FORMAT = new int[] { + Process.PROC_TAB_TERM|Process.PROC_OUT_STRING| // 0: name + Process.PROC_QUOTES, + Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 1: count + Process.PROC_TAB_TERM, + Process.PROC_TAB_TERM, + Process.PROC_TAB_TERM, + Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 5: totalTime + }; + + private static final int[] WAKEUP_SOURCES_FORMAT = new int[] { + Process.PROC_TAB_TERM|Process.PROC_OUT_STRING, // 0: name + Process.PROC_TAB_TERM|Process.PROC_COMBINE| + Process.PROC_OUT_LONG, // 1: count + Process.PROC_TAB_TERM|Process.PROC_COMBINE, + Process.PROC_TAB_TERM|Process.PROC_COMBINE, + Process.PROC_TAB_TERM|Process.PROC_COMBINE, + Process.PROC_TAB_TERM|Process.PROC_COMBINE, + Process.PROC_TAB_TERM|Process.PROC_COMBINE + |Process.PROC_OUT_LONG, // 6: totalTime + }; + + private final String[] mProcWakelocksName = new String[3]; + private final long[] mProcWakelocksData = new long[3]; + + /** + * Reads kernel wakelock stats and updates the staleStats with the new information. + * @param staleStats Existing object to update. + * @return the updated data. + */ + public final KernelWakelockStats readKernelWakelockStats(KernelWakelockStats staleStats) { + byte[] buffer = new byte[32*1024]; + int len; + boolean wakeup_sources; + + try { + FileInputStream is; + try { + is = new FileInputStream(sWakeupSourceFile); + wakeup_sources = true; + } catch (java.io.FileNotFoundException e) { + try { + is = new FileInputStream(sWakelockFile); + wakeup_sources = false; + } catch (java.io.FileNotFoundException e2) { + return null; + } + } + + len = is.read(buffer); + is.close(); + } catch (java.io.IOException e) { + return null; + } + + if (len > 0) { + if (len >= buffer.length) { + Slog.wtf(TAG, "Kernel wake locks exceeded buffer size " + buffer.length); + } + int i; + for (i=0; i<len; i++) { + if (buffer[i] == '\0') { + len = i; + break; + } + } + } + return parseProcWakelocks(buffer, len, wakeup_sources, staleStats); + } + + /** + * Reads the wakelocks and updates the staleStats with the new information. + */ + private KernelWakelockStats parseProcWakelocks(byte[] wlBuffer, int len, boolean wakeup_sources, + final KernelWakelockStats staleStats) { + String name; + int count; + long totalTime; + int startIndex; + int endIndex; + int numUpdatedWlNames = 0; + + // Advance past the first line. + int i; + for (i = 0; i < len && wlBuffer[i] != '\n' && wlBuffer[i] != '\0'; i++); + startIndex = endIndex = i + 1; + + synchronized(this) { + sKernelWakelockUpdateVersion++; + while (endIndex < len) { + for (endIndex=startIndex; + endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0'; + endIndex++); + endIndex++; // endIndex is an exclusive upper bound. + // Don't go over the end of the buffer, Process.parseProcLine might + // write to wlBuffer[endIndex] + if (endIndex >= (len - 1) ) { + return staleStats; + } + + String[] nameStringArray = mProcWakelocksName; + long[] wlData = mProcWakelocksData; + // Stomp out any bad characters since this is from a circular buffer + // A corruption is seen sometimes that results in the vm crashing + // This should prevent crashes and the line will probably fail to parse + for (int j = startIndex; j < endIndex; j++) { + if ((wlBuffer[j] & 0x80) != 0) wlBuffer[j] = (byte) '?'; + } + boolean parsed = Process.parseProcLine(wlBuffer, startIndex, endIndex, + wakeup_sources ? WAKEUP_SOURCES_FORMAT : + PROC_WAKELOCKS_FORMAT, + nameStringArray, wlData, null); + + name = nameStringArray[0]; + count = (int) wlData[1]; + + if (wakeup_sources) { + // convert milliseconds to microseconds + totalTime = wlData[2] * 1000; + } else { + // convert nanoseconds to microseconds with rounding. + totalTime = (wlData[2] + 500) / 1000; + } + + if (parsed && name.length() > 0) { + if (!staleStats.containsKey(name)) { + staleStats.put(name, new KernelWakelockStats.Entry(count, totalTime, + sKernelWakelockUpdateVersion)); + numUpdatedWlNames++; + } else { + KernelWakelockStats.Entry kwlStats = staleStats.get(name); + if (kwlStats.mVersion == sKernelWakelockUpdateVersion) { + kwlStats.mCount += count; + kwlStats.mTotalTime += totalTime; + } else { + kwlStats.mCount = count; + kwlStats.mTotalTime = totalTime; + kwlStats.mVersion = sKernelWakelockUpdateVersion; + numUpdatedWlNames++; + } + } + } + startIndex = endIndex; + } + + if (staleStats.size() != numUpdatedWlNames) { + // Don't report old data. + Iterator<KernelWakelockStats.Entry> itr = staleStats.values().iterator(); + while (itr.hasNext()) { + if (itr.next().mVersion != sKernelWakelockUpdateVersion) { + itr.remove(); + } + } + } + + staleStats.kernelWakelockVersion = sKernelWakelockUpdateVersion; + return staleStats; + } + } +} diff --git a/core/java/com/android/internal/os/KernelWakelockStats.java b/core/java/com/android/internal/os/KernelWakelockStats.java new file mode 100644 index 0000000..144ea00 --- /dev/null +++ b/core/java/com/android/internal/os/KernelWakelockStats.java @@ -0,0 +1,37 @@ +/* + * 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 com.android.internal.os; + +import java.util.HashMap; + +/** + * Kernel wakelock stats object. + */ +public class KernelWakelockStats extends HashMap<String, KernelWakelockStats.Entry> { + public static class Entry { + public int mCount; + public long mTotalTime; + public int mVersion; + + Entry(int count, long totalTime, int version) { + mCount = count; + mTotalTime = totalTime; + mVersion = version; + } + } + + int kernelWakelockVersion; +} diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java index d9ebc25..a106f48 100644 --- a/core/java/com/android/internal/util/Protocol.java +++ b/core/java/com/android/internal/util/Protocol.java @@ -52,6 +52,7 @@ public class Protocol { public static final int BASE_WIFI_RTT_SERVICE = 0x00027300; public static final int BASE_WIFI_PASSPOINT_MANAGER = 0x00028000; public static final int BASE_WIFI_PASSPOINT_SERVICE = 0x00028100; + public static final int BASE_WIFI_LOGGER = 0x00028300; public static final int BASE_DHCP = 0x00030000; public static final int BASE_DATA_CONNECTION = 0x00040000; public static final int BASE_DATA_CONNECTION_AC = 0x00041000; diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java new file mode 100644 index 0000000..be9945d --- /dev/null +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -0,0 +1,596 @@ +/* + * 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 com.android.internal.widget; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.graphics.Color; +import android.graphics.Point; +import android.graphics.Rect; +import android.graphics.drawable.ColorDrawable; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.View.MeasureSpec; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.Button; +import android.widget.ImageButton; +import android.widget.LinearLayout; +import android.widget.PopupWindow; + +import com.android.internal.R; +import com.android.internal.util.Preconditions; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +/** + * A floating toolbar for showing contextual menu items. + * This view shows as many menu item buttons as can fit in the horizontal toolbar and the + * the remaining menu items in a vertical overflow view when the overflow button is clicked. + * The horizontal toolbar morphs into the vertical overflow view. + */ +public final class FloatingToolbar { + + private static final MenuItem.OnMenuItemClickListener NO_OP_MENUITEM_CLICK_LISTENER = + new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + return false; + } + }; + + private final Context mContext; + private final FloatingToolbarPopup mPopup; + private final ViewGroup mMenuItemButtonsContainer; + private final View.OnClickListener mMenuItemButtonOnClickListener = + new View.OnClickListener() { + @Override + public void onClick(View v) { + if (v.getTag() instanceof MenuItem) { + mMenuItemClickListener.onMenuItemClick((MenuItem) v.getTag()); + mPopup.dismiss(); + } + } + }; + + private final Rect mContentRect = new Rect(); + private final Point mCoordinates = new Point(); + + private Menu mMenu; + private List<CharSequence> mShowingTitles = new ArrayList<CharSequence>(); + private MenuItem.OnMenuItemClickListener mMenuItemClickListener = NO_OP_MENUITEM_CLICK_LISTENER; + private View mOpenOverflowButton; + + private int mSuggestedWidth; + + /** + * Initializes a floating toolbar. + */ + public FloatingToolbar(Context context, Window window) { + mContext = Preconditions.checkNotNull(context); + mPopup = new FloatingToolbarPopup(Preconditions.checkNotNull(window.getDecorView())); + mMenuItemButtonsContainer = createMenuButtonsContainer(context); + } + + /** + * Sets the menu to be shown in this floating toolbar. + * NOTE: Call {@link #updateLayout()} or {@link #show()} to effect visual changes to the + * toolbar. + */ + public FloatingToolbar setMenu(Menu menu) { + mMenu = Preconditions.checkNotNull(menu); + return this; + } + + /** + * Sets the custom listener for invocation of menu items in this floating + * toolbar. + */ + public FloatingToolbar setOnMenuItemClickListener( + MenuItem.OnMenuItemClickListener menuItemClickListener) { + if (menuItemClickListener != null) { + mMenuItemClickListener = menuItemClickListener; + } else { + mMenuItemClickListener = NO_OP_MENUITEM_CLICK_LISTENER; + } + return this; + } + + /** + * Sets the content rectangle. This is the area of the interesting content that this toolbar + * should avoid obstructing. + * NOTE: Call {@link #updateLayout()} or {@link #show()} to effect visual changes to the + * toolbar. + */ + public FloatingToolbar setContentRect(Rect rect) { + mContentRect.set(Preconditions.checkNotNull(rect)); + return this; + } + + /** + * Sets the suggested width of this floating toolbar. + * The actual width will be about this size but there are no guarantees that it will be exactly + * the suggested width. + * NOTE: Call {@link #updateLayout()} or {@link #show()} to effect visual changes to the + * toolbar. + */ + public FloatingToolbar setSuggestedWidth(int suggestedWidth) { + mSuggestedWidth = suggestedWidth; + return this; + } + + /** + * Shows this floating toolbar. + */ + public FloatingToolbar show() { + List<MenuItem> menuItems = getVisibleAndEnabledMenuItems(mMenu); + if (hasContentChanged(menuItems) || hasWidthChanged()) { + mPopup.dismiss(); + layoutMenuItemButtons(menuItems); + mShowingTitles = getMenuItemTitles(menuItems); + } + refreshCoordinates(); + mPopup.updateCoordinates(mCoordinates.x, mCoordinates.y); + if (!mPopup.isShowing()) { + mPopup.show(mCoordinates.x, mCoordinates.y); + } + return this; + } + + /** + * Updates this floating toolbar to reflect recent position and view updates. + * NOTE: This method is a no-op if the toolbar isn't showing. + */ + public FloatingToolbar updateLayout() { + if (mPopup.isShowing()) { + // show() performs all the logic we need here. + show(); + } + return this; + } + + /** + * Dismisses this floating toolbar. + */ + public void dismiss() { + mPopup.dismiss(); + } + + /** + * Returns {@code true} if this popup is currently showing. {@code false} otherwise. + */ + public boolean isShowing() { + return mPopup.isShowing(); + } + + /** + * Refreshes {@link #mCoordinates} with values based on {@link #mContentRect}. + */ + private void refreshCoordinates() { + int popupWidth = mPopup.getWidth(); + int popupHeight = mPopup.getHeight(); + if (!mPopup.isShowing()) { + // Popup isn't yet shown, get estimated size from the menu item buttons container. + mMenuItemButtonsContainer.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); + popupWidth = mMenuItemButtonsContainer.getMeasuredWidth(); + popupHeight = mMenuItemButtonsContainer.getMeasuredHeight(); + } + int x = mContentRect.centerX() - popupWidth / 2; + int y; + if (shouldDisplayAtTopOfContent()) { + y = mContentRect.top - popupHeight; + } else { + y = mContentRect.bottom; + } + mCoordinates.set(x, y); + } + + /** + * Returns true if this floating toolbar's menu items have been reordered or changed. + */ + private boolean hasContentChanged(List<MenuItem> menuItems) { + return !mShowingTitles.equals(getMenuItemTitles(menuItems)); + } + + /** + * Returns true if there is a significant change in width of the toolbar. + */ + private boolean hasWidthChanged() { + int actualWidth = mPopup.getWidth(); + int difference = Math.abs(actualWidth - mSuggestedWidth); + return difference > (actualWidth * 0.2); + } + + /** + * Returns true if the preferred positioning of the toolbar is above the content rect. + */ + private boolean shouldDisplayAtTopOfContent() { + return mContentRect.top - getMinimumOverflowHeight(mContext) > 0; + } + + /** + * Returns the visible and enabled menu items in the specified menu. + * This method is recursive. + */ + private List<MenuItem> getVisibleAndEnabledMenuItems(Menu menu) { + List<MenuItem> menuItems = new ArrayList<MenuItem>(); + for (int i = 0; (menu != null) && (i < menu.size()); i++) { + MenuItem menuItem = menu.getItem(i); + if (menuItem.isVisible() && menuItem.isEnabled()) { + Menu subMenu = menuItem.getSubMenu(); + if (subMenu != null) { + menuItems.addAll(getVisibleAndEnabledMenuItems(subMenu)); + } else { + menuItems.add(menuItem); + } + } + } + return menuItems; + } + + private List<CharSequence> getMenuItemTitles(List<MenuItem> menuItems) { + List<CharSequence> titles = new ArrayList<CharSequence>(); + for (MenuItem menuItem : menuItems) { + titles.add(menuItem.getTitle()); + } + return titles; + } + + private void layoutMenuItemButtons(List<MenuItem> menuItems) { + final int toolbarWidth = getAdjustedToolbarWidth(mContext, mSuggestedWidth) + // Reserve space for the "open overflow" button. + - getEstimatedOpenOverflowButtonWidth(mContext); + + int availableWidth = toolbarWidth; + LinkedList<MenuItem> remainingMenuItems = new LinkedList<MenuItem>(menuItems); + + mMenuItemButtonsContainer.removeAllViews(); + + boolean isFirstItem = true; + while (!remainingMenuItems.isEmpty()) { + final MenuItem menuItem = remainingMenuItems.peek(); + Button menuItemButton = createMenuItemButton(mContext, menuItem); + + // Adding additional left padding for the first button to even out button spacing. + if (isFirstItem) { + menuItemButton.setPadding( + 2 * menuItemButton.getPaddingLeft(), + menuItemButton.getPaddingTop(), + menuItemButton.getPaddingRight(), + menuItemButton.getPaddingBottom()); + isFirstItem = false; + } + + // Adding additional right padding for the last button to even out button spacing. + if (remainingMenuItems.size() == 1) { + menuItemButton.setPadding( + menuItemButton.getPaddingLeft(), + menuItemButton.getPaddingTop(), + 2 * menuItemButton.getPaddingRight(), + menuItemButton.getPaddingBottom()); + } + + menuItemButton.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); + int menuItemButtonWidth = Math.min(menuItemButton.getMeasuredWidth(), toolbarWidth); + if (menuItemButtonWidth <= availableWidth) { + menuItemButton.setTag(menuItem); + menuItemButton.setOnClickListener(mMenuItemButtonOnClickListener); + mMenuItemButtonsContainer.addView(menuItemButton); + menuItemButton.getLayoutParams().width = menuItemButtonWidth; + availableWidth -= menuItemButtonWidth; + remainingMenuItems.pop(); + } else { + // The "open overflow" button launches the vertical overflow from the + // floating toolbar. + createOpenOverflowButtonIfNotExists(); + mMenuItemButtonsContainer.addView(mOpenOverflowButton); + break; + } + } + mPopup.setContentView(mMenuItemButtonsContainer); + } + + /** + * Creates and returns the button that opens the vertical overflow. + */ + private void createOpenOverflowButtonIfNotExists() { + mOpenOverflowButton = (ImageButton) LayoutInflater.from(mContext) + .inflate(R.layout.floating_popup_open_overflow_button, null); + mOpenOverflowButton.setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View v) { + // Open the overflow. + } + }); + } + + /** + * Creates and returns a floating toolbar menu buttons container. + */ + private static ViewGroup createMenuButtonsContainer(Context context) { + return (ViewGroup) LayoutInflater.from(context) + .inflate(R.layout.floating_popup_container, null); + } + + /** + * Creates and returns a menu button for the specified menu item. + */ + private static Button createMenuItemButton(Context context, MenuItem menuItem) { + Button menuItemButton = (Button) LayoutInflater.from(context) + .inflate(R.layout.floating_popup_menu_button, null); + menuItemButton.setText(menuItem.getTitle()); + menuItemButton.setContentDescription(menuItem.getTitle()); + return menuItemButton; + } + + private static int getMinimumOverflowHeight(Context context) { + return context.getResources(). + getDimensionPixelSize(R.dimen.floating_toolbar_minimum_overflow_height); + } + + private static int getEstimatedOpenOverflowButtonWidth(Context context) { + return context.getResources() + .getDimensionPixelSize(R.dimen.floating_toolbar_menu_button_minimum_width); + } + + private static int getAdjustedToolbarWidth(Context context, int width) { + if (width <= 0 || width > getScreenWidth(context)) { + width = context.getResources() + .getDimensionPixelSize(R.dimen.floating_toolbar_default_width); + } + return width; + } + + /** + * Returns the device's screen width. + */ + public static int getScreenWidth(Context context) { + return context.getResources().getDisplayMetrics().widthPixels; + } + + /** + * Returns the device's screen height. + */ + public static int getScreenHeight(Context context) { + return context.getResources().getDisplayMetrics().heightPixels; + } + + + /** + * A popup window used by the floating toolbar. + */ + private static final class FloatingToolbarPopup { + + private final View mParent; + private final PopupWindow mPopupWindow; + private final ViewGroup mContentContainer; + private final Animator.AnimatorListener mOnDismissEnd = + new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mPopupWindow.dismiss(); + mDismissAnimating = false; + } + }; + private final AnimatorSet mGrowFadeInFromBottomAnimation; + private final AnimatorSet mShrinkFadeOutFromBottomAnimation; + + private boolean mDismissAnimating; + + /** + * Initializes a new floating bar popup. + * + * @param parent A parent view to get the {@link View#getWindowToken()} token from. + */ + public FloatingToolbarPopup(View parent) { + mParent = Preconditions.checkNotNull(parent); + mContentContainer = createContentContainer(parent.getContext()); + mPopupWindow = createPopupWindow(mContentContainer); + mGrowFadeInFromBottomAnimation = createGrowFadeInFromBottom(mContentContainer); + mShrinkFadeOutFromBottomAnimation = + createShrinkFadeOutFromBottomAnimation(mContentContainer, mOnDismissEnd); + } + + /** + * Shows this popup at the specified coordinates. + * The specified coordinates may be adjusted to make sure the popup is entirely on-screen. + * If this popup is already showing, this will be a no-op. + */ + public void show(int x, int y) { + if (isShowing()) { + updateCoordinates(x, y); + return; + } + + mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, 0, 0); + positionOnScreen(x, y); + growFadeInFromBottom(); + + mDismissAnimating = false; + } + + /** + * Gets rid of this popup. If the popup isn't currently showing, this will be a no-op. + */ + public void dismiss() { + if (!isShowing()) { + return; + } + + if (mDismissAnimating) { + // This window is already dismissing. Don't restart the animation. + return; + } + mDismissAnimating = true; + shrinkFadeOutFromBottom(); + } + + /** + * Returns {@code true} if this popup is currently showing. {@code false} otherwise. + */ + public boolean isShowing() { + return mPopupWindow.isShowing() && !mDismissAnimating; + } + + /** + * Updates the coordinates of this popup. + * The specified coordinates may be adjusted to make sure the popup is entirely on-screen. + */ + public void updateCoordinates(int x, int y) { + if (isShowing()) { + positionOnScreen(x, y); + } + } + + /** + * Sets the content of this popup. + */ + public void setContentView(View view) { + Preconditions.checkNotNull(view); + mContentContainer.removeAllViews(); + mContentContainer.addView(view); + } + + /** + * Returns the width of this popup. + */ + public int getWidth() { + return mContentContainer.getWidth(); + } + + /** + * Returns the height of this popup. + */ + public int getHeight() { + return mContentContainer.getHeight(); + } + + /** + * Returns the context this popup is running in. + */ + public Context getContext() { + return mContentContainer.getContext(); + } + + private void positionOnScreen(int x, int y) { + if (getWidth() == 0) { + // content size is yet to be measured. + mContentContainer.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); + } + x = clamp(x, 0, getScreenWidth(getContext()) - getWidth()); + y = clamp(y, 0, getScreenHeight(getContext()) - getHeight()); + + // Position the view w.r.t. the window. + mContentContainer.setX(x); + mContentContainer.setY(y); + } + + /** + * Performs the "grow and fade in from the bottom" animation on the floating popup. + */ + private void growFadeInFromBottom() { + setPivot(); + mGrowFadeInFromBottomAnimation.start(); + } + + /** + * Performs the "shrink and fade out from bottom" animation on the floating popup. + */ + private void shrinkFadeOutFromBottom() { + setPivot(); + mShrinkFadeOutFromBottomAnimation.start(); + } + + /** + * Sets the popup content container's pivot. + */ + private void setPivot() { + mContentContainer.setPivotX(mContentContainer.getMeasuredWidth() / 2); + mContentContainer.setPivotY(mContentContainer.getMeasuredHeight()); + } + + private static ViewGroup createContentContainer(Context context) { + return (ViewGroup) LayoutInflater.from(context) + .inflate(R.layout.floating_popup_container, null); + } + + private static PopupWindow createPopupWindow(View content) { + ViewGroup popupContentHolder = new LinearLayout(content.getContext()); + PopupWindow popupWindow = new PopupWindow(popupContentHolder); + popupWindow.setAnimationStyle(0); + popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + popupWindow.setWidth(getScreenWidth(content.getContext())); + popupWindow.setHeight(getScreenHeight(content.getContext())); + content.setLayoutParams(new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + popupContentHolder.addView(content); + return popupWindow; + } + + /** + * Creates a "grow and fade in from the bottom" animation for the specified view. + * + * @param view The view to animate + */ + private static AnimatorSet createGrowFadeInFromBottom(View view) { + AnimatorSet growFadeInFromBottomAnimation = new AnimatorSet(); + growFadeInFromBottomAnimation.playTogether( + ObjectAnimator.ofFloat(view, View.SCALE_X, 0.5f, 1).setDuration(125), + ObjectAnimator.ofFloat(view, View.SCALE_Y, 0.5f, 1).setDuration(125), + ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1).setDuration(75)); + return growFadeInFromBottomAnimation; + } + + /** + * Creates a "shrink and fade out from bottom" animation for the specified view. + * + * @param view The view to animate + * @param listener The animation listener + */ + private static AnimatorSet createShrinkFadeOutFromBottomAnimation( + View view, Animator.AnimatorListener listener) { + AnimatorSet shrinkFadeOutFromBottomAnimation = new AnimatorSet(); + shrinkFadeOutFromBottomAnimation.playTogether( + ObjectAnimator.ofFloat(view, View.SCALE_Y, 1, 0.5f).setDuration(125), + ObjectAnimator.ofFloat(view, View.ALPHA, 1, 0).setDuration(75)); + shrinkFadeOutFromBottomAnimation.setStartDelay(150); + shrinkFadeOutFromBottomAnimation.addListener(listener); + return shrinkFadeOutFromBottomAnimation; + } + + /** + * Returns value, restricted to the range min->max (inclusive). + * If maximum is less than minimum, the result is undefined. + * + * @param value The value to clamp. + * @param minimum The minimum value in the range. + * @param maximum The maximum value in the range. Must not be less than minimum. + */ + private static int clamp(int value, int minimum, int maximum) { + return Math.max(minimum, Math.min(value, maximum)); + } + } +} diff --git a/core/jni/android/graphics/MinikinUtils.cpp b/core/jni/android/graphics/MinikinUtils.cpp index 8139c24..8bdbff4 100644 --- a/core/jni/android/graphics/MinikinUtils.cpp +++ b/core/jni/android/graphics/MinikinUtils.cpp @@ -26,10 +26,10 @@ namespace android { -void MinikinUtils::doLayout(Layout* layout, const Paint* paint, int bidiFlags, TypefaceImpl* typeface, - const uint16_t* buf, size_t start, size_t count, size_t bufSize) { - TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(typeface); - layout->setFontCollection(resolvedFace->fFontCollection); +FontStyle MinikinUtils::prepareMinikinPaint(MinikinPaint* minikinPaint, FontCollection** pFont, + const Paint* paint, TypefaceImpl* typeface) { + const TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(typeface); + *pFont = resolvedFace->fFontCollection; FontStyle resolved = resolvedFace->fStyle; /* Prepare minikin FontStyle */ @@ -40,15 +40,26 @@ void MinikinUtils::doLayout(Layout* layout, const Paint* paint, int bidiFlags, T FontStyle minikinStyle(minikinLang, minikinVariant, resolved.getWeight(), resolved.getItalic()); /* Prepare minikin Paint */ - MinikinPaint minikinPaint; - minikinPaint.size = (int)/*WHY?!*/paint->getTextSize(); - minikinPaint.scaleX = paint->getTextScaleX(); - minikinPaint.skewX = paint->getTextSkewX(); - minikinPaint.letterSpacing = paint->getLetterSpacing(); - minikinPaint.paintFlags = MinikinFontSkia::packPaintFlags(paint); - minikinPaint.fontFeatureSettings = paint->getFontFeatureSettings(); - minikinPaint.hyphenEdit = HyphenEdit(paint->getHyphenEdit()); + // Note: it would be nice to handle fractional size values (it would improve smooth zoom + // behavior), but historically size has been treated as an int. + // TODO: explore whether to enable fractional sizes, possibly when linear text flag is set. + minikinPaint->size = (int)paint->getTextSize(); + minikinPaint->scaleX = paint->getTextScaleX(); + minikinPaint->skewX = paint->getTextSkewX(); + minikinPaint->letterSpacing = paint->getLetterSpacing(); + minikinPaint->paintFlags = MinikinFontSkia::packPaintFlags(paint); + minikinPaint->fontFeatureSettings = paint->getFontFeatureSettings(); + minikinPaint->hyphenEdit = HyphenEdit(paint->getHyphenEdit()); + return minikinStyle; +} +void MinikinUtils::doLayout(Layout* layout, const Paint* paint, int bidiFlags, + TypefaceImpl* typeface, const uint16_t* buf, size_t start, size_t count, + size_t bufSize) { + FontCollection *font; + MinikinPaint minikinPaint; + FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, &font, paint, typeface); + layout->setFontCollection(font); layout->doLayout(buf, start, count, bufSize, bidiFlags, minikinStyle, minikinPaint); } diff --git a/core/jni/android/graphics/MinikinUtils.h b/core/jni/android/graphics/MinikinUtils.h index 236f1fd..1ee6245 100644 --- a/core/jni/android/graphics/MinikinUtils.h +++ b/core/jni/android/graphics/MinikinUtils.h @@ -31,22 +31,14 @@ namespace android { -// TODO: these should be defined in Minikin's Layout.h -enum { - kBidi_LTR = 0, - kBidi_RTL = 1, - kBidi_Default_LTR = 2, - kBidi_Default_RTL = 3, - kBidi_Force_LTR = 4, - kBidi_Force_RTL = 5, - - kBidi_Mask = 0x7 -}; - class MinikinUtils { public: - static void doLayout(Layout* layout, const Paint* paint, int bidiFlags, TypefaceImpl* typeface, - const uint16_t* buf, size_t start, size_t count, size_t bufSize); + static FontStyle prepareMinikinPaint(MinikinPaint* minikinPaint, FontCollection** pFont, + const Paint* paint, TypefaceImpl* typeface); + + static void doLayout(Layout* layout, const Paint* paint, int bidiFlags, + TypefaceImpl* typeface, const uint16_t* buf, size_t start, size_t count, + size_t bufSize); static float xOffsetForTextAlign(Paint* paint, const Layout& layout); diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp index f0131b4..4b43de3 100644 --- a/core/jni/android/graphics/Paint.cpp +++ b/core/jni/android/graphics/Paint.cpp @@ -101,6 +101,16 @@ public: } static jlong init(JNIEnv* env, jobject clazz) { + SK_COMPILE_ASSERT(1 << 0 == SkPaint::kAntiAlias_Flag, paint_flags_mismatch); + SK_COMPILE_ASSERT(1 << 2 == SkPaint::kDither_Flag, paint_flags_mismatch); + SK_COMPILE_ASSERT(1 << 3 == SkPaint::kUnderlineText_Flag, paint_flags_mismatch); + SK_COMPILE_ASSERT(1 << 4 == SkPaint::kStrikeThruText_Flag, paint_flags_mismatch); + SK_COMPILE_ASSERT(1 << 5 == SkPaint::kFakeBoldText_Flag, paint_flags_mismatch); + SK_COMPILE_ASSERT(1 << 6 == SkPaint::kLinearText_Flag, paint_flags_mismatch); + SK_COMPILE_ASSERT(1 << 7 == SkPaint::kSubpixelText_Flag, paint_flags_mismatch); + SK_COMPILE_ASSERT(1 << 8 == SkPaint::kDevKernText_Flag, paint_flags_mismatch); + SK_COMPILE_ASSERT(1 << 10 == SkPaint::kEmbeddedBitmapText_Flag, paint_flags_mismatch); + Paint* obj = new Paint(); defaultSettingsForAndroid(obj); return reinterpret_cast<jlong>(obj); diff --git a/core/jni/android/graphics/TypefaceImpl.h b/core/jni/android/graphics/TypefaceImpl.h index d36f83a..4b14917 100644 --- a/core/jni/android/graphics/TypefaceImpl.h +++ b/core/jni/android/graphics/TypefaceImpl.h @@ -62,4 +62,4 @@ void TypefaceImpl_setDefault(TypefaceImpl* face); } -#endif // _ANDROID_GRAPHICS_TYPEFACE_IMPL_H_
\ No newline at end of file +#endif // _ANDROID_GRAPHICS_TYPEFACE_IMPL_H_ diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp index 0b737a7..7d12230 100644 --- a/core/jni/android_hardware_SensorManager.cpp +++ b/core/jni/android_hardware_SensorManager.cpp @@ -18,6 +18,8 @@ #include <map> +#include <ScopedUtfChars.h> + #include <utils/Log.h> #include <utils/Looper.h> @@ -99,6 +101,9 @@ public: if (string1 == NULL) { return string2 != NULL; } + if (string2 == NULL) { + return false; + } return string1->compare(*string2) < 0; } }; @@ -264,9 +269,12 @@ private: } }; -static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject eventQ, jobject msgQ, jfloatArray scratch) { +static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject eventQ, jobject msgQ, + jfloatArray scratch, jstring packageName) { SensorManager& mgr(SensorManager::getInstance()); - sp<SensorEventQueue> queue(mgr.createEventQueue()); + ScopedUtfChars packageUtf(env, packageName); + String8 clientName(packageUtf.c_str()); + sp<SensorEventQueue> queue(mgr.createEventQueue(clientName)); sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ); if (messageQueue == NULL) { @@ -280,10 +288,11 @@ static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject event } static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle, jint rate_us, - jint maxBatchReportLatency, jint reservedFlags) { + jint maxBatchReportLatency) { sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ)); + return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency, - reservedFlags); + 0); } static jint nativeDisableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle) { @@ -316,11 +325,11 @@ static JNINativeMethod gSystemSensorManagerMethods[] = { static JNINativeMethod gBaseEventQueueMethods[] = { {"nativeInitBaseEventQueue", - "(Landroid/hardware/SystemSensorManager$BaseEventQueue;Landroid/os/MessageQueue;[F)J", - (void*)nativeInitSensorEventQueue }, + "(Landroid/hardware/SystemSensorManager$BaseEventQueue;Landroid/os/MessageQueue;[FLjava/lang/String;)J", + (void*)nativeInitSensorEventQueue }, {"nativeEnableSensor", - "(JIIII)I", + "(JIII)I", (void*)nativeEnableSensor }, {"nativeDisableSensor", diff --git a/core/jni/android_server_FingerprintManager.cpp b/core/jni/android_server_FingerprintManager.cpp index 853425c..5d59234 100644 --- a/core/jni/android_server_FingerprintManager.cpp +++ b/core/jni/android_server_FingerprintManager.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "Fingerprint-JNI" #include "JNIHelp.h" +#include <inttypes.h> #include <android_runtime/AndroidRuntime.h> #include <android_runtime/Log.h> @@ -47,14 +48,15 @@ static jobject gCallback; class CallbackHandler : public MessageHandler { int type; - int arg1, arg2; + int arg1, arg2, arg3; public: - CallbackHandler(int type, int arg1, int arg2) : type(type), arg1(arg1), arg2(arg2) { } + CallbackHandler(int type, int arg1, int arg2, int arg3) + : type(type), arg1(arg1), arg2(arg2), arg3(arg3) { } virtual void handleMessage(const Message& message) { //ALOG(LOG_VERBOSE, LOG_TAG, "hal_notify(msg=%d, arg1=%d, arg2=%d)\n", msg.type, arg1, arg2); JNIEnv* env = AndroidRuntime::getJNIEnv(); - env->CallVoidMethod(gCallback, gFingerprintServiceClassInfo.notify, type, arg1, arg2); + env->CallVoidMethod(gCallback, gFingerprintServiceClassInfo.notify, type, arg1, arg2, arg3); } }; @@ -62,6 +64,7 @@ public: static void hal_notify_callback(fingerprint_msg_t msg) { uint32_t arg1 = 0; uint32_t arg2 = 0; + uint32_t arg3 = 0; switch (msg.type) { case FINGERPRINT_ERROR: arg1 = msg.data.error; @@ -71,13 +74,16 @@ static void hal_notify_callback(fingerprint_msg_t msg) { break; case FINGERPRINT_PROCESSED: arg1 = msg.data.processed.finger.fid; + arg2 = msg.data.processed.finger.gid; break; case FINGERPRINT_TEMPLATE_ENROLLING: arg1 = msg.data.enroll.finger.fid; - arg2 = msg.data.enroll.samples_remaining; + arg2 = msg.data.enroll.finger.gid; + arg3 = msg.data.enroll.samples_remaining; break; case FINGERPRINT_TEMPLATE_REMOVED: arg1 = msg.data.removed.finger.fid; + arg2 = msg.data.removed.finger.gid; break; default: ALOGE("fingerprint: invalid msg: %d", msg.type); @@ -86,7 +92,7 @@ static void hal_notify_callback(fingerprint_msg_t msg) { // This call potentially comes in on a thread not owned by us. Hand it off to our // looper so it runs on our thread when calling back to FingerprintService. // CallbackHandler object is reference-counted, so no cleanup necessary. - gLooper->sendMessage(new CallbackHandler(msg.type, arg1, arg2), Message()); + gLooper->sendMessage(new CallbackHandler(msg.type, arg1, arg2, arg3), Message()); } static void nativeInit(JNIEnv *env, jobject clazz, jobject mQueue, jobject callbackObj) { @@ -95,9 +101,15 @@ static void nativeInit(JNIEnv *env, jobject clazz, jobject mQueue, jobject callb gLooper = android_os_MessageQueue_getMessageQueue(env, mQueue)->getLooper(); } -static jint nativeEnroll(JNIEnv* env, jobject clazz, jint timeout) { - ALOG(LOG_VERBOSE, LOG_TAG, "nativeEnroll()\n"); - int ret = gContext.device->enroll(gContext.device, 0, timeout); +static jint nativeEnroll(JNIEnv* env, jobject clazz, jint timeout, jint groupId) { + ALOG(LOG_VERBOSE, LOG_TAG, "nativeEnroll(gid=%d, timeout=%d)\n", groupId, timeout); + int ret = gContext.device->enroll(gContext.device, groupId, timeout); + return reinterpret_cast<jint>(ret); +} + +static jint nativeAuthenticate(JNIEnv* env, jobject clazz, jlong sessionId, jint groupId) { + ALOG(LOG_VERBOSE, LOG_TAG, "nativeAuthenticate(sid=%" PRId64 ", gid=%d)\n", sessionId, groupId); + int ret = gContext.device->authenticate(gContext.device, sessionId, groupId); return reinterpret_cast<jint>(ret); } @@ -107,11 +119,11 @@ static jint nativeEnrollCancel(JNIEnv* env, jobject clazz) { return reinterpret_cast<jint>(ret); } -static jint nativeRemove(JNIEnv* env, jobject clazz, jint fingerprintId) { - ALOG(LOG_VERBOSE, LOG_TAG, "nativeRemove(%d)\n", fingerprintId); +static jint nativeRemove(JNIEnv* env, jobject clazz, jint fingerId, jint groupId) { + ALOG(LOG_VERBOSE, LOG_TAG, "nativeRemove(fid=%d, gid=%d)\n", fingerId, groupId); fingerprint_finger_id_t finger; - finger.gid = 0; - finger.fid = fingerprintId; + finger.fid = fingerId; + finger.gid = groupId; int ret = gContext.device->remove(gContext.device, finger); return reinterpret_cast<jint>(ret); } @@ -172,9 +184,10 @@ static jint nativeCloseHal(JNIEnv* env, jobject clazz) { // TODO: clean up void methods static const JNINativeMethod g_methods[] = { - { "nativeEnroll", "(I)I", (void*)nativeEnroll }, + { "nativeAuthenticate", "(JI)I", (void*)nativeAuthenticate }, + { "nativeEnroll", "(II)I", (void*)nativeEnroll }, { "nativeEnrollCancel", "()I", (void*)nativeEnrollCancel }, - { "nativeRemove", "(I)I", (void*)nativeRemove }, + { "nativeRemove", "(II)I", (void*)nativeRemove }, { "nativeOpenHal", "()I", (void*)nativeOpenHal }, { "nativeCloseHal", "()I", (void*)nativeCloseHal }, { "nativeInit","(Landroid/os/MessageQueue;" @@ -185,7 +198,7 @@ int register_android_server_fingerprint_FingerprintService(JNIEnv* env) { jclass clazz = FindClassOrDie(env, FINGERPRINT_SERVICE); gFingerprintServiceClassInfo.clazz = MakeGlobalRefOrDie(env, clazz); gFingerprintServiceClassInfo.notify = - GetMethodIDOrDie(env, gFingerprintServiceClassInfo.clazz,"notify", "(III)V"); + GetMethodIDOrDie(env, gFingerprintServiceClassInfo.clazz,"notify", "(IIII)V"); int result = RegisterMethodsOrDie(env, FINGERPRINT_SERVICE, g_methods, NELEM(g_methods)); ALOG(LOG_VERBOSE, LOG_TAG, "FingerprintManager JNI ready.\n"); return result; diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp index 8800f0b..6cc1f68 100644 --- a/core/jni/android_text_StaticLayout.cpp +++ b/core/jni/android_text_StaticLayout.cpp @@ -34,6 +34,7 @@ #include "MinikinSkia.h" #include "MinikinUtils.h" #include "Paint.h" +#include "minikin/LineBreaker.h" namespace android { @@ -46,636 +47,116 @@ struct JLineBreaksID { static jclass gLineBreaks_class; static JLineBreaksID gLineBreaks_fieldID; -class Builder { - public: - ~Builder() { - utext_close(&mUText); - delete mBreakIterator; - } - - void setLocale(const icu::Locale& locale) { - delete mBreakIterator; - UErrorCode status = U_ZERO_ERROR; - mBreakIterator = icu::BreakIterator::createLineInstance(locale, status); - // TODO: check status - } - - void resize(size_t size) { - mTextBuf.resize(size); - mWidthBuf.resize(size); - } - - size_t size() const { - return mTextBuf.size(); - } - - uint16_t* buffer() { - return mTextBuf.data(); - } - - float* widths() { - return mWidthBuf.data(); - } - - // set text to current contents of buffer - void setText() { - UErrorCode status = U_ZERO_ERROR; - utext_openUChars(&mUText, mTextBuf.data(), mTextBuf.size(), &status); - mBreakIterator->setText(&mUText, status); - } - - void finish() { - if (mTextBuf.size() > MAX_TEXT_BUF_RETAIN) { - mTextBuf.clear(); - mTextBuf.shrink_to_fit(); - mWidthBuf.clear(); - mWidthBuf.shrink_to_fit(); - } - } - - icu::BreakIterator* breakIterator() const { - return mBreakIterator; - } - - float measureStyleRun(Paint* paint, TypefaceImpl* typeface, size_t start, size_t end, - bool isRtl); - - void addReplacement(size_t start, size_t end, float width); - - private: - const size_t MAX_TEXT_BUF_RETAIN = 32678; - icu::BreakIterator* mBreakIterator = nullptr; - UText mUText = UTEXT_INITIALIZER; - std::vector<uint16_t>mTextBuf; - std::vector<float>mWidthBuf; -}; - static const int CHAR_SPACE = 0x20; static const int CHAR_TAB = 0x09; static const int CHAR_NEWLINE = 0x0a; static const int CHAR_ZWSP = 0x200b; -class TabStops { - public: - // specified stops must be a sorted array (allowed to be null) - TabStops(JNIEnv* env, jintArray stops, jint defaultTabWidth) : - mStops(env), mTabWidth(defaultTabWidth) { - if (stops != nullptr) { - mStops.reset(stops); - mNumStops = mStops.size(); - } else { - mNumStops = 0; - } - } - float width(float widthSoFar) const { - const jint* mStopsArray = mStops.get(); - for (int i = 0; i < mNumStops; i++) { - if (mStopsArray[i] > widthSoFar) { - return mStopsArray[i]; - } - } - // find the next tabstop after widthSoFar - return static_cast<int>((widthSoFar + mTabWidth) / mTabWidth) * mTabWidth; - } - private: - ScopedIntArrayRO mStops; - const int mTabWidth; - int mNumStops; - - // disable copying and assignment - TabStops(const TabStops&); - void operator=(const TabStops&); -}; - -enum PrimitiveType { - kPrimitiveType_Box, - kPrimitiveType_Glue, - kPrimitiveType_Penalty, - kPrimitiveType_Variable, - kPrimitiveType_Wordbreak -}; - -static const float PENALTY_INFINITY = 1e7; // forced non-break, negative infinity is forced break - -struct Primitive { - PrimitiveType type; - int location; - // 'Box' has width - // 'Glue' has width - // 'Penalty' has width and penalty - // 'Variable' has tabStop - // 'Wordbreak' has penalty - union { - struct { - float width; - float penalty; - }; - const TabStops* tabStop; - }; -}; - -class LineWidth { - public: - LineWidth(float firstWidth, int firstWidthLineCount, float restWidth) : - mFirstWidth(firstWidth), mFirstWidthLineCount(firstWidthLineCount), - mRestWidth(restWidth) {} - float getLineWidth(int line) const { - return (line < mFirstWidthLineCount) ? mFirstWidth : mRestWidth; - } - private: - const float mFirstWidth; - const int mFirstWidthLineCount; - const float mRestWidth; -}; - -class LineBreaker { - public: - LineBreaker(const std::vector<Primitive>& primitives, - const LineWidth& lineWidth) : - mPrimitives(primitives), mLineWidth(lineWidth) {} - virtual ~LineBreaker() {} - virtual void computeBreaks(std::vector<int>* breaks, std::vector<float>* widths, - std::vector<unsigned char>* flags) const = 0; - protected: - const std::vector<Primitive>& mPrimitives; - const LineWidth& mLineWidth; -}; - -class OptimizingLineBreaker : public LineBreaker { - public: - OptimizingLineBreaker(const std::vector<Primitive>& primitives, const LineWidth& lineWidth) : - LineBreaker(primitives, lineWidth) {} - void computeBreaks(std::vector<int>* breaks, std::vector<float>* widths, - std::vector<unsigned char>* flags) const { - int numBreaks = mPrimitives.size(); - Node* opt = new Node[numBreaks]; - opt[0].prev = -1; - opt[0].prevCount = 0; - opt[0].width = 0; - opt[0].demerits = 0; - opt[0].flags = false; - opt[numBreaks - 1].prev = -1; - opt[numBreaks - 1].prevCount = 0; - - std::list<int> active; - active.push_back(0); - int lastBreak = 0; - for (int i = 0; i < numBreaks; i++) { - const Primitive& p = mPrimitives[i]; - if (p.type == kPrimitiveType_Penalty) { - const bool finalBreak = (i + 1 == numBreaks); - bool breakFound = false; - Node bestBreak; - for (std::list<int>::iterator it = active.begin(); it != active.end(); /* incrementing done in loop */) { - const int pos = *it; - bool flags; - float width, printedWidth; - const int lines = opt[pos].prevCount; - const float maxWidth = mLineWidth.getLineWidth(lines); - // we have to compute metrics every time -- - // we can't really precompute this stuff and just deal with breaks - // because of the way tab characters work, this makes it computationally - // harder, but this way, we can still optimize while treating tab characters - // correctly - computeMetrics(pos, i, &width, &printedWidth, &flags); - if (printedWidth <= maxWidth) { - float demerits = computeDemerits(maxWidth, printedWidth, - finalBreak, p.penalty) + opt[pos].demerits; - if (!breakFound || demerits < bestBreak.demerits) { - bestBreak.prev = pos; - bestBreak.prevCount = opt[pos].prevCount + 1; - bestBreak.demerits = demerits; - bestBreak.width = printedWidth; - bestBreak.flags = flags; - breakFound = true; - } - ++it; - } else { - active.erase(it++); // safe to delete like this - } - } - if (p.penalty == -PENALTY_INFINITY) { - active.clear(); - } - if (breakFound) { - opt[i] = bestBreak; - active.push_back(i); - lastBreak = i; - } - if (active.empty()) { - // we can't give up! - float width, printedWidth; - bool flags; - const int lines = opt[lastBreak].prevCount; - const float maxWidth = mLineWidth.getLineWidth(lines); - const int breakIndex = desperateBreak(lastBreak, numBreaks, maxWidth, &width, &printedWidth, &flags); - - opt[breakIndex].prev = lastBreak; - opt[breakIndex].prevCount = lines + 1; - opt[breakIndex].demerits = 0; // doesn't matter, it's the only one - opt[breakIndex].width = width; - opt[breakIndex].flags = flags; - - active.push_back(breakIndex); - lastBreak = breakIndex; - i = breakIndex; // incremented by i++ - } - } - } - - int idx = numBreaks - 1; - int count = opt[idx].prevCount; - breaks->resize(count); - widths->resize(count); - flags->resize(count); - while (opt[idx].prev != -1) { - --count; - - (*breaks)[count] = mPrimitives[idx].location; - (*widths)[count] = opt[idx].width; - (*flags)[count] = opt[idx].flags; - - idx = opt[idx].prev; - } - delete[] opt; - } - private: - inline void computeMetrics(int start, int end, float* width, float* printedWidth, bool* flags) const { - bool f = false; - float w = 0, pw = 0; - for (int i = start; i < end; i++) { - const Primitive& p = mPrimitives[i]; - if (p.type == kPrimitiveType_Box || p.type == kPrimitiveType_Glue) { - w += p.width; - if (p.type == kPrimitiveType_Box) { - pw = w; - } - } else if (p.type == kPrimitiveType_Variable) { - w = p.tabStop->width(w); - f = true; - } - } - *width = w; - *printedWidth = pw; - *flags = f; - } - - inline float computeDemerits(float maxWidth, float width, bool finalBreak, float penalty) const { - float deviation = finalBreak ? 0 : maxWidth - width; - return (deviation * deviation) + penalty; - } - - // returns end pos (chosen break), -1 if fail - inline int desperateBreak(int start, int limit, float maxWidth, float* width, float* printedWidth, bool* flags) const { - float w = 0, pw = 0; - bool breakFound = false; - int breakIndex = 0, firstTabIndex = INT_MAX; - for (int i = start; i < limit; i++) { - const Primitive& p = mPrimitives[i]; - - if (p.type == kPrimitiveType_Box || p.type == kPrimitiveType_Glue) { - w += p.width; - if (p.type == kPrimitiveType_Box) { - pw = w; - } - } else if (p.type == kPrimitiveType_Variable) { - w = p.tabStop->width(w); - firstTabIndex = std::min(firstTabIndex, i); - } - - if (pw > maxWidth) { - if (breakFound) { - break; - } else { - // no choice, keep going - } - } - - // must make progress - if (i > start && (p.type == kPrimitiveType_Penalty || p.type == kPrimitiveType_Wordbreak)) { - breakFound = true; - breakIndex = i; - } - } - - if (breakFound) { - *width = w; - *printedWidth = pw; - *flags = (start <= firstTabIndex && firstTabIndex < breakIndex); - return breakIndex; - } else { - return -1; - } - } - - struct Node { - int prev; // set to sentinel value (-1) for initial node - int prevCount; // number of breaks so far - float demerits; - float width; - bool flags; - }; -}; - -class GreedyLineBreaker : public LineBreaker { - public: - GreedyLineBreaker(const std::vector<Primitive>& primitives, const LineWidth& lineWidth) : - LineBreaker(primitives, lineWidth) {} - void computeBreaks(std::vector<int>* breaks, std::vector<float>* widths, - std::vector<unsigned char>* flags) const { - int lineNum = 0; - float width = 0, printedWidth = 0; - bool breakFound = false, goodBreakFound = false; - int breakIndex = 0, goodBreakIndex = 0; - float breakWidth = 0, goodBreakWidth = 0; - int firstTabIndex = INT_MAX; - - float maxWidth = mLineWidth.getLineWidth(lineNum); - - const int numPrimitives = mPrimitives.size(); - // greedily fit as many characters as possible on each line - // loop over all primitives, and choose the best break point - // (if possible, a break point without splitting a word) - // after going over the maximum length - for (int i = 0; i < numPrimitives; i++) { - const Primitive& p = mPrimitives[i]; - - // update the current line width - if (p.type == kPrimitiveType_Box || p.type == kPrimitiveType_Glue) { - width += p.width; - if (p.type == kPrimitiveType_Box) { - printedWidth = width; - } - } else if (p.type == kPrimitiveType_Variable) { - width = p.tabStop->width(width); - // keep track of first tab character in the region we are examining - // so we can determine whether or not a line contains a tab - firstTabIndex = std::min(firstTabIndex, i); - } - - // find the best break point for the characters examined so far - if (printedWidth > maxWidth) { - if (breakFound || goodBreakFound) { - if (goodBreakFound) { - // a true line break opportunity existed in the characters examined so far, - // so there is no need to split a word - i = goodBreakIndex; // no +1 because of i++ - lineNum++; - maxWidth = mLineWidth.getLineWidth(lineNum); - breaks->push_back(mPrimitives[goodBreakIndex].location); - widths->push_back(goodBreakWidth); - flags->push_back(firstTabIndex < goodBreakIndex); - firstTabIndex = INT_MAX; - } else { - // must split a word because there is no other option - i = breakIndex; // no +1 because of i++ - lineNum++; - maxWidth = mLineWidth.getLineWidth(lineNum); - breaks->push_back(mPrimitives[breakIndex].location); - widths->push_back(breakWidth); - flags->push_back(firstTabIndex < breakIndex); - firstTabIndex = INT_MAX; - } - printedWidth = width = 0; - goodBreakFound = breakFound = false; - goodBreakWidth = breakWidth = 0; - continue; - } else { - // no choice, keep going... must make progress by putting at least one - // character on a line, even if part of that character is cut off -- - // there is no other option - } - } - - // update possible break points - if (p.type == kPrimitiveType_Penalty && p.penalty < PENALTY_INFINITY) { - // this does not handle penalties with width - - // handle forced line break - if (p.penalty == -PENALTY_INFINITY) { - lineNum++; - maxWidth = mLineWidth.getLineWidth(lineNum); - breaks->push_back(p.location); - widths->push_back(printedWidth); - flags->push_back(firstTabIndex < i); - firstTabIndex = INT_MAX; - printedWidth = width = 0; - goodBreakFound = breakFound = false; - goodBreakWidth = breakWidth = 0; - continue; - } - if (i > breakIndex && (printedWidth <= maxWidth || breakFound == false)) { - breakFound = true; - breakIndex = i; - breakWidth = printedWidth; - } - if (i > goodBreakIndex && printedWidth <= maxWidth) { - goodBreakFound = true; - goodBreakIndex = i; - goodBreakWidth = printedWidth; - } - } else if (p.type == kPrimitiveType_Wordbreak) { - // only do this if necessary -- we don't want to break words - // when possible, but sometimes it is unavoidable - if (i > breakIndex && (printedWidth <= maxWidth || breakFound == false)) { - breakFound = true; - breakIndex = i; - breakWidth = printedWidth; - } - } - } - - if (breakFound || goodBreakFound) { - // output last break if there are more characters to output - if (goodBreakFound) { - breaks->push_back(mPrimitives[goodBreakIndex].location); - widths->push_back(goodBreakWidth); - flags->push_back(firstTabIndex < goodBreakIndex); - } else { - breaks->push_back(mPrimitives[breakIndex].location); - widths->push_back(breakWidth); - flags->push_back(firstTabIndex < breakIndex); - } - } - } -}; +// set text and set a number of parameters for creating a layout (width, tabstops, strategy) +static void nSetupParagraph(JNIEnv* env, jclass, jlong nativePtr, jcharArray text, jint length, + jfloat firstWidth, jint firstWidthLineLimit, jfloat restWidth, + jintArray variableTabStops, jint defaultTabStop, jint strategy) { + LineBreaker* b = reinterpret_cast<LineBreaker*>(nativePtr); + b->resize(length); + env->GetCharArrayRegion(text, 0, length, b->buffer()); + b->setText(); + b->setLineWidths(firstWidth, firstWidthLineLimit, restWidth); + if (variableTabStops == nullptr) { + b->setTabStops(nullptr, 0, defaultTabStop); + } else { + ScopedIntArrayRO stops(env, variableTabStops); + b->setTabStops(stops.get(), stops.size(), defaultTabStop); + } + b->setStrategy(static_cast<BreakStrategy>(strategy)); +} -static jint recycleCopy(JNIEnv* env, jobject recycle, jintArray recycleBreaks, +static void recycleCopy(JNIEnv* env, jobject recycle, jintArray recycleBreaks, jfloatArray recycleWidths, jbooleanArray recycleFlags, - jint recycleLength, const std::vector<jint>& breaks, - const std::vector<jfloat>& widths, const std::vector<jboolean>& flags) { - int bufferLength = breaks.size(); - if (recycleLength < bufferLength) { + jint recycleLength, size_t nBreaks, const jint* breaks, + const jfloat* widths, const jboolean* flags) { + if ((size_t)recycleLength < nBreaks) { // have to reallocate buffers - recycleBreaks = env->NewIntArray(bufferLength); - recycleWidths = env->NewFloatArray(bufferLength); - recycleFlags = env->NewBooleanArray(bufferLength); + recycleBreaks = env->NewIntArray(nBreaks); + recycleWidths = env->NewFloatArray(nBreaks); + recycleFlags = env->NewBooleanArray(nBreaks); env->SetObjectField(recycle, gLineBreaks_fieldID.breaks, recycleBreaks); env->SetObjectField(recycle, gLineBreaks_fieldID.widths, recycleWidths); env->SetObjectField(recycle, gLineBreaks_fieldID.flags, recycleFlags); } // copy data - env->SetIntArrayRegion(recycleBreaks, 0, breaks.size(), &breaks.front()); - env->SetFloatArrayRegion(recycleWidths, 0, widths.size(), &widths.front()); - env->SetBooleanArrayRegion(recycleFlags, 0, flags.size(), &flags.front()); - - return bufferLength; -} - -void computePrimitives(const jchar* textArr, const jfloat* widthsArr, jint length, const std::vector<int>& breaks, - const TabStops& tabStopCalculator, std::vector<Primitive>* primitives) { - int breaksSize = breaks.size(); - int breakIndex = 0; - Primitive p; - for (int i = 0; i < length; i++) { - p.location = i; - jchar c = textArr[i]; - if (c == CHAR_SPACE || c == CHAR_ZWSP) { - p.type = kPrimitiveType_Glue; - p.width = widthsArr[i]; - primitives->push_back(p); - } else if (c == CHAR_TAB) { - p.type = kPrimitiveType_Variable; - p.tabStop = &tabStopCalculator; // shared between all variable primitives - primitives->push_back(p); - } else if (c != CHAR_NEWLINE) { - while (breakIndex < breaksSize && breaks[breakIndex] < i) breakIndex++; - p.width = 0; - if (breakIndex < breaksSize && breaks[breakIndex] == i) { - p.type = kPrimitiveType_Penalty; - p.penalty = 0; - } else { - p.type = kPrimitiveType_Wordbreak; - } - if (widthsArr[i] != 0) { - primitives->push_back(p); - } - - p.type = kPrimitiveType_Box; - p.width = widthsArr[i]; - primitives->push_back(p); - } - } - // final break at end of everything - p.location = length; - p.type = kPrimitiveType_Penalty; - p.width = 0; - p.penalty = -PENALTY_INFINITY; - primitives->push_back(p); -} - -// sets the text on the builder -static void nSetText(JNIEnv* env, jclass, jlong nativePtr, jcharArray text, int length) { - Builder* b = reinterpret_cast<Builder*>(nativePtr); - b->resize(length); - env->GetCharArrayRegion(text, 0, length, b->buffer()); - b->setText(); + env->SetIntArrayRegion(recycleBreaks, 0, nBreaks, breaks); + env->SetFloatArrayRegion(recycleWidths, 0, nBreaks, widths); + env->SetBooleanArrayRegion(recycleFlags, 0, nBreaks, flags); } static jint nComputeLineBreaks(JNIEnv* env, jclass, jlong nativePtr, - jint length, - jfloat firstWidth, jint firstWidthLineLimit, jfloat restWidth, - jintArray variableTabStops, jint defaultTabStop, jboolean optimize, jobject recycle, jintArray recycleBreaks, jfloatArray recycleWidths, jbooleanArray recycleFlags, jint recycleLength) { - Builder* b = reinterpret_cast<Builder*>(nativePtr); + LineBreaker* b = reinterpret_cast<LineBreaker*>(nativePtr); - std::vector<int> breaks; + size_t nBreaks = b->computeBreaks(); - icu::BreakIterator* breakIterator = b->breakIterator(); - int loc = breakIterator->first(); - while ((loc = breakIterator->next()) != icu::BreakIterator::DONE) { - breaks.push_back(loc); - } - - // TODO: all these allocations can be moved into the builder - std::vector<Primitive> primitives; - TabStops tabStops(env, variableTabStops, defaultTabStop); - computePrimitives(b->buffer(), b->widths(), length, breaks, tabStops, &primitives); - - LineWidth lineWidth(firstWidth, firstWidthLineLimit, restWidth); - std::vector<int> computedBreaks; - std::vector<float> computedWidths; - std::vector<unsigned char> computedFlags; + recycleCopy(env, recycle, recycleBreaks, recycleWidths, recycleFlags, recycleLength, + nBreaks, b->getBreaks(), b->getWidths(), b->getFlags()); - if (optimize) { - OptimizingLineBreaker breaker(primitives, lineWidth); - breaker.computeBreaks(&computedBreaks, &computedWidths, &computedFlags); - } else { - GreedyLineBreaker breaker(primitives, lineWidth); - breaker.computeBreaks(&computedBreaks, &computedWidths, &computedFlags); - } b->finish(); - return recycleCopy(env, recycle, recycleBreaks, recycleWidths, recycleFlags, recycleLength, - computedBreaks, computedWidths, computedFlags); + return static_cast<jint>(nBreaks); } static jlong nNewBuilder(JNIEnv*, jclass) { - return reinterpret_cast<jlong>(new Builder); + return reinterpret_cast<jlong>(new LineBreaker); } static void nFreeBuilder(JNIEnv*, jclass, jlong nativePtr) { - delete reinterpret_cast<Builder*>(nativePtr); + delete reinterpret_cast<LineBreaker*>(nativePtr); } static void nFinishBuilder(JNIEnv*, jclass, jlong nativePtr) { - Builder* b = reinterpret_cast<Builder*>(nativePtr); + LineBreaker* b = reinterpret_cast<LineBreaker*>(nativePtr); b->finish(); } static void nSetLocale(JNIEnv* env, jclass, jlong nativePtr, jstring javaLocaleName) { ScopedIcuLocale icuLocale(env, javaLocaleName); - Builder* b = reinterpret_cast<Builder*>(nativePtr); + LineBreaker* b = reinterpret_cast<LineBreaker*>(nativePtr); if (icuLocale.valid()) { b->setLocale(icuLocale.locale()); } } -float Builder::measureStyleRun(Paint* paint, TypefaceImpl* typeface, size_t start, size_t end, - bool isRtl) { - Layout layout; - int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR; - // TODO: should we provide more context? - MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, mTextBuf.data() + start, 0, - end - start, end - start); - layout.getAdvances(mWidthBuf.data() + start); - return layout.getAdvance(); -} - -void Builder::addReplacement(size_t start, size_t end, float width) { - mWidthBuf[start] = width; - std::fill(&mWidthBuf[start + 1], &mWidthBuf[end], 0.0f); -} - // Basically similar to Paint.getTextRunAdvances but with C++ interface static jfloat nAddStyleRun(JNIEnv* env, jclass, jlong nativePtr, jlong nativePaint, jlong nativeTypeface, jint start, jint end, jboolean isRtl) { - Builder* b = reinterpret_cast<Builder*>(nativePtr); + LineBreaker* b = reinterpret_cast<LineBreaker*>(nativePtr); Paint* paint = reinterpret_cast<Paint*>(nativePaint); TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(nativeTypeface); - return b->measureStyleRun(paint, typeface, start, end, isRtl); + FontCollection *font; + MinikinPaint minikinPaint; + FontStyle style = MinikinUtils::prepareMinikinPaint(&minikinPaint, &font, paint, typeface); + return b->addStyleRun(&minikinPaint, font, style, start, end, isRtl); } // Accept width measurements for the run, passed in from Java static void nAddMeasuredRun(JNIEnv* env, jclass, jlong nativePtr, jint start, jint end, jfloatArray widths) { - Builder* b = reinterpret_cast<Builder*>(nativePtr); - env->GetFloatArrayRegion(widths, start, end - start, b->widths() + start); + LineBreaker* b = reinterpret_cast<LineBreaker*>(nativePtr); + env->GetFloatArrayRegion(widths, start, end - start, b->charWidths() + start); + b->addStyleRun(nullptr, nullptr, FontStyle{}, start, end, false); } static void nAddReplacementRun(JNIEnv* env, jclass, jlong nativePtr, jint start, jint end, jfloat width) { - Builder* b = reinterpret_cast<Builder*>(nativePtr); + LineBreaker* b = reinterpret_cast<LineBreaker*>(nativePtr); b->addReplacement(start, end, width); } static void nGetWidths(JNIEnv* env, jclass, jlong nativePtr, jfloatArray widths) { - Builder* b = reinterpret_cast<Builder*>(nativePtr); - env->SetFloatArrayRegion(widths, 0, b->size(), b->widths()); + LineBreaker* b = reinterpret_cast<LineBreaker*>(nativePtr); + env->SetFloatArrayRegion(widths, 0, b->size(), b->charWidths()); } static JNINativeMethod gMethods[] = { @@ -684,12 +165,12 @@ static JNINativeMethod gMethods[] = { {"nFreeBuilder", "(J)V", (void*) nFreeBuilder}, {"nFinishBuilder", "(J)V", (void*) nFinishBuilder}, {"nSetLocale", "(JLjava/lang/String;)V", (void*) nSetLocale}, - {"nSetText", "(J[CI)V", (void*) nSetText}, + {"nSetupParagraph", "(J[CIFIF[III)V", (void*) nSetupParagraph}, {"nAddStyleRun", "(JJJIIZ)F", (void*) nAddStyleRun}, {"nAddMeasuredRun", "(JII[F)V", (void*) nAddMeasuredRun}, {"nAddReplacementRun", "(JIIF)V", (void*) nAddReplacementRun}, {"nGetWidths", "(J[F)V", (void*) nGetWidths}, - {"nComputeLineBreaks", "(JIFIF[IIZLandroid/text/StaticLayout$LineBreaks;[I[F[ZI)I", + {"nComputeLineBreaks", "(JLandroid/text/StaticLayout$LineBreaks;[I[F[ZI)I", (void*) nComputeLineBreaks} }; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 4d6b5f6..851c4bf 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -77,6 +77,8 @@ <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" /> <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGING" /> + <protected-broadcast android:name="android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED" /> + <protected-broadcast android:name="android.app.action.ENTER_CAR_MODE" /> <protected-broadcast android:name="android.app.action.EXIT_CAR_MODE" /> <protected-broadcast android:name="android.app.action.ENTER_DESK_MODE" /> @@ -2607,7 +2609,8 @@ android:protectionLevel="signature|system" /> <!-- @SystemApi Allows an application to collect component usage - statistics @hide --> + statistics + <p>Not for use by third-party applications. --> <permission android:name="android.permission.PACKAGE_USAGE_STATS" android:label="@string/permlab_pkgUsageStats" android:description="@string/permdesc_pkgUsageStats" diff --git a/core/res/res/anim/ic_checkbox_checked_box_inner_merged_animation.xml b/core/res/res/anim/ic_checkbox_checked_box_inner_merged_animation.xml new file mode 100644 index 0000000..7be32af --- /dev/null +++ b/core/res/res/anim/ic_checkbox_checked_box_inner_merged_animation.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<set + xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="166" + android:propertyName="pathData" + android:valueFrom="M 0.0,-1.0 l 0.0,0.0 c 0.5522847498,0.0 1.0,0.4477152502 1.0,1.0 l 0.0,0.0 c 0.0,0.5522847498 -0.4477152502,1.0 -1.0,1.0 l 0.0,0.0 c -0.5522847498,0.0 -1.0,-0.4477152502 -1.0,-1.0 l 0.0,0.0 c 0.0,-0.5522847498 0.4477152502,-1.0 1.0,-1.0 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" + android:valueTo="M 0.0,-1.0 l 0.0,0.0 c 0.5522847498,0.0 1.0,0.4477152502 1.0,1.0 l 0.0,0.0 c 0.0,0.5522847498 -0.4477152502,1.0 -1.0,1.0 l 0.0,0.0 c -0.5522847498,0.0 -1.0,-0.4477152502 -1.0,-1.0 l 0.0,0.0 c 0.0,-0.5522847498 0.4477152502,-1.0 1.0,-1.0 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="333" + android:propertyName="pathData" + android:valueFrom="M 0.0,-1.0 l 0.0,0.0 c 0.5522847498,0.0 1.0,0.4477152502 1.0,1.0 l 0.0,0.0 c 0.0,0.5522847498 -0.4477152502,1.0 -1.0,1.0 l 0.0,0.0 c -0.5522847498,0.0 -1.0,-0.4477152502 -1.0,-1.0 l 0.0,0.0 c 0.0,-0.5522847498 0.4477152502,-1.0 1.0,-1.0 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" + android:valueTo="M -7.0,-7.0 l 14.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,14.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -14.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-14.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" + android:valueType="pathType" + android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_1" /> + </set> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="133" + android:propertyName="fillAlpha" + android:valueFrom="0.0" + android:valueTo="0.0" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="33" + android:propertyName="fillAlpha" + android:valueFrom="0.0" + android:valueTo="1.0" + android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_0" /> + </set> +</set> diff --git a/core/res/res/anim/ic_checkbox_checked_check_path_merged_animation.xml b/core/res/res/anim/ic_checkbox_checked_check_path_merged_animation.xml new file mode 100644 index 0000000..fcba2c8 --- /dev/null +++ b/core/res/res/anim/ic_checkbox_checked_check_path_merged_animation.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<set + xmlns:android="http://schemas.android.com/apk/res/android" > + <objectAnimator + android:duration="166" + android:propertyName="pathData" + android:valueFrom="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M -2.0,5.00001525879 c 0.0,0.0 -5.0,-5.00001525879 -5.0,-5.00001525879 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 3.58590698242,3.58601379395 3.58590698242,3.58601379395 c 0.0,0.0 7.58590698242,-7.58601379395 7.58590698242,-7.58601379395 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -9.0,9.00001525879 -9.0,9.00001525879 Z" + android:valueTo="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M 0.0,1.42500305176 c 0.0,0.0 -1.4234161377,-1.40159606934 -1.4234161377,-1.40159606934 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 0.00932312011719,-0.0124053955078 0.00932312011719,-0.0124053955078 c 0.0,0.0 0.0234069824219,-0.0235137939453 0.0234069824219,-0.0235137939453 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -1.4375,1.43751525879 -1.4375,1.43751525879 Z" + android:valueType="pathType" + android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_1" /> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="133" + android:propertyName="fillAlpha" + android:valueFrom="1.0" + android:valueTo="1.0" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="33" + android:propertyName="fillAlpha" + android:valueFrom="1.0" + android:valueTo="0.0" + android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_0" /> + </set> +</set> diff --git a/core/res/res/anim/ic_checkbox_checked_icon_null_animation.xml b/core/res/res/anim/ic_checkbox_checked_icon_null_animation.xml new file mode 100644 index 0000000..312003f --- /dev/null +++ b/core/res/res/anim/ic_checkbox_checked_icon_null_animation.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<set + xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="166" + android:propertyName="scaleX" + android:valueFrom="0.2" + android:valueTo="0.18" + android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_1" /> + <objectAnimator + android:duration="333" + android:propertyName="scaleX" + android:valueFrom="0.18" + android:valueTo="0.2" + android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_1" /> + </set> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="166" + android:propertyName="scaleY" + android:valueFrom="0.2" + android:valueTo="0.18" + android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_1" /> + <objectAnimator + android:duration="333" + android:propertyName="scaleY" + android:valueFrom="0.18" + android:valueTo="0.2" + android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_1" /> + </set> +</set> diff --git a/core/res/res/anim/ic_checkbox_unchecked_box_inner_merged_animation.xml b/core/res/res/anim/ic_checkbox_unchecked_box_inner_merged_animation.xml new file mode 100644 index 0000000..b5ad5e9d --- /dev/null +++ b/core/res/res/anim/ic_checkbox_unchecked_box_inner_merged_animation.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<set + xmlns:android="http://schemas.android.com/apk/res/android" > + <objectAnimator + android:duration="166" + android:propertyName="pathData" + android:valueFrom="M -7.0,-7.0 l 14.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,14.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -14.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-14.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" + android:valueTo="M 0.0,-0.05 l 0.0,0.0 c 0.02761423749,0.0 0.05,0.02238576251 0.05,0.05 l 0.0,0.0 c 0.0,0.02761423749 -0.02238576251,0.05 -0.05,0.05 l 0.0,0.0 c -0.02761423749,0.0 -0.05,-0.02238576251 -0.05,-0.05 l 0.0,0.0 c 0.0,-0.02761423749 0.02238576251,-0.05 0.05,-0.05 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" + android:valueType="pathType" + android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_1" /> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="166" + android:propertyName="fillAlpha" + android:valueFrom="1.0" + android:valueTo="1.0" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="33" + android:propertyName="fillAlpha" + android:valueFrom="1.0" + android:valueTo="0.0" + android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_0" /> + </set> +</set> diff --git a/core/res/res/anim/ic_checkbox_unchecked_box_outer_merged_animation.xml b/core/res/res/anim/ic_checkbox_unchecked_box_outer_merged_animation.xml new file mode 100644 index 0000000..066971a --- /dev/null +++ b/core/res/res/anim/ic_checkbox_unchecked_box_outer_merged_animation.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<set + xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="pathData" + android:valueFrom="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M -2.0,5.00001525879 c 0.0,0.0 -1.4234161377,-1.40159606934 -1.4234161377,-1.40159606934 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 0.00932312011719,-0.0124053955078 0.00932312011719,-0.0124053955078 c 0.0,0.0 0.0234069824219,-0.0235137939453 0.0234069824219,-0.0235137939453 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -1.4375,1.43751525879 -1.4375,1.43751525879 Z" + android:valueTo="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M -2.0,5.00001525879 c 0.0,0.0 -1.4234161377,-1.40159606934 -1.4234161377,-1.40159606934 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 0.00932312011719,-0.0124053955078 0.00932312011719,-0.0124053955078 c 0.0,0.0 0.0234069824219,-0.0235137939453 0.0234069824219,-0.0235137939453 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -1.4375,1.43751525879 -1.4375,1.43751525879 Z" + android:valueType="pathType" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="300" + android:propertyName="pathData" + android:valueFrom="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M -2.0,5.00001525879 c 0.0,0.0 -1.4234161377,-1.40159606934 -1.4234161377,-1.40159606934 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 0.00932312011719,-0.0124053955078 0.00932312011719,-0.0124053955078 c 0.0,0.0 0.0234069824219,-0.0235137939453 0.0234069824219,-0.0235137939453 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -1.4375,1.43751525879 -1.4375,1.43751525879 Z" + android:valueTo="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M -2.0,5.00001525879 c 0.0,0.0 -5.0,-5.00001525879 -5.0,-5.00001525879 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 3.58590698242,3.58601379395 3.58590698242,3.58601379395 c 0.0,0.0 7.58590698242,-7.58601379395 7.58590698242,-7.58601379395 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -9.0,9.00001525879 -9.0,9.00001525879 Z" + android:valueType="pathType" + android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_1" /> + </set> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="166" + android:propertyName="fillAlpha" + android:valueFrom="0.0" + android:valueTo="0.0" + android:interpolator="@android:interpolator/linear" /> + <objectAnimator + android:duration="33" + android:propertyName="fillAlpha" + android:valueFrom="0.0" + android:valueTo="1.0" + android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_0" /> + </set> +</set> diff --git a/core/res/res/anim/ic_checkbox_unchecked_icon_null_animation.xml b/core/res/res/anim/ic_checkbox_unchecked_icon_null_animation.xml new file mode 100644 index 0000000..fc40d47 --- /dev/null +++ b/core/res/res/anim/ic_checkbox_unchecked_icon_null_animation.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<set + xmlns:android="http://schemas.android.com/apk/res/android" > + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="scaleX" + android:valueFrom="0.2" + android:valueTo="0.18" + android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_1" /> + <objectAnimator + android:duration="300" + android:propertyName="scaleX" + android:valueFrom="0.18" + android:valueTo="0.2" + android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_1" /> + </set> + <set + android:ordering="sequentially" > + <objectAnimator + android:duration="200" + android:propertyName="scaleY" + android:valueFrom="0.2" + android:valueTo="0.18" + android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_1" /> + <objectAnimator + android:duration="300" + android:propertyName="scaleY" + android:valueFrom="0.18" + android:valueTo="0.2" + android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_1" /> + </set> +</set> diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_000.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_000.png Binary files differdeleted file mode 100644 index 3cb4073..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_000.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_001.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_001.png Binary files differdeleted file mode 100644 index 8fd1480..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_001.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_002.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_002.png Binary files differdeleted file mode 100644 index d35b579..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_002.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_003.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_003.png Binary files differdeleted file mode 100644 index 543c6bc..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_003.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_004.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_004.png Binary files differdeleted file mode 100644 index 4fc3c40..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_004.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_005.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_005.png Binary files differdeleted file mode 100644 index c184535..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_005.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_006.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_006.png Binary files differdeleted file mode 100644 index 9f9dd43..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_006.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_007.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_007.png Binary files differdeleted file mode 100644 index 8c629ce..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_007.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_008.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_008.png Binary files differdeleted file mode 100644 index 81134b5..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_008.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_009.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_009.png Binary files differdeleted file mode 100644 index baa5860..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_009.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_010.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_010.png Binary files differdeleted file mode 100644 index d7e28366..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_010.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_011.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_011.png Binary files differdeleted file mode 100644 index 6f24795..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_011.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_012.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_012.png Binary files differdeleted file mode 100644 index 22f997d..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_012.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_013.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_013.png Binary files differdeleted file mode 100644 index 85f4471..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_013.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_014.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_014.png Binary files differdeleted file mode 100644 index ad483c9..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_014.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_015.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_015.png Binary files differdeleted file mode 100644 index f24c2fb..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_015.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_000.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_000.png Binary files differdeleted file mode 100644 index 7a9e9bd..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_000.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_001.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_001.png Binary files differdeleted file mode 100644 index af04902..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_001.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_002.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_002.png Binary files differdeleted file mode 100644 index 32a6e94..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_002.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_003.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_003.png Binary files differdeleted file mode 100644 index c1b4b37..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_003.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_004.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_004.png Binary files differdeleted file mode 100644 index 34d3ade..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_004.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_005.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_005.png Binary files differdeleted file mode 100644 index 3d5db53..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_005.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_006.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_006.png Binary files differdeleted file mode 100644 index ea35437..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_006.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_007.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_007.png Binary files differdeleted file mode 100644 index 48744f8..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_007.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_008.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_008.png Binary files differdeleted file mode 100644 index f654517..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_008.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_009.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_009.png Binary files differdeleted file mode 100644 index 16f959a..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_009.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_010.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_010.png Binary files differdeleted file mode 100644 index 98c754b..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_010.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_011.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_011.png Binary files differdeleted file mode 100644 index 5827dc2..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_011.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_012.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_012.png Binary files differdeleted file mode 100644 index 9850d74..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_012.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_013.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_013.png Binary files differdeleted file mode 100644 index 03ab06b..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_013.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_014.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_014.png Binary files differdeleted file mode 100644 index 11cdd88..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_014.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_015.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_015.png Binary files differdeleted file mode 100644 index 874edbf..0000000 --- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_015.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_000.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_000.png Binary files differdeleted file mode 100644 index 9759818..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_000.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_001.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_001.png Binary files differdeleted file mode 100644 index 4eb2c4f..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_001.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_002.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_002.png Binary files differdeleted file mode 100644 index e6d6b42..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_002.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_003.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_003.png Binary files differdeleted file mode 100644 index 03cb23a..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_003.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_004.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_004.png Binary files differdeleted file mode 100644 index bfe3c3d..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_004.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_005.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_005.png Binary files differdeleted file mode 100644 index 65bdf42..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_005.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_006.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_006.png Binary files differdeleted file mode 100644 index 44f9614b..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_006.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_007.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_007.png Binary files differdeleted file mode 100644 index cf8ec38..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_007.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_008.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_008.png Binary files differdeleted file mode 100644 index 4d624b3..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_008.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_009.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_009.png Binary files differdeleted file mode 100644 index 7c4eb7f..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_009.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_010.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_010.png Binary files differdeleted file mode 100644 index e90dd31..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_010.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_011.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_011.png Binary files differdeleted file mode 100644 index 831c0e8..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_011.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_012.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_012.png Binary files differdeleted file mode 100644 index 7355dfd..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_012.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_013.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_013.png Binary files differdeleted file mode 100644 index be71a69..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_013.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_014.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_014.png Binary files differdeleted file mode 100644 index a4a185b..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_014.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_015.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_015.png Binary files differdeleted file mode 100644 index 8d0386f..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_015.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_000.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_000.png Binary files differdeleted file mode 100644 index 70793c4..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_000.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_001.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_001.png Binary files differdeleted file mode 100644 index 632082b..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_001.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_002.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_002.png Binary files differdeleted file mode 100644 index e7fc5fb..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_002.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_003.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_003.png Binary files differdeleted file mode 100644 index 91a0a33..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_003.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_004.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_004.png Binary files differdeleted file mode 100644 index 3bd90d6..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_004.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_005.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_005.png Binary files differdeleted file mode 100644 index 5ac39ec..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_005.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_006.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_006.png Binary files differdeleted file mode 100644 index 4181983..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_006.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_007.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_007.png Binary files differdeleted file mode 100644 index c8b04df..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_007.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_008.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_008.png Binary files differdeleted file mode 100644 index b7b3a9f..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_008.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_009.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_009.png Binary files differdeleted file mode 100644 index 62bc4ed..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_009.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_010.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_010.png Binary files differdeleted file mode 100644 index ac463ad..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_010.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_011.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_011.png Binary files differdeleted file mode 100644 index 12b605d..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_011.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_012.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_012.png Binary files differdeleted file mode 100644 index 63a3c6a..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_012.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_013.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_013.png Binary files differdeleted file mode 100644 index 17660c4..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_013.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_014.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_014.png Binary files differdeleted file mode 100644 index 7d9de3d..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_014.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_015.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_015.png Binary files differdeleted file mode 100644 index 8aa1be2..0000000 --- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_015.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_000.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_000.png Binary files differdeleted file mode 100644 index 2347643..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_000.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_001.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_001.png Binary files differdeleted file mode 100644 index 70aaa01..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_001.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_002.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_002.png Binary files differdeleted file mode 100644 index 01e498a..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_002.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_003.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_003.png Binary files differdeleted file mode 100644 index 71d1cf7..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_003.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_004.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_004.png Binary files differdeleted file mode 100644 index d1e7b1d..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_004.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_005.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_005.png Binary files differdeleted file mode 100644 index 7db7d06..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_005.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_006.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_006.png Binary files differdeleted file mode 100644 index dadb62e..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_006.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_007.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_007.png Binary files differdeleted file mode 100644 index f87f744..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_007.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_008.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_008.png Binary files differdeleted file mode 100644 index be99d87..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_008.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_009.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_009.png Binary files differdeleted file mode 100644 index f83bc05..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_009.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_010.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_010.png Binary files differdeleted file mode 100644 index 870071d..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_010.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_011.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_011.png Binary files differdeleted file mode 100644 index 3a18414..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_011.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_012.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_012.png Binary files differdeleted file mode 100644 index f3d1187..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_012.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_013.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_013.png Binary files differdeleted file mode 100644 index 4078cca..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_013.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_014.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_014.png Binary files differdeleted file mode 100644 index d4849b5..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_014.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_015.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_015.png Binary files differdeleted file mode 100644 index 6e2af72..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_015.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_000.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_000.png Binary files differdeleted file mode 100644 index 9244174..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_000.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_001.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_001.png Binary files differdeleted file mode 100644 index 8c7fe95..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_001.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_002.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_002.png Binary files differdeleted file mode 100644 index 71eb1d0..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_002.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_003.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_003.png Binary files differdeleted file mode 100644 index 613f38a..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_003.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_004.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_004.png Binary files differdeleted file mode 100644 index 2d20ccc..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_004.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_005.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_005.png Binary files differdeleted file mode 100644 index 407f78d..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_005.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_006.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_006.png Binary files differdeleted file mode 100644 index 1bf24b0..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_006.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_007.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_007.png Binary files differdeleted file mode 100644 index a450bd0..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_007.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_008.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_008.png Binary files differdeleted file mode 100644 index 63ba593..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_008.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_009.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_009.png Binary files differdeleted file mode 100644 index 6d05e5a..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_009.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_010.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_010.png Binary files differdeleted file mode 100644 index 1c8cd8f..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_010.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_011.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_011.png Binary files differdeleted file mode 100644 index b8bc564..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_011.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_012.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_012.png Binary files differdeleted file mode 100644 index 3d80128..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_012.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_013.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_013.png Binary files differdeleted file mode 100644 index c21dfba..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_013.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_014.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_014.png Binary files differdeleted file mode 100644 index 2dfe90d..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_014.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_015.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_015.png Binary files differdeleted file mode 100644 index 5f40d73..0000000 --- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_015.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_000.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_000.png Binary files differdeleted file mode 100644 index b754381..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_000.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_001.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_001.png Binary files differdeleted file mode 100644 index 517d7a7..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_001.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_002.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_002.png Binary files differdeleted file mode 100644 index 2c1d5b6..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_002.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_003.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_003.png Binary files differdeleted file mode 100644 index 0c6ff7e..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_003.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_004.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_004.png Binary files differdeleted file mode 100644 index 0796601..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_004.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_005.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_005.png Binary files differdeleted file mode 100644 index 9b4e0f8..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_005.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_006.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_006.png Binary files differdeleted file mode 100644 index 25767eb..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_006.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_007.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_007.png Binary files differdeleted file mode 100644 index cd0951f..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_007.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_008.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_008.png Binary files differdeleted file mode 100644 index 9ae8165..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_008.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_009.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_009.png Binary files differdeleted file mode 100644 index efd9bc6..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_009.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_010.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_010.png Binary files differdeleted file mode 100644 index fccbc9d..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_010.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_011.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_011.png Binary files differdeleted file mode 100644 index dddafca..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_011.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_012.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_012.png Binary files differdeleted file mode 100644 index 7e37433..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_012.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_013.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_013.png Binary files differdeleted file mode 100644 index 9bc22de..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_013.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_014.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_014.png Binary files differdeleted file mode 100644 index 507ed10..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_014.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_015.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_015.png Binary files differdeleted file mode 100644 index 6a21c7f..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_015.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_000.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_000.png Binary files differdeleted file mode 100644 index 0d544d9..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_000.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_001.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_001.png Binary files differdeleted file mode 100644 index 39da0ac..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_001.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_002.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_002.png Binary files differdeleted file mode 100644 index d5ada12..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_002.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_003.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_003.png Binary files differdeleted file mode 100644 index d4e096c..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_003.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_004.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_004.png Binary files differdeleted file mode 100644 index 468a9b4..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_004.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_005.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_005.png Binary files differdeleted file mode 100644 index ea3cd2e..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_005.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_006.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_006.png Binary files differdeleted file mode 100644 index 0652cb0..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_006.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_007.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_007.png Binary files differdeleted file mode 100644 index 768d2b0..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_007.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_008.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_008.png Binary files differdeleted file mode 100644 index 1d06a90..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_008.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_009.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_009.png Binary files differdeleted file mode 100644 index 8a70a80..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_009.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_010.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_010.png Binary files differdeleted file mode 100644 index bf9ec7f..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_010.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_011.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_011.png Binary files differdeleted file mode 100644 index cff07b9..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_011.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_012.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_012.png Binary files differdeleted file mode 100644 index 40f997e..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_012.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_013.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_013.png Binary files differdeleted file mode 100644 index 6ba84ec..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_013.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_014.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_014.png Binary files differdeleted file mode 100644 index 766610e..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_014.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_015.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_015.png Binary files differdeleted file mode 100644 index 810a029..0000000 --- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_015.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_000.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_000.png Binary files differdeleted file mode 100644 index f0ff1a7..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_000.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_001.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_001.png Binary files differdeleted file mode 100644 index b382df3..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_001.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_002.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_002.png Binary files differdeleted file mode 100644 index 8cb4ce2..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_002.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_003.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_003.png Binary files differdeleted file mode 100644 index 4db2b01..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_003.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_004.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_004.png Binary files differdeleted file mode 100644 index 8c4709b..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_004.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_005.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_005.png Binary files differdeleted file mode 100644 index 1ad960a..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_005.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_006.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_006.png Binary files differdeleted file mode 100644 index e47cc20..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_006.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_007.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_007.png Binary files differdeleted file mode 100644 index c4d0d51..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_007.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_008.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_008.png Binary files differdeleted file mode 100644 index 915d56a..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_008.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_009.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_009.png Binary files differdeleted file mode 100644 index 85795cb..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_009.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_010.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_010.png Binary files differdeleted file mode 100644 index 157fd91..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_010.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_011.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_011.png Binary files differdeleted file mode 100644 index 9d446de..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_011.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_012.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_012.png Binary files differdeleted file mode 100644 index dfac1f0..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_012.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_013.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_013.png Binary files differdeleted file mode 100644 index aed6c08..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_013.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_014.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_014.png Binary files differdeleted file mode 100644 index 1b8bd6b..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_014.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_015.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_015.png Binary files differdeleted file mode 100644 index 5dd0e5b..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_015.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_000.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_000.png Binary files differdeleted file mode 100644 index 5dd0e5b..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_000.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_001.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_001.png Binary files differdeleted file mode 100644 index 1a31ad9..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_001.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_002.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_002.png Binary files differdeleted file mode 100644 index 63c7f12..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_002.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_003.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_003.png Binary files differdeleted file mode 100644 index 847dd08..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_003.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_004.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_004.png Binary files differdeleted file mode 100644 index b93f3cc..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_004.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_005.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_005.png Binary files differdeleted file mode 100644 index 1e3dea7..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_005.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_006.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_006.png Binary files differdeleted file mode 100644 index 5a85238..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_006.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_007.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_007.png Binary files differdeleted file mode 100644 index 35960ca..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_007.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_008.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_008.png Binary files differdeleted file mode 100644 index 6db5555..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_008.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_009.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_009.png Binary files differdeleted file mode 100644 index a9c5851..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_009.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_010.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_010.png Binary files differdeleted file mode 100644 index 38465bd..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_010.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_011.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_011.png Binary files differdeleted file mode 100644 index 15942dc..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_011.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_012.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_012.png Binary files differdeleted file mode 100644 index 67d0d64..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_012.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_013.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_013.png Binary files differdeleted file mode 100644 index 69b5c1b..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_013.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_014.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_014.png Binary files differdeleted file mode 100644 index 0e5d331..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_014.png +++ /dev/null diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_015.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_015.png Binary files differdeleted file mode 100644 index f0ff1a7..0000000 --- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_015.png +++ /dev/null diff --git a/core/res/res/drawable/btn_check_material_anim.xml b/core/res/res/drawable/btn_check_material_anim.xml index 24df879..41caa4e 100644 --- a/core/res/res/drawable/btn_check_material_anim.xml +++ b/core/res/res/drawable/btn_check_material_anim.xml @@ -15,159 +15,15 @@ --> <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_enabled="false" android:state_checked="true"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_015" - android:tint="?attr/colorControlNormal" - android:alpha="?attr/disabledAlpha" /> - </item> - <item android:state_enabled="false"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_000" - android:tint="?attr/colorControlNormal" - android:alpha="?attr/disabledAlpha" /> - </item> - <item android:state_checked="true" android:id="@+id/on"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_015" - android:tint="?attr/colorControlActivated" /> - </item> - <item android:id="@+id/off"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_000" - android:tint="?attr/colorControlNormal" /> - </item> - <transition android:fromId="@+id/off" android:toId="@+id/on"> - <animation-list> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_000" - android:tint="?attr/colorControlNormal" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_001" - android:tint="?attr/colorControlNormal" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_002" - android:tint="?attr/colorControlNormal" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_003" - android:tint="?attr/colorControlNormal" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_004" - android:tint="?attr/colorControlNormal" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_005" - android:tint="?attr/colorControlNormal" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_006" - android:tint="?attr/colorControlNormal" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_007" - android:tint="?attr/colorControlNormal" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_008" - android:tint="?attr/colorControlActivated" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_009" - android:tint="?attr/colorControlActivated" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_010" - android:tint="?attr/colorControlActivated" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_011" - android:tint="?attr/colorControlActivated" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_012" - android:tint="?attr/colorControlActivated" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_013" - android:tint="?attr/colorControlActivated" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_014" - android:tint="?attr/colorControlActivated" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_on_mtrl_015" - android:tint="?attr/colorControlActivated" /> - </item> - </animation-list> - </transition> - <transition android:fromId="@+id/on" android:toId="@+id/off"> - <animation-list> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_off_mtrl_000" - android:tint="?attr/colorControlActivated" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_off_mtrl_001" - android:tint="?attr/colorControlActivated" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_off_mtrl_002" - android:tint="?attr/colorControlActivated" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_off_mtrl_003" - android:tint="?attr/colorControlActivated" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_off_mtrl_004" - android:tint="?attr/colorControlActivated" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_off_mtrl_005" - android:tint="?attr/colorControlActivated" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_off_mtrl_006" - android:tint="?attr/colorControlActivated" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_off_mtrl_007" - android:tint="?attr/colorControlActivated" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_off_mtrl_008" - android:tint="?attr/colorControlNormal" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_off_mtrl_009" - android:tint="?attr/colorControlNormal" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_off_mtrl_010" - android:tint="?attr/colorControlNormal" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_off_mtrl_011" - android:tint="?attr/colorControlNormal" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_off_mtrl_012" - android:tint="?attr/colorControlNormal" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_off_mtrl_013" - android:tint="?attr/colorControlNormal" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_off_mtrl_014" - android:tint="?attr/colorControlNormal" /> - </item> - <item android:duration="15"> - <bitmap android:src="@drawable/btn_check_to_off_mtrl_015" - android:tint="?attr/colorControlNormal" /> - </item> - </animation-list> - </transition> + <item android:state_checked="true" android:id="@+id/on" + android:drawable="@drawable/ic_checkbox_checked" /> + <item android:id="@+id/off" + android:drawable="@drawable/ic_checkbox_unchecked" /> + + <transition android:fromId="@+id/off" android:toId="@+id/on" + android:drawable="@drawable/ic_checkbox_unchecked_animation" /> + + <transition android:fromId="@+id/on" android:toId="@+id/off" + android:drawable="@drawable/ic_checkbox_checked_animation" /> </animated-selector> diff --git a/core/res/res/drawable/ic_checkbox_checked.xml b/core/res/res/drawable/ic_checkbox_checked.xml new file mode 100644 index 0000000..4764115 --- /dev/null +++ b/core/res/res/drawable/ic_checkbox_checked.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<vector + xmlns:android="http://schemas.android.com/apk/res/android" + android:name="ic_checkbox_checked" + android:width="32dp" + android:viewportWidth="48" + android:height="32dp" + android:viewportHeight="48" + android:tint="?attr/colorControlNormal" > + <group + android:name="icon_null" + android:translateX="24" + android:translateY="24" + android:scaleX="0.2" + android:scaleY="0.2" > + <group + android:name="check" + android:scaleX="7.5" + android:scaleY="7.5" > + <path + android:name="check_path_merged" + android:pathData="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M -2.0,5.00001525879 c 0.0,0.0 -5.0,-5.00001525879 -5.0,-5.00001525879 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 3.58590698242,3.58601379395 3.58590698242,3.58601379395 c 0.0,0.0 7.58590698242,-7.58601379395 7.58590698242,-7.58601379395 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -9.0,9.00001525879 -9.0,9.00001525879 Z" + android:fillColor="#FF000000" /> + </group> + <group + android:name="box_dilate" + android:scaleX="7.5" + android:scaleY="7.5" > + <path + android:name="box_inner_merged" + android:pathData="M 0.0,-1.0 l 0.0,0.0 c 0.5522847498,0.0 1.0,0.4477152502 1.0,1.0 l 0.0,0.0 c 0.0,0.5522847498 -0.4477152502,1.0 -1.0,1.0 l 0.0,0.0 c -0.5522847498,0.0 -1.0,-0.4477152502 -1.0,-1.0 l 0.0,0.0 c 0.0,-0.5522847498 0.4477152502,-1.0 1.0,-1.0 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" + android:fillColor="#FF000000" + android:fillAlpha="0" /> + </group> + </group> +</vector> diff --git a/core/res/res/drawable/ic_checkbox_checked_animation.xml b/core/res/res/drawable/ic_checkbox_checked_animation.xml new file mode 100644 index 0000000..af5eeee --- /dev/null +++ b/core/res/res/drawable/ic_checkbox_checked_animation.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/ic_checkbox_checked" > + <target + android:name="icon_null" + android:animation="@anim/ic_checkbox_checked_icon_null_animation" /> + <target + android:name="check_path_merged" + android:animation="@anim/ic_checkbox_checked_check_path_merged_animation" /> + <target + android:name="box_inner_merged" + android:animation="@anim/ic_checkbox_checked_box_inner_merged_animation" /> +</animated-vector> diff --git a/core/res/res/drawable/ic_checkbox_unchecked.xml b/core/res/res/drawable/ic_checkbox_unchecked.xml new file mode 100644 index 0000000..410f0bc --- /dev/null +++ b/core/res/res/drawable/ic_checkbox_unchecked.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<vector + xmlns:android="http://schemas.android.com/apk/res/android" + android:name="ic_checkbox_unchecked" + android:width="32dp" + android:viewportWidth="48" + android:height="32dp" + android:viewportHeight="48" + android:tint="?attr/colorControlNormal" > + <group + android:name="icon_null" + android:translateX="24" + android:translateY="24" + android:scaleX="0.2" + android:scaleY="0.2" > + <group + android:name="check" + android:scaleX="7.5" + android:scaleY="7.5" > + <path + android:name="box_outer_merged" + android:pathData="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M -2.0,5.00001525879 c 0.0,0.0 -1.4234161377,-1.40159606934 -1.4234161377,-1.40159606934 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 0.00932312011719,-0.0124053955078 0.00932312011719,-0.0124053955078 c 0.0,0.0 0.0234069824219,-0.0235137939453 0.0234069824219,-0.0235137939453 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -1.4375,1.43751525879 -1.4375,1.43751525879 Z" + android:fillColor="#FF000000" + android:fillAlpha="0" /> + </group> + <group + android:name="box_dilate" + android:scaleX="7.5" + android:scaleY="7.5" > + <path + android:name="box_inner_merged" + android:pathData="M -7.0,-7.0 l 14.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,14.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -14.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-14.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" + android:fillColor="#FF000000" /> + </group> + </group> +</vector> diff --git a/core/res/res/drawable/ic_checkbox_unchecked_animation.xml b/core/res/res/drawable/ic_checkbox_unchecked_animation.xml new file mode 100644 index 0000000..605fce1 --- /dev/null +++ b/core/res/res/drawable/ic_checkbox_unchecked_animation.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<animated-vector + xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/ic_checkbox_unchecked" > + <target + android:name="icon_null" + android:animation="@anim/ic_checkbox_unchecked_icon_null_animation" /> + <target + android:name="box_outer_merged" + android:animation="@anim/ic_checkbox_unchecked_box_outer_merged_animation" /> + <target + android:name="box_inner_merged" + android:animation="@anim/ic_checkbox_unchecked_box_inner_merged_animation" /> +</animated-vector> diff --git a/core/res/res/interpolator/ic_checkbox_checked_animation_interpolator_0.xml b/core/res/res/interpolator/ic_checkbox_checked_animation_interpolator_0.xml new file mode 100644 index 0000000..ceac663 --- /dev/null +++ b/core/res/res/interpolator/ic_checkbox_checked_animation_interpolator_0.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<pathInterpolator + xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0.0,0.0 l 1.0,0.0 l 0.0,1.0" /> diff --git a/core/res/res/interpolator/ic_checkbox_checked_animation_interpolator_1.xml b/core/res/res/interpolator/ic_checkbox_checked_animation_interpolator_1.xml new file mode 100644 index 0000000..26bc8ad --- /dev/null +++ b/core/res/res/interpolator/ic_checkbox_checked_animation_interpolator_1.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<pathInterpolator + xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0.0,0.0 c 0.33333333,0.0 0.0,1.0 1.0,1.0" /> diff --git a/core/res/res/interpolator/ic_checkbox_unchecked_animation_interpolator_0.xml b/core/res/res/interpolator/ic_checkbox_unchecked_animation_interpolator_0.xml new file mode 100644 index 0000000..ceac663 --- /dev/null +++ b/core/res/res/interpolator/ic_checkbox_unchecked_animation_interpolator_0.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<pathInterpolator + xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0.0,0.0 l 1.0,0.0 l 0.0,1.0" /> diff --git a/core/res/res/interpolator/ic_checkbox_unchecked_animation_interpolator_1.xml b/core/res/res/interpolator/ic_checkbox_unchecked_animation_interpolator_1.xml new file mode 100644 index 0000000..26bc8ad --- /dev/null +++ b/core/res/res/interpolator/ic_checkbox_unchecked_animation_interpolator_1.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<pathInterpolator + xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0.0,0.0 c 0.33333333,0.0 0.0,1.0 1.0,1.0" /> diff --git a/core/res/res/layout/floating_popup_container.xml b/core/res/res/layout/floating_popup_container.xml new file mode 100644 index 0000000..f247919 --- /dev/null +++ b/core/res/res/layout/floating_popup_container.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* Copyright 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. +*/ +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="horizontal" + android:layout_width="wrap_content" + android:layout_height="@dimen/floating_toolbar_height" + android:elevation="2dp" + android:focusable="true" + android:focusableInTouchMode="true" + android:background="@android:color/background_light" /> diff --git a/core/res/res/layout/floating_popup_menu_button.xml b/core/res/res/layout/floating_popup_menu_button.xml new file mode 100644 index 0000000..9fa13bd --- /dev/null +++ b/core/res/res/layout/floating_popup_menu_button.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* Copyright 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. +*/ +--> +<Button xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:minWidth="@dimen/floating_toolbar_menu_button_side_padding" + android:paddingLeft="@dimen/floating_toolbar_menu_button_side_padding" + android:paddingRight="@dimen/floating_toolbar_menu_button_side_padding" + android:paddingTop="0dp" + android:paddingBottom="0dp" + android:singleLine="true" + android:ellipsize="end" + android:fontFamily="sans-serif" + android:textSize="@dimen/floating_toolbar_text_size" + android:textAllCaps="true" + android:background="?attr/selectableItemBackground" />
\ No newline at end of file diff --git a/core/res/res/layout/floating_popup_open_overflow_button.xml b/core/res/res/layout/floating_popup_open_overflow_button.xml new file mode 100644 index 0000000..4c1176c --- /dev/null +++ b/core/res/res/layout/floating_popup_open_overflow_button.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* Copyright 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. +*/ +--> +<ImageButton xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="@dimen/floating_toolbar_menu_button_minimum_width" + android:layout_height="match_parent" + android:minWidth="@dimen/floating_toolbar_menu_button_minimum_width" + android:minHeight="@dimen/floating_toolbar_height" + android:src="@drawable/ic_menu_moreoverflow_material" + android:contentDescription="@string/action_menu_overflow_description" + android:background="?attr/selectableItemBackgroundBorderless" /> diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 0c61591..aed69ba 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Minute se sirkelglyer"</string> <string name="select_hours" msgid="6043079511766008245">"Kies ure"</string> <string name="select_minutes" msgid="3974345615920336087">"Kies minute"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Maandrooster van dae"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Jaarlys"</string> <string name="select_day" msgid="7774759604701773332">"Kies maand en dag"</string> <string name="select_year" msgid="7952052866994196170">"Kies jaar"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> gekies"</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index b639b4f..f6b38ad 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"የደቂቃዎች ክብ ተንሸራታች"</string> <string name="select_hours" msgid="6043079511766008245">"ሰዓታትን ይምረጡ"</string> <string name="select_minutes" msgid="3974345615920336087">"ደቂቃዎችን ይምረጡ"</string> - <string name="day_picker_description" msgid="8990847925961297968">"የቀናት የወር ፍርግርግ"</string> - <string name="year_picker_description" msgid="5524331207436052403">"የዓመት ዝርዝር"</string> <string name="select_day" msgid="7774759604701773332">"ወር እና ቀን ይምረጡ"</string> <string name="select_year" msgid="7952052866994196170">"ዓመት ይምረጡ"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ተመርጧል"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 42bf57d..ddb0e4d 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -1830,8 +1830,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"شريط التمرير الدائري للدقائق"</string> <string name="select_hours" msgid="6043079511766008245">"تحديد الساعات"</string> <string name="select_minutes" msgid="3974345615920336087">"تحديد الدقائق"</string> - <string name="day_picker_description" msgid="8990847925961297968">"شبكة الشهر مكونة من الأيام"</string> - <string name="year_picker_description" msgid="5524331207436052403">"قائمة الأعوام"</string> <string name="select_day" msgid="7774759604701773332">"تحديد الشهر واليوم"</string> <string name="select_year" msgid="7952052866994196170">"تحديد العام"</string> <string name="item_is_selected" msgid="949687401682476608">"تم تحديد <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index ecfa7bd..efae80e 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Кръгов плъзгач за минутите"</string> <string name="select_hours" msgid="6043079511766008245">"Избиране на часове"</string> <string name="select_minutes" msgid="3974345615920336087">"Избиране на минути"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Месечна таблица на дните"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Списък с години"</string> <string name="select_day" msgid="7774759604701773332">"Избиране на месец и ден"</string> <string name="select_year" msgid="7952052866994196170">"Избиране на година"</string> <string name="item_is_selected" msgid="949687401682476608">"Избрахте <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml index f20e21f..c47a502 100644 --- a/core/res/res/values-bn-rBD/strings.xml +++ b/core/res/res/values-bn-rBD/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"বৃত্তাকার মিনিট নির্বাচকের স্লাইডার"</string> <string name="select_hours" msgid="6043079511766008245">"ঘন্টা নির্বাচন করুন"</string> <string name="select_minutes" msgid="3974345615920336087">"মিনিট নির্বাচন করুন"</string> - <string name="day_picker_description" msgid="8990847925961297968">"দিন দিয়ে সংগঠিত মাসের গ্রিড"</string> - <string name="year_picker_description" msgid="5524331207436052403">"বছরের তালিকা"</string> <string name="select_day" msgid="7774759604701773332">"মাস এবং দিন নির্বাচন করুন"</string> <string name="select_year" msgid="7952052866994196170">"বছর নির্বাচন করুন"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> নির্বাচন করা হয়েছে"</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index aebebf2..ed964e9 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Control circular dels minuts"</string> <string name="select_hours" msgid="6043079511766008245">"Selecciona les hores"</string> <string name="select_minutes" msgid="3974345615920336087">"Selecciona els minuts"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Graella mensual de dies"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Llista anual"</string> <string name="select_day" msgid="7774759604701773332">"Selecciona un mes i un dia"</string> <string name="select_year" msgid="7952052866994196170">"Selecciona un any"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> seleccionat"</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 988818b..d7e86a5 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -1812,8 +1812,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Kruhový posuvník minut"</string> <string name="select_hours" msgid="6043079511766008245">"Zvolte hodiny"</string> <string name="select_minutes" msgid="3974345615920336087">"Zvolte minuty"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Dny uspořádané po měsících"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Seznam roků"</string> <string name="select_day" msgid="7774759604701773332">"Vyberte měsíc a den"</string> <string name="select_year" msgid="7952052866994196170">"Vyberte rok"</string> <string name="item_is_selected" msgid="949687401682476608">"Vybrána položka <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 20b7ad2..b97720d 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Cirkulær minutvælger"</string> <string name="select_hours" msgid="6043079511766008245">"Vælg timer"</string> <string name="select_minutes" msgid="3974345615920336087">"Vælg minutter"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Månedsgitter med dage"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Liste over år"</string> <string name="select_day" msgid="7774759604701773332">"Vælg måned og dag"</string> <string name="select_year" msgid="7952052866994196170">"Vælg år"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> er valgt"</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 07153fe..227e20c 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -203,7 +203,7 @@ <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flugmodus ist AN."</string> <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flugmodus ist AUS."</string> <string name="global_action_settings" msgid="1756531602592545966">"Einstellungen"</string> - <string name="global_action_assist" msgid="3892832961594295030">"Geräteassistent"</string> + <string name="global_action_assist" msgid="3892832961594295030">"Assistent"</string> <string name="global_action_voice_assist" msgid="7751191495200504480">"Sprachassistent"</string> <string name="global_action_lockdown" msgid="8751542514724332873">"Jetzt sperren"</string> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string> @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Kreisförmiger Schieberegler für Minuten"</string> <string name="select_hours" msgid="6043079511766008245">"Stunden auswählen"</string> <string name="select_minutes" msgid="3974345615920336087">"Minuten auswählen"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Monatsraster mit einzelnen Tagen"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Jahresliste"</string> <string name="select_day" msgid="7774759604701773332">"Monat und Tag auswählen"</string> <string name="select_year" msgid="7952052866994196170">"Jahr auswählen"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ausgewählt"</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index e0a6f88..c3e1bb7 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Κυκλικό ρυθμιστικό λεπτών"</string> <string name="select_hours" msgid="6043079511766008245">"Επιλογή ωρών"</string> <string name="select_minutes" msgid="3974345615920336087">"Επιλογή λεπτών"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Πλέγμα ημερών του μήνα"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Λίστα ετών"</string> <string name="select_day" msgid="7774759604701773332">"Επιλογή μήνα και ημέρας"</string> <string name="select_year" msgid="7952052866994196170">"Επιλογή έτους"</string> <string name="item_is_selected" msgid="949687401682476608">"Επιλέχτηκε το στοιχείο <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index f52daf6..bfcb90c 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Minutes circular slider"</string> <string name="select_hours" msgid="6043079511766008245">"Select hours"</string> <string name="select_minutes" msgid="3974345615920336087">"Select minutes"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Month grid of days"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Year list"</string> <string name="select_day" msgid="7774759604701773332">"Select month and day"</string> <string name="select_year" msgid="7952052866994196170">"Select year"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selected"</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index f52daf6..bfcb90c 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Minutes circular slider"</string> <string name="select_hours" msgid="6043079511766008245">"Select hours"</string> <string name="select_minutes" msgid="3974345615920336087">"Select minutes"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Month grid of days"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Year list"</string> <string name="select_day" msgid="7774759604701773332">"Select month and day"</string> <string name="select_year" msgid="7952052866994196170">"Select year"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selected"</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index f52daf6..bfcb90c 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Minutes circular slider"</string> <string name="select_hours" msgid="6043079511766008245">"Select hours"</string> <string name="select_minutes" msgid="3974345615920336087">"Select minutes"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Month grid of days"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Year list"</string> <string name="select_day" msgid="7774759604701773332">"Select month and day"</string> <string name="select_year" msgid="7952052866994196170">"Select year"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selected"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index ce419dc..78cc227 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Control deslizante circular de minutos"</string> <string name="select_hours" msgid="6043079511766008245">"Seleccionar horas"</string> <string name="select_minutes" msgid="3974345615920336087">"Seleccionar minutos"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Cuadrícula mensual de días"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Lista de años"</string> <string name="select_day" msgid="7774759604701773332">"Seleccionar mes y día"</string> <string name="select_year" msgid="7952052866994196170">"Seleccionar año"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> seleccionado"</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index e22ea21..969881c 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Control deslizante circular de minutos"</string> <string name="select_hours" msgid="6043079511766008245">"Seleccionar horas"</string> <string name="select_minutes" msgid="3974345615920336087">"Seleccionar minutos"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Cuadrícula mensual de días"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Lista de años"</string> <string name="select_day" msgid="7774759604701773332">"Seleccionar mes y día"</string> <string name="select_year" msgid="7952052866994196170">"Seleccionar año"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> seleccionado"</string> diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml index 85b5c3c..72b13da 100644 --- a/core/res/res/values-et-rEE/strings.xml +++ b/core/res/res/values-et-rEE/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Ringikujuline minutiliugur"</string> <string name="select_hours" msgid="6043079511766008245">"Tundide valimine"</string> <string name="select_minutes" msgid="3974345615920336087">"Minutite valimine"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Päevad kuu ruudustikus"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Aastate loend"</string> <string name="select_day" msgid="7774759604701773332">"Kuu ja päeva valimine"</string> <string name="select_year" msgid="7952052866994196170">"Aasta valimine"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> on valitud"</string> diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml index 02d8dd3..da96ec3 100644 --- a/core/res/res/values-eu-rES/strings.xml +++ b/core/res/res/values-eu-rES/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Minutuak aukeratzeko ikuspegi zirkularra"</string> <string name="select_hours" msgid="6043079511766008245">"Hautatu orduak"</string> <string name="select_minutes" msgid="3974345615920336087">"Hautatu minutuak"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Hilabete-ikuspegiko eguna aukeratzeko sareta"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Urteen zerrenda"</string> <string name="select_day" msgid="7774759604701773332">"Hautatu hilabetea eta eguna"</string> <string name="select_year" msgid="7952052866994196170">"Hautatu urtea"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> hautatu da"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 2073b5e..1aa1cc8 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"لغزنده دایرهای دقیقه"</string> <string name="select_hours" msgid="6043079511766008245">"انتخاب ساعت"</string> <string name="select_minutes" msgid="3974345615920336087">"انتخاب دقیقه"</string> - <string name="day_picker_description" msgid="8990847925961297968">"جدول روزها براساس ماه"</string> - <string name="year_picker_description" msgid="5524331207436052403">"لیست سالها"</string> <string name="select_day" msgid="7774759604701773332">"انتخاب ماه و روز"</string> <string name="select_year" msgid="7952052866994196170">"انتخاب سال"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> انتخاب شد"</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index a2f1ccf..39860e3 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Minuuttien ympyränmuotoinen liukusäädin"</string> <string name="select_hours" msgid="6043079511766008245">"Valitse tunnit"</string> <string name="select_minutes" msgid="3974345615920336087">"Valitse minuutit"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Päiväruudukko kuukausittain"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Vuosiluettelo"</string> <string name="select_day" msgid="7774759604701773332">"Valitse kuukausi ja päivä"</string> <string name="select_year" msgid="7952052866994196170">"Valitse vuosi"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> on valittu"</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 837b58a..4a3e4a1 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Curseur circulaire des minutes"</string> <string name="select_hours" msgid="6043079511766008245">"Sélectionnez les heures"</string> <string name="select_minutes" msgid="3974345615920336087">"Sélectionnez les minutes"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Calendrier mensuel sous forme de grille"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Liste des années"</string> <string name="select_day" msgid="7774759604701773332">"Sélectionnez un mois et un jour"</string> <string name="select_year" msgid="7952052866994196170">"Sélectionnez une année"</string> <string name="item_is_selected" msgid="949687401682476608">"« <xliff:g id="ITEM">%1$s</xliff:g> » a été sélectionné"</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index c6e1387..1713dd8 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Curseur circulaire des minutes"</string> <string name="select_hours" msgid="6043079511766008245">"Sélectionner une heure"</string> <string name="select_minutes" msgid="3974345615920336087">"Sélectionner des minutes"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Calendrier mensuel sous forme de grille"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Liste des années"</string> <string name="select_day" msgid="7774759604701773332">"Sélectionner un mois et un jour"</string> <string name="select_year" msgid="7952052866994196170">"Sélectionner une année"</string> <string name="item_is_selected" msgid="949687401682476608">"\"<xliff:g id="ITEM">%1$s</xliff:g>\" sélectionné"</string> diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml index 5218ed5..e35d654 100644 --- a/core/res/res/values-gl-rES/strings.xml +++ b/core/res/res/values-gl-rES/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Control de desprazamento circular dos minutos"</string> <string name="select_hours" msgid="6043079511766008245">"Seleccionar horas"</string> <string name="select_minutes" msgid="3974345615920336087">"Seleccionar minutos"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Grade mensual de días"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Lista de anos"</string> <string name="select_day" msgid="7774759604701773332">"Seleccionar mes e día"</string> <string name="select_year" msgid="7952052866994196170">"Seleccionar ano"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> seleccionado"</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 6463cc5..53c395d 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -1211,9 +1211,9 @@ <string name="app_running_notification_title" msgid="8718335121060787914">"<xliff:g id="APP_NAME">%1$s</xliff:g> चल रहा है"</string> <string name="app_running_notification_text" msgid="4653586947747330058">"अधिक जानकारी के लिए या ऐप्स रोकने के लिए स्पर्श करें."</string> <string name="ok" msgid="5970060430562524910">"ठीक है"</string> - <string name="cancel" msgid="6442560571259935130">"रहने दें"</string> + <string name="cancel" msgid="6442560571259935130">"अभी नहीं"</string> <string name="yes" msgid="5362982303337969312">"ठीक है"</string> - <string name="no" msgid="5141531044935541497">"रहने दें"</string> + <string name="no" msgid="5141531044935541497">"अभी नहीं"</string> <string name="dialog_alert_title" msgid="2049658708609043103">"ध्यान दें"</string> <string name="loading" msgid="7933681260296021180">"लोड हो रहे हैं..."</string> <string name="capital_on" msgid="1544682755514494298">"चालू"</string> @@ -1335,7 +1335,7 @@ <string name="sms_short_code_details" msgid="5873295990846059400">"इससे आपके मोबाइल खाते पर "<b>"शुल्क लग सकता है"</b>"."</string> <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"इससे आपके मोबाइल खाते पर शुल्क लगेगा."</b></string> <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"भेजें"</string> - <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"रहने दें"</string> + <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"अभी नहीं"</string> <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"मेरी पसंद को याद रखें"</string> <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"आप इसे बाद में सेटिंग > ऐप्स में बदल सकते हैं"</string> <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"हमेशा अनुमति दें"</string> @@ -1545,7 +1545,7 @@ <string name="date_picker_increment_year_button" msgid="6318697384310808899">"वर्ष बढ़ाएं"</string> <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"वर्ष कम करें"</string> <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string> - <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"रहने दें"</string> + <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"अभी नहीं"</string> <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"हटाएं"</string> <string name="keyboardview_keycode_done" msgid="1992571118466679775">"पूर्ण"</string> <string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"Mode change"</string> @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"मिनटों का चक्राकार स्लाइडर"</string> <string name="select_hours" msgid="6043079511766008245">"घंटे चुनें"</string> <string name="select_minutes" msgid="3974345615920336087">"मिनट चुनें"</string> - <string name="day_picker_description" msgid="8990847925961297968">"दिनों की माह ग्रिड"</string> - <string name="year_picker_description" msgid="5524331207436052403">"वर्ष की सूची"</string> <string name="select_day" msgid="7774759604701773332">"माह और दिन चुनें"</string> <string name="select_year" msgid="7952052866994196170">"वर्ष चुनें"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> चयनित"</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index 0f39d7c..7d39eb8 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -1803,8 +1803,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Kružni klizač minuta"</string> <string name="select_hours" msgid="6043079511766008245">"Odaberite sate"</string> <string name="select_minutes" msgid="3974345615920336087">"Odaberite minute"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Mreža dana u mjesecu"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Popis godina"</string> <string name="select_day" msgid="7774759604701773332">"Odaberite mjesec i dan"</string> <string name="select_year" msgid="7952052866994196170">"Odaberite godinu"</string> <string name="item_is_selected" msgid="949687401682476608">"Odabrana je stavka <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index adada44..9a9bfb3 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Perc kör alakú csúszkája"</string> <string name="select_hours" msgid="6043079511766008245">"Óra kiválasztása"</string> <string name="select_minutes" msgid="3974345615920336087">"Perc kiválasztása"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Napok havi leosztásban"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Évek listája"</string> <string name="select_day" msgid="7774759604701773332">"Válassza ki a hónapot és a napot"</string> <string name="select_year" msgid="7952052866994196170">"Válassza ki az évet"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> kiválasztva"</string> diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml index 65bacf7..1b5dfaa 100644 --- a/core/res/res/values-hy-rAM/strings.xml +++ b/core/res/res/values-hy-rAM/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Րոպեների ընտրություն թվատախտակից"</string> <string name="select_hours" msgid="6043079511766008245">"Ընտրեք ժամը"</string> <string name="select_minutes" msgid="3974345615920336087">"Ընտրեք րոպեն"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Ամսաթվի ընտրության պատուհան"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Տարիների ցանկ"</string> <string name="select_day" msgid="7774759604701773332">"Ընտրեք ամիսն ու օրը"</string> <string name="select_year" msgid="7952052866994196170">"Ընտրեք տարին"</string> <string name="item_is_selected" msgid="949687401682476608">"Ընտրված է <xliff:g id="ITEM">%1$s</xliff:g> տարրը"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 2f7cb25..b0deed2 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Penggeser putar menit"</string> <string name="select_hours" msgid="6043079511766008245">"Pilih jam"</string> <string name="select_minutes" msgid="3974345615920336087">"Pilih menit"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Kisi hari pada bulan"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Daftar tahun"</string> <string name="select_day" msgid="7774759604701773332">"Pilih bulan dan hari"</string> <string name="select_year" msgid="7952052866994196170">"Pilih tahun"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> dipilih"</string> diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml index a926d3d..5538c00 100644 --- a/core/res/res/values-is-rIS/strings.xml +++ b/core/res/res/values-is-rIS/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Valskífa fyrir mínútur"</string> <string name="select_hours" msgid="6043079511766008245">"Veldu klukkustundir"</string> <string name="select_minutes" msgid="3974345615920336087">"Veldu mínútur"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Mánaðartafla með dögum"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Áralisti"</string> <string name="select_day" msgid="7774759604701773332">"Veldu mánuð og dag"</string> <string name="select_year" msgid="7952052866994196170">"Veldu ár"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> valið"</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 74ad5f7..d8dd2ea 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Dispositivo di scorrimento circolare per i minuti"</string> <string name="select_hours" msgid="6043079511766008245">"Seleziona le ore"</string> <string name="select_minutes" msgid="3974345615920336087">"Seleziona i minuti"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Griglia di giorni per mese"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Elenco degli anni"</string> <string name="select_day" msgid="7774759604701773332">"Seleziona mese e giorno"</string> <string name="select_year" msgid="7952052866994196170">"Seleziona anno"</string> <string name="item_is_selected" msgid="949687401682476608">"Elemento selezionato: <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 1e8d680..1839b45 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -1812,8 +1812,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"מחוון דקות מעגלי"</string> <string name="select_hours" msgid="6043079511766008245">"בחר שעות"</string> <string name="select_minutes" msgid="3974345615920336087">"בחר דקות"</string> - <string name="day_picker_description" msgid="8990847925961297968">"בחירת ימים בחודש בתצוגת רשת"</string> - <string name="year_picker_description" msgid="5524331207436052403">"רשימת שנים"</string> <string name="select_day" msgid="7774759604701773332">"בחר חודש ויום"</string> <string name="select_year" msgid="7952052866994196170">"בחר שנה"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> נבחר"</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 5598018..613a2f1 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"円形スライダー(分)"</string> <string name="select_hours" msgid="6043079511766008245">"時間を選択"</string> <string name="select_minutes" msgid="3974345615920336087">"分を選択"</string> - <string name="day_picker_description" msgid="8990847925961297968">"日グリッド(月別)"</string> - <string name="year_picker_description" msgid="5524331207436052403">"年リスト"</string> <string name="select_day" msgid="7774759604701773332">"月と日を選択"</string> <string name="select_year" msgid="7952052866994196170">"年を選択"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g>を選択しました"</string> diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml index d179c28..befe9e7 100644 --- a/core/res/res/values-ka-rGE/strings.xml +++ b/core/res/res/values-ka-rGE/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"წუთების წრიული სლაიდერი"</string> <string name="select_hours" msgid="6043079511766008245">"აირჩიეთ საათები"</string> <string name="select_minutes" msgid="3974345615920336087">"აირჩიეთ წუთები"</string> - <string name="day_picker_description" msgid="8990847925961297968">"დღეების ბადე თვეზე"</string> - <string name="year_picker_description" msgid="5524331207436052403">"წლის სია"</string> <string name="select_day" msgid="7774759604701773332">"აირჩიეთ თვე და რიცხვი"</string> <string name="select_year" msgid="7952052866994196170">"აირჩიეთ წელი"</string> <string name="item_is_selected" msgid="949687401682476608">"არჩეულია <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml index caa12d2..8b19127 100644 --- a/core/res/res/values-kk-rKZ/strings.xml +++ b/core/res/res/values-kk-rKZ/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Минут айналымын қозғалтқыш"</string> <string name="select_hours" msgid="6043079511766008245">"Сағат таңдау"</string> <string name="select_minutes" msgid="3974345615920336087">"Минут таңдау"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Күндердің айлық торлары"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Жыл тізімі"</string> <string name="select_day" msgid="7774759604701773332">"Ай мен күнді таңдау"</string> <string name="select_year" msgid="7952052866994196170">"Жыл таңдау"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> таңдалды"</string> diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml index 3326462..12c9661 100644 --- a/core/res/res/values-km-rKH/strings.xml +++ b/core/res/res/values-km-rKH/strings.xml @@ -1796,8 +1796,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"គ្រាប់រំកិលរង្វង់នាទី"</string> <string name="select_hours" msgid="6043079511766008245">"ជ្រើសម៉ោង"</string> <string name="select_minutes" msgid="3974345615920336087">"ជ្រើសនាទី"</string> - <string name="day_picker_description" msgid="8990847925961297968">"ក្រឡាខែនៃថ្ងៃ"</string> - <string name="year_picker_description" msgid="5524331207436052403">"បញ្ជីឆ្នាំ"</string> <string name="select_day" msgid="7774759604701773332">"ជ្រើសខែ និងថ្ងៃ"</string> <string name="select_year" msgid="7952052866994196170">"ជ្រើសឆ្នាំ"</string> <string name="item_is_selected" msgid="949687401682476608">"បានជ្រើស <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml index 2bd45d4..2f967ea 100644 --- a/core/res/res/values-kn-rIN/strings.xml +++ b/core/res/res/values-kn-rIN/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"ನಿಮಿಷಗಳ ವೃತ್ತಾಕಾರ ಸ್ಲೈಡರ್"</string> <string name="select_hours" msgid="6043079511766008245">"ಗಂಟೆಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string> <string name="select_minutes" msgid="3974345615920336087">"ನಿಮಿಷಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string> - <string name="day_picker_description" msgid="8990847925961297968">"ದಿನಗಳ ತಿಂಗಳಿನ ಗ್ರಿಡ್"</string> - <string name="year_picker_description" msgid="5524331207436052403">"ವರ್ಷದ ಪಟ್ಟಿ"</string> <string name="select_day" msgid="7774759604701773332">"ತಿಂಗಳು ಮತ್ತು ದಿನವನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string> <string name="select_year" msgid="7952052866994196170">"ವರ್ಷವನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 463f84d..654fffb 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"분 원형 슬라이더"</string> <string name="select_hours" msgid="6043079511766008245">"시간 선택"</string> <string name="select_minutes" msgid="3974345615920336087">"분 선택"</string> - <string name="day_picker_description" msgid="8990847925961297968">"월별 바둑판식 날짜 표시"</string> - <string name="year_picker_description" msgid="5524331207436052403">"년"</string> <string name="select_day" msgid="7774759604701773332">"월/일 선택"</string> <string name="select_year" msgid="7952052866994196170">"연도 선택"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g>이(가) 선택됨"</string> diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml index fdfc442..5905240 100644 --- a/core/res/res/values-ky-rKG/strings.xml +++ b/core/res/res/values-ky-rKG/strings.xml @@ -2309,8 +2309,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Мүнөт жебеси"</string> <string name="select_hours" msgid="6043079511766008245">"Саатты тандаңыз"</string> <string name="select_minutes" msgid="3974345615920336087">"Мүнөттөрдү тандаңыз"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Айдын күндөрү"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Жыл тизмеги"</string> <string name="select_day" msgid="7774759604701773332">"Ай жана күндү тандаңыз"</string> <string name="select_year" msgid="7952052866994196170">"Жылды тандаңыз"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> тандалды"</string> diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml index e565c00..c932d2d 100644 --- a/core/res/res/values-lo-rLA/strings.xml +++ b/core/res/res/values-lo-rLA/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"ໂຕໝຸນປັບນາທີ"</string> <string name="select_hours" msgid="6043079511766008245">"ເລືອກຊົ່ວໂມງ"</string> <string name="select_minutes" msgid="3974345615920336087">"ເລືອກນາທີ"</string> - <string name="day_picker_description" msgid="8990847925961297968">"ຕາຕາລາງວັນທີເດືອນປີ"</string> - <string name="year_picker_description" msgid="5524331207436052403">"ລາຍການປີ"</string> <string name="select_day" msgid="7774759604701773332">"ເລືອກເດືອນ ແລະ ວັນ"</string> <string name="select_year" msgid="7952052866994196170">"ເລືອກປີ"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ຖືກເລືອກແລ້ວ"</string> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index 099593c..42b7770 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -1812,8 +1812,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Apskritas minučių slankiklis"</string> <string name="select_hours" msgid="6043079511766008245">"Pasirinkite valandas"</string> <string name="select_minutes" msgid="3974345615920336087">"Pasirinkite minutes"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Mėnesio dienų tinklelis"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Metų sąrašas"</string> <string name="select_day" msgid="7774759604701773332">"Pasirinkite mėnesį ir dieną"</string> <string name="select_year" msgid="7952052866994196170">"Pasirinkite metus"</string> <string name="item_is_selected" msgid="949687401682476608">"Pasirinkta: <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 9ab2772..1be0eeb 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -1803,8 +1803,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Minūšu apļveida slīdnis"</string> <string name="select_hours" msgid="6043079511766008245">"Atlasiet stundas."</string> <string name="select_minutes" msgid="3974345615920336087">"Atlasiet minūtes."</string> - <string name="day_picker_description" msgid="8990847925961297968">"Režģis ar mēneša dienām"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Gadu saraksts"</string> <string name="select_day" msgid="7774759604701773332">"Atlasiet mēnesi un dienu."</string> <string name="select_year" msgid="7952052866994196170">"Atlasiet gadu."</string> <string name="item_is_selected" msgid="949687401682476608">"Atlasīts: <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-mcc310-mnc260/strings.xml b/core/res/res/values-mcc310-mnc260/strings.xml index 5cadc2a..75b1b53 100644 --- a/core/res/res/values-mcc310-mnc260/strings.xml +++ b/core/res/res/values-mcc310-mnc260/strings.xml @@ -29,4 +29,6 @@ <string-array name="wfcOperatorErrorMessages"> <item>Wi-Fi Calling isn\'t available. Contact your carrier to enable Wi-Fi Calling.</item> </string-array> + <!-- Template for showing cellular network operator name while WFC is active --> + <string name="wfcSpnFormat">%s Wi-Fi Calling</string> </resources> diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml index 2080d50..387238e 100644 --- a/core/res/res/values-mk-rMK/strings.xml +++ b/core/res/res/values-mk-rMK/strings.xml @@ -1796,8 +1796,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Приказ на минути во кружно движење"</string> <string name="select_hours" msgid="6043079511766008245">"Избери часови"</string> <string name="select_minutes" msgid="3974345615920336087">"Избери минути"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Рамка на месец со денови"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Список по години"</string> <string name="select_day" msgid="7774759604701773332">"Избери месец и ден"</string> <string name="select_year" msgid="7952052866994196170">"Избери година"</string> <string name="item_is_selected" msgid="949687401682476608">"Избрано <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml index 2ae1177..68fd869 100644 --- a/core/res/res/values-ml-rIN/strings.xml +++ b/core/res/res/values-ml-rIN/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"ചാക്രികമായി മിനിറ്റുകൾ ദൃശ്യമാകുന്ന സ്ലൈഡർ"</string> <string name="select_hours" msgid="6043079511766008245">"മണിക്കൂർ തിരഞ്ഞെടുക്കുക"</string> <string name="select_minutes" msgid="3974345615920336087">"മിനിറ്റ് തിരഞ്ഞെടുക്കുക"</string> - <string name="day_picker_description" msgid="8990847925961297968">"മാസപ്രകാരമുള്ള ദിവസ ഗ്രിഡ്"</string> - <string name="year_picker_description" msgid="5524331207436052403">"വർഷങ്ങളുടെ ലിസ്റ്റ്"</string> <string name="select_day" msgid="7774759604701773332">"മാസവും ദിവസവും തിരഞ്ഞെടുക്കുക"</string> <string name="select_year" msgid="7952052866994196170">"വർഷം തിരഞ്ഞെടുക്കുക"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> തിരഞ്ഞെടുത്തു"</string> diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml index 4a8b5b9..07fb9a9 100644 --- a/core/res/res/values-mn-rMN/strings.xml +++ b/core/res/res/values-mn-rMN/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Минут гүйлгэгч"</string> <string name="select_hours" msgid="6043079511766008245">"Цаг сонгоно уу"</string> <string name="select_minutes" msgid="3974345615920336087">"Минут сонгоно уу"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Өдрүүдийг сараар"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Жилийн жагсаалт"</string> <string name="select_day" msgid="7774759604701773332">"Сар болон өдрийг сонгоно уу"</string> <string name="select_year" msgid="7952052866994196170">"Жилийг сонгоно уу"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> сонгогдсон"</string> diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml index 3fc5663..737154e 100644 --- a/core/res/res/values-mr-rIN/strings.xml +++ b/core/res/res/values-mr-rIN/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"मिनिटे परिपत्रक स्लायडर"</string> <string name="select_hours" msgid="6043079511766008245">"तास निवडा"</string> <string name="select_minutes" msgid="3974345615920336087">"मिनिटे निवडा"</string> - <string name="day_picker_description" msgid="8990847925961297968">"दिवसांची महिना ग्रिड"</string> - <string name="year_picker_description" msgid="5524331207436052403">"वर्ष सूची"</string> <string name="select_day" msgid="7774759604701773332">"महिना आणि दिवस निवडा"</string> <string name="select_year" msgid="7952052866994196170">"वर्ष निवडा"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> निवडले"</string> diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml index d849680..10d5d5f 100644 --- a/core/res/res/values-ms-rMY/strings.xml +++ b/core/res/res/values-ms-rMY/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Penggelangsar bulatan minit"</string> <string name="select_hours" msgid="6043079511766008245">"Pilih jam"</string> <string name="select_minutes" msgid="3974345615920336087">"Pilih minit"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Grid hari bulanan"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Senarai tahun"</string> <string name="select_day" msgid="7774759604701773332">"Pilih bulan dan hari"</string> <string name="select_year" msgid="7952052866994196170">"Pilih tahun"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> dipilih"</string> diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml index 36a6cde..f97c576 100644 --- a/core/res/res/values-my-rMM/strings.xml +++ b/core/res/res/values-my-rMM/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"မိနစ်လှည့်သော ရွေ့လျားတန်"</string> <string name="select_hours" msgid="6043079511766008245">"နာရီများ ရွေးပါ"</string> <string name="select_minutes" msgid="3974345615920336087">"မိနစ်များ ရွေးပါ"</string> - <string name="day_picker_description" msgid="8990847925961297968">"လအလိုက် ရွေးနိုင်သော ရက်များ"</string> - <string name="year_picker_description" msgid="5524331207436052403">"ခုနှစ် အစဉ်"</string> <string name="select_day" msgid="7774759604701773332">"လ နှင့် ရက် ရွေးပါ"</string> <string name="select_year" msgid="7952052866994196170">"ခုနှစ်ကို ရွေးပါ"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ခုရွေးချယ်ထားပြီး"</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 022bb16..3b45940 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Sirkulær glidebryter for minutter"</string> <string name="select_hours" msgid="6043079511766008245">"Angi timer"</string> <string name="select_minutes" msgid="3974345615920336087">"Angi minutter"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Månedsrutenett med dager"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Årsliste"</string> <string name="select_day" msgid="7774759604701773332">"Velg måneden og dagen"</string> <string name="select_year" msgid="7952052866994196170">"Velg året"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> er valgt"</string> diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml index 54fe0e5..907047f 100644 --- a/core/res/res/values-ne-rNP/strings.xml +++ b/core/res/res/values-ne-rNP/strings.xml @@ -1800,8 +1800,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"मिनेट गोलाकार स्लाइडर"</string> <string name="select_hours" msgid="6043079511766008245">"घण्टा चयन गर्नुहोस्"</string> <string name="select_minutes" msgid="3974345615920336087">"मिनेट चयन गर्नुहोस्"</string> - <string name="day_picker_description" msgid="8990847925961297968">"दिनहरुको महिना ग्रिड"</string> - <string name="year_picker_description" msgid="5524331207436052403">"वर्ष सूची"</string> <string name="select_day" msgid="7774759604701773332">"महिना र दिन चयन गर्नुहोस्"</string> <string name="select_year" msgid="7952052866994196170">"वर्ष चयन गर्नुहोस्"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> चयन गरियो"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 3318bff..d6c02f5 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Ronde schuifregelaar voor minuten"</string> <string name="select_hours" msgid="6043079511766008245">"Uren selecteren"</string> <string name="select_minutes" msgid="3974345615920336087">"Minuten selecteren"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Maandraster van dagen"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Jaarlijst"</string> <string name="select_day" msgid="7774759604701773332">"Maand en dag selecteren"</string> <string name="select_year" msgid="7952052866994196170">"Jaar selecteren"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> geselecteerd"</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 4e56e90..8e31053 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -1812,8 +1812,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Kołowy suwak minut"</string> <string name="select_hours" msgid="6043079511766008245">"Wybierz godziny"</string> <string name="select_minutes" msgid="3974345615920336087">"Wybierz minuty"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Siatka miesięczna z dniami"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Lista lat"</string> <string name="select_day" msgid="7774759604701773332">"Wybierz miesiąc i dzień"</string> <string name="select_year" msgid="7952052866994196170">"Wybierz rok"</string> <string name="item_is_selected" msgid="949687401682476608">"Wybrałeś <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 1ddef71..7a0985c 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Controlo de deslize circular dos minutos"</string> <string name="select_hours" msgid="6043079511766008245">"Selecionar horas"</string> <string name="select_minutes" msgid="3974345615920336087">"Selecionar minutos"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Grelha de dias do mês"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Lista de anos"</string> <string name="select_day" msgid="7774759604701773332">"Selecionar mês e dia"</string> <string name="select_year" msgid="7952052866994196170">"Selecionar ano"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selecionado"</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 35ae345..8f86b40 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Controle deslizante circular dos minutos"</string> <string name="select_hours" msgid="6043079511766008245">"Selecione as horas"</string> <string name="select_minutes" msgid="3974345615920336087">"Selecione os minutos"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Grade mensal de dias"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Lista de anos"</string> <string name="select_day" msgid="7774759604701773332">"Selecione o mês e o dia"</string> <string name="select_year" msgid="7952052866994196170">"Selecione o ano"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selecionado"</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 360b966..6246941 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -1803,8 +1803,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Selector circular pentru minute"</string> <string name="select_hours" msgid="6043079511766008245">"Selectați orele"</string> <string name="select_minutes" msgid="3974345615920336087">"Selectați minutele"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Afișare pe luni"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Listă de ani"</string> <string name="select_day" msgid="7774759604701773332">"Selectați luna și ziua"</string> <string name="select_year" msgid="7952052866994196170">"Selectați anul"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selectat"</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 5aa3b39..21cc5b7 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -1812,8 +1812,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Выбор минут на циферблате"</string> <string name="select_hours" msgid="6043079511766008245">"Выберите часы"</string> <string name="select_minutes" msgid="3974345615920336087">"Выберите минуты"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Окно выбора даты"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Меню выбора года"</string> <string name="select_day" msgid="7774759604701773332">"Выберите месяц и число"</string> <string name="select_year" msgid="7952052866994196170">"Выберите год"</string> <string name="item_is_selected" msgid="949687401682476608">"Выбран элемент <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml index 8a83db9..1b9b317 100644 --- a/core/res/res/values-si-rLK/strings.xml +++ b/core/res/res/values-si-rLK/strings.xml @@ -1796,8 +1796,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"මිනිත්තු කවාකාර සර්පනය"</string> <string name="select_hours" msgid="6043079511766008245">"පැය තෝරන්න"</string> <string name="select_minutes" msgid="3974345615920336087">"මිනිත්තු තෝරන්න"</string> - <string name="day_picker_description" msgid="8990847925961297968">"දින ජාලයකින් මාසය"</string> - <string name="year_picker_description" msgid="5524331207436052403">"වසර ලැයිස්තුව"</string> <string name="select_day" msgid="7774759604701773332">"මාසය සහ දිනය තෝරන්න"</string> <string name="select_year" msgid="7952052866994196170">"වසර තෝරන්න"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> තෝරාගෙන ඇත"</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index 676ffe2..c46fc93 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -1812,8 +1812,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Kruhový posúvač minút"</string> <string name="select_hours" msgid="6043079511766008245">"Vyberte hodiny"</string> <string name="select_minutes" msgid="3974345615920336087">"Vyberte minúty"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Tabuľka dní v mesiaci"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Zoznam rokov"</string> <string name="select_day" msgid="7774759604701773332">"Vyberte mesiac a deň"</string> <string name="select_year" msgid="7952052866994196170">"Vyberte rok"</string> <string name="item_is_selected" msgid="949687401682476608">"Bola vybratá položka <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index 07d4bb7..a42b022 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -1812,8 +1812,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Okrogli drsnik za minute"</string> <string name="select_hours" msgid="6043079511766008245">"Izberite ure"</string> <string name="select_minutes" msgid="3974345615920336087">"Izberite minute"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Mesečna mreža dni"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Seznam let"</string> <string name="select_day" msgid="7774759604701773332">"Izberite mesec in dan"</string> <string name="select_year" msgid="7952052866994196170">"Izberite leto"</string> <string name="item_is_selected" msgid="949687401682476608">"Izbrano: <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index 54da9a4..7e2f18e 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -1803,8 +1803,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Кружни клизач за минуте"</string> <string name="select_hours" msgid="6043079511766008245">"Изаберите сате"</string> <string name="select_minutes" msgid="3974345615920336087">"Изаберите минуте"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Приказ дана у месецу у виду мреже"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Листа година"</string> <string name="select_day" msgid="7774759604701773332">"Изаберите месец и дан"</string> <string name="select_year" msgid="7952052866994196170">"Изаберите годину"</string> <string name="item_is_selected" msgid="949687401682476608">"Изабрали сте <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index dd8a883..326842c 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Cirkelreglage för minuter"</string> <string name="select_hours" msgid="6043079511766008245">"Välj timmar"</string> <string name="select_minutes" msgid="3974345615920336087">"Välj minuter"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Rutnät för månad"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Lista över år"</string> <string name="select_day" msgid="7774759604701773332">"Välj månad och dag"</string> <string name="select_year" msgid="7952052866994196170">"Välj år"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> har markerats"</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index cfa56de..d681855 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Kitelezi cha mviringo wa dakika"</string> <string name="select_hours" msgid="6043079511766008245">"Chagua saa"</string> <string name="select_minutes" msgid="3974345615920336087">"Chagua dakika"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Gridi ya mwezi ya siku"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Orodha ya miaka"</string> <string name="select_day" msgid="7774759604701773332">"Chagua mwezi na siku"</string> <string name="select_year" msgid="7952052866994196170">"Chagua mwaka"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> kimechaguliwa"</string> diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml index 0e5bf3c..086fe6a 100644 --- a/core/res/res/values-ta-rIN/strings.xml +++ b/core/res/res/values-ta-rIN/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"நிமிடங்களுக்கான வட்டவடிவ ஸ்லைடர்"</string> <string name="select_hours" msgid="6043079511766008245">"மணிநேரத்தைத் தேர்ந்தெடுக்கவும்"</string> <string name="select_minutes" msgid="3974345615920336087">"நிமிடத்தைத் தேர்ந்தெடுக்கவும்"</string> - <string name="day_picker_description" msgid="8990847925961297968">"நாட்களின் மாதக் கட்டம்"</string> - <string name="year_picker_description" msgid="5524331207436052403">"ஆண்டு பட்டியல்"</string> <string name="select_day" msgid="7774759604701773332">"மாதம் மற்றும் தேதியைத் தேர்ந்தெடுக்கவும்"</string> <string name="select_year" msgid="7952052866994196170">"ஆண்டைத் தேர்ந்தெடுக்கவும்"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> தேர்ந்தெடுக்கப்பட்டது"</string> diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml index 4684adf..5f59597 100644 --- a/core/res/res/values-te-rIN/strings.xml +++ b/core/res/res/values-te-rIN/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"నిమిషాల వృత్తాకార స్లయిడర్"</string> <string name="select_hours" msgid="6043079511766008245">"గంటలను ఎంచుకోండి"</string> <string name="select_minutes" msgid="3974345615920336087">"నిమిషాలను ఎంచుకోండి"</string> - <string name="day_picker_description" msgid="8990847925961297968">"రోజుల యొక్క నెల గ్రిడ్"</string> - <string name="year_picker_description" msgid="5524331207436052403">"సంవత్సర జాబితా"</string> <string name="select_day" msgid="7774759604701773332">"నెల మరియు రోజును ఎంచుకోండి"</string> <string name="select_year" msgid="7952052866994196170">"సంవత్సరాన్ని ఎంచుకోండి"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ఎంచుకోబడింది"</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index 39be8c7..df4ff52 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"ตัวเลื่อนหมุนระบุนาที"</string> <string name="select_hours" msgid="6043079511766008245">"เลือกชั่วโมง"</string> <string name="select_minutes" msgid="3974345615920336087">"เลือกนาที"</string> - <string name="day_picker_description" msgid="8990847925961297968">"ตารางเดือนของวัน"</string> - <string name="year_picker_description" msgid="5524331207436052403">"รายการปี"</string> <string name="select_day" msgid="7774759604701773332">"เลือกเดือนและวัน"</string> <string name="select_year" msgid="7952052866994196170">"เลือกปี"</string> <string name="item_is_selected" msgid="949687401682476608">"เลือก <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 95a1480..41480ed 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Pabilog na slider ng mga minuto"</string> <string name="select_hours" msgid="6043079511766008245">"Pumili ng mga oras"</string> <string name="select_minutes" msgid="3974345615920336087">"Pumili ng mga minuto"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Grid ng mga araw ayon sa buwan"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Listahan ng taon"</string> <string name="select_day" msgid="7774759604701773332">"Pumili ng buwan at araw"</string> <string name="select_year" msgid="7952052866994196170">"Pumili ng taon"</string> <string name="item_is_selected" msgid="949687401682476608">"Napili ang <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 373ef66..f254b5c 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Dakika kaydırma çemberi"</string> <string name="select_hours" msgid="6043079511766008245">"Saati seçin"</string> <string name="select_minutes" msgid="3974345615920336087">"Dakikayı seçin"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Ayın günleri tablosu"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Yıl listesi"</string> <string name="select_day" msgid="7774759604701773332">"Ayı ve günü seçin"</string> <string name="select_year" msgid="7952052866994196170">"Yılı seçin"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> seçildi"</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index c3cfe6d..78beaf5 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -1812,8 +1812,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Вибір хвилин на циферблаті"</string> <string name="select_hours" msgid="6043079511766008245">"Виберіть години"</string> <string name="select_minutes" msgid="3974345615920336087">"Виберіть хвилини"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Вікно вибору дати"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Меню вибору року"</string> <string name="select_day" msgid="7774759604701773332">"Виберіть місяць і день"</string> <string name="select_year" msgid="7952052866994196170">"Виберіть рік"</string> <string name="item_is_selected" msgid="949687401682476608">"Вибрано: <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml index f315112..4f604aa 100644 --- a/core/res/res/values-ur-rPK/strings.xml +++ b/core/res/res/values-ur-rPK/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"منٹس سرکلر سلائیڈر"</string> <string name="select_hours" msgid="6043079511766008245">"گھنٹے منتخب کریں"</string> <string name="select_minutes" msgid="3974345615920336087">"منٹ منتخب کریں"</string> - <string name="day_picker_description" msgid="8990847925961297968">"دنوں کا ماہ کا گرڈ"</string> - <string name="year_picker_description" msgid="5524331207436052403">"سال کی فہرست"</string> <string name="select_day" msgid="7774759604701773332">"ماہ اور دن منتخب کریں"</string> <string name="select_year" msgid="7952052866994196170">"سال منتخب کریں"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> کو منتخب کیا گیا"</string> diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml index 78bad61..dc90c25 100644 --- a/core/res/res/values-uz-rUZ/strings.xml +++ b/core/res/res/values-uz-rUZ/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Doiradan daqiqani tanlang"</string> <string name="select_hours" msgid="6043079511766008245">"Soatlarni tanlash"</string> <string name="select_minutes" msgid="3974345615920336087">"Daqiqalarni tanlash"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Oy kunlari (jadval ko‘rinishida)"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Yil ro‘yxati"</string> <string name="select_day" msgid="7774759604701773332">"Oy va kunni tanlash"</string> <string name="select_year" msgid="7952052866994196170">"Yilni tanlash"</string> <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> tanlandi"</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index a2ebfd4..5031e85 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Thanh trượt phút hình tròn"</string> <string name="select_hours" msgid="6043079511766008245">"Chọn giờ"</string> <string name="select_minutes" msgid="3974345615920336087">"Chọn phút"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Lưới ngày theo tháng"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Danh sách năm"</string> <string name="select_day" msgid="7774759604701773332">"Chọn tháng và ngày"</string> <string name="select_year" msgid="7952052866994196170">"Chọn năm"</string> <string name="item_is_selected" msgid="949687401682476608">"Đã chọn <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index e7c6bee..d8631a6 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"分钟转盘"</string> <string name="select_hours" msgid="6043079511766008245">"选择小时"</string> <string name="select_minutes" msgid="3974345615920336087">"选择分钟"</string> - <string name="day_picker_description" msgid="8990847925961297968">"按月份划分的日期网格"</string> - <string name="year_picker_description" msgid="5524331207436052403">"年份列表"</string> <string name="select_day" msgid="7774759604701773332">"选择月份和日期"</string> <string name="select_year" msgid="7952052866994196170">"选择年份"</string> <string name="item_is_selected" msgid="949687401682476608">"已选择<xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index a62cf11..9b9e945 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"分鐘環形滑桿"</string> <string name="select_hours" msgid="6043079511766008245">"選取小時"</string> <string name="select_minutes" msgid="3974345615920336087">"選取分鐘"</string> - <string name="day_picker_description" msgid="8990847925961297968">"顯示每日的月曆方格"</string> - <string name="year_picker_description" msgid="5524331207436052403">"年份清單"</string> <string name="select_day" msgid="7774759604701773332">"選取月份和日期"</string> <string name="select_year" msgid="7952052866994196170">"選取年份"</string> <string name="item_is_selected" msgid="949687401682476608">"已選取<xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 5d1821a..323ccc3 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"分鐘數環狀滑桿"</string> <string name="select_hours" msgid="6043079511766008245">"選取小時數"</string> <string name="select_minutes" msgid="3974345615920336087">"選取分鐘數"</string> - <string name="day_picker_description" msgid="8990847925961297968">"日期網格 (按月顯示)"</string> - <string name="year_picker_description" msgid="5524331207436052403">"年份清單"</string> <string name="select_day" msgid="7774759604701773332">"選取月份和日期"</string> <string name="select_year" msgid="7952052866994196170">"選取年份"</string> <string name="item_is_selected" msgid="949687401682476608">"已選取 <xliff:g id="ITEM">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index 4c3a400..ec68b17 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -1794,8 +1794,6 @@ <string name="minute_picker_description" msgid="8606010966873791190">"Amaminithi weslayidi esiyindingilizi"</string> <string name="select_hours" msgid="6043079511766008245">"Khetha amahora"</string> <string name="select_minutes" msgid="3974345615920336087">"Khetha amaminithi"</string> - <string name="day_picker_description" msgid="8990847925961297968">"Igridi yenyanga yezinsuku"</string> - <string name="year_picker_description" msgid="5524331207436052403">"Uhlu lonyaka"</string> <string name="select_day" msgid="7774759604701773332">"Khetha inyanga nosuku"</string> <string name="select_year" msgid="7952052866994196170">"Khetha unyaka"</string> <string name="item_is_selected" msgid="949687401682476608">"I-<xliff:g id="ITEM">%1$s</xliff:g> ekhethiwe"</string> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index b5576c5..79a6bde 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2633,6 +2633,70 @@ <enum name="paddedBounds" value="3" /> </attr> + <!-- Defines the drawable to draw over the content. This can be used as an overlay. + The foreground drawable participates in the padding of the content if the gravity + is set to fill. --> + <attr name="foreground" format="reference|color" /> + <!-- Defines the gravity to apply to the foreground drawable. The gravity defaults + to fill. --> + <attr name="foregroundGravity"> + <!-- Push object to the top of its container, not changing its size. --> + <flag name="top" value="0x30" /> + <!-- Push object to the bottom of its container, not changing its size. --> + <flag name="bottom" value="0x50" /> + <!-- Push object to the left of its container, not changing its size. --> + <flag name="left" value="0x03" /> + <!-- Push object to the right of its container, not changing its size. --> + <flag name="right" value="0x05" /> + <!-- Place object in the vertical center of its container, not changing its size. --> + <flag name="center_vertical" value="0x10" /> + <!-- Grow the vertical size of the object if needed so it completely fills its container. --> + <flag name="fill_vertical" value="0x70" /> + <!-- Place object in the horizontal center of its container, not changing its size. --> + <flag name="center_horizontal" value="0x01" /> + <!-- Grow the horizontal size of the object if needed so it completely fills its container. --> + <flag name="fill_horizontal" value="0x07" /> + <!-- Place the object in the center of its container in both the vertical and horizontal axis, not changing its size. --> + <flag name="center" value="0x11" /> + <!-- Grow the horizontal and vertical size of the object if needed so it completely fills its container. --> + <flag name="fill" value="0x77" /> + <!-- Additional option that can be set to have the top and/or bottom edges of + the child clipped to its container's bounds. + The clip will be based on the vertical gravity: a top gravity will clip the bottom + edge, a bottom gravity will clip the top edge, and neither will clip both edges. --> + <flag name="clip_vertical" value="0x80" /> + <!-- Additional option that can be set to have the left and/or right edges of + the child clipped to its container's bounds. + The clip will be based on the horizontal gravity: a left gravity will clip the right + edge, a right gravity will clip the left edge, and neither will clip both edges. --> + <flag name="clip_horizontal" value="0x08" /> + </attr> + <!-- Defines whether the foreground drawable should be drawn inside the padding. + This property is turned on by default. --> + <attr name="foregroundInsidePadding" format="boolean" /> + <!-- Tint to apply to the foreground. --> + <attr name="foregroundTint" format="color" /> + <!-- Blending mode used to apply the foreground tint. --> + <attr name="foregroundTintMode"> + <!-- The tint is drawn on top of the drawable. + [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] --> + <enum name="src_over" value="3" /> + <!-- The tint is masked by the alpha channel of the drawable. The drawable’s + color channels are thrown out. [Sa * Da, Sc * Da] --> + <enum name="src_in" value="5" /> + <!-- The tint is drawn above the drawable, but with the drawable’s alpha + channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] --> + <enum name="src_atop" value="9" /> + <!-- Multiplies the color and alpha channels of the drawable with those of + the tint. [Sa * Da, Sc * Dc] --> + <enum name="multiply" value="14" /> + <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] --> + <enum name="screen" value="15" /> + <!-- Combines the tint and drawable color and alpha channels, clamping the + result to valid color values. Saturate(S + D) --> + <enum name="add" value="16" /> + </attr> + </declare-styleable> <!-- Attributes that can be assigned to a tag for a particular View. --> @@ -3366,72 +3430,9 @@ <attr name="padding" /> </declare-styleable> <declare-styleable name="FrameLayout"> - <!-- Defines the drawable to draw over the content. This can be used as an overlay. - The foreground drawable participates in the padding of the content if the gravity - is set to fill. --> - <attr name="foreground" format="reference|color" /> - <!-- Defines the gravity to apply to the foreground drawable. The gravity defaults - to fill. --> - <attr name="foregroundGravity"> - <!-- Push object to the top of its container, not changing its size. --> - <flag name="top" value="0x30" /> - <!-- Push object to the bottom of its container, not changing its size. --> - <flag name="bottom" value="0x50" /> - <!-- Push object to the left of its container, not changing its size. --> - <flag name="left" value="0x03" /> - <!-- Push object to the right of its container, not changing its size. --> - <flag name="right" value="0x05" /> - <!-- Place object in the vertical center of its container, not changing its size. --> - <flag name="center_vertical" value="0x10" /> - <!-- Grow the vertical size of the object if needed so it completely fills its container. --> - <flag name="fill_vertical" value="0x70" /> - <!-- Place object in the horizontal center of its container, not changing its size. --> - <flag name="center_horizontal" value="0x01" /> - <!-- Grow the horizontal size of the object if needed so it completely fills its container. --> - <flag name="fill_horizontal" value="0x07" /> - <!-- Place the object in the center of its container in both the vertical and horizontal axis, not changing its size. --> - <flag name="center" value="0x11" /> - <!-- Grow the horizontal and vertical size of the object if needed so it completely fills its container. --> - <flag name="fill" value="0x77" /> - <!-- Additional option that can be set to have the top and/or bottom edges of - the child clipped to its container's bounds. - The clip will be based on the vertical gravity: a top gravity will clip the bottom - edge, a bottom gravity will clip the top edge, and neither will clip both edges. --> - <flag name="clip_vertical" value="0x80" /> - <!-- Additional option that can be set to have the left and/or right edges of - the child clipped to its container's bounds. - The clip will be based on the horizontal gravity: a left gravity will clip the right - edge, a right gravity will clip the left edge, and neither will clip both edges. --> - <flag name="clip_horizontal" value="0x08" /> - </attr> - <!-- Defines whether the foreground drawable should be drawn inside the padding. - This property is turned on by default. --> - <attr name="foregroundInsidePadding" format="boolean" /> <!-- Determines whether to measure all children or just those in the VISIBLE or INVISIBLE state when measuring. Defaults to false. --> <attr name="measureAllChildren" format="boolean" /> - <!-- Tint to apply to the foreground. --> - <attr name="foregroundTint" format="color" /> - <!-- Blending mode used to apply the foreground tint. --> - <attr name="foregroundTintMode"> - <!-- The tint is drawn on top of the drawable. - [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] --> - <enum name="src_over" value="3" /> - <!-- The tint is masked by the alpha channel of the drawable. The drawable’s - color channels are thrown out. [Sa * Da, Sc * Da] --> - <enum name="src_in" value="5" /> - <!-- The tint is drawn above the drawable, but with the drawable’s alpha - channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] --> - <enum name="src_atop" value="9" /> - <!-- Multiplies the color and alpha channels of the drawable with those of - the tint. [Sa * Da, Sc * Dc] --> - <enum name="multiply" value="14" /> - <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] --> - <enum name="screen" value="15" /> - <!-- Combines the tint and drawable color and alpha channels, clamping the - result to valid color values. Saturate(S + D) --> - <enum name="add" value="16" /> - </attr> </declare-styleable> <declare-styleable name="ExpandableListView"> <!-- Indicator shown beside the group View. This can be a stateful Drawable. --> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index aefb67c..283c237 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -389,13 +389,12 @@ with the same {@link android.R.attr#taskAffinity} as it has. --> <attr name="allowTaskReparenting" format="boolean" /> - <!-- Declare that this application may use cleartext traffic (e.g., HTTP rather than HTTPS; - WebSockets rather than WebSockets Secure; XMPP, IMAP, STMP without STARTTLS or TLS). - Defaults to true. If set to false {@code false}, the app declares that it does not - intend to use cleartext network traffic, in which case platform components (e.g., - HTTP stacks, {@code WebView}, {@code MediaPlayer}) will refuse app's requests to use - cleartext traffic. Third-party libraries are encouraged to honor this flag as well. - @hide --> + <!-- Declare that this application may use cleartext traffic, such as HTTP rather than HTTPS; + WebSockets rather than WebSockets Secure; XMPP, IMAP, STMP without STARTTLS or TLS. + Defaults to true. If set to false {@code false}, the application declares that it does not + intend to use cleartext network traffic, in which case platform components (e.g. HTTP + stacks, {@code WebView}, {@code MediaPlayer}) will refuse applications's requests to use + cleartext traffic. Third-party libraries are encouraged to honor this flag as well. --> <attr name="usesCleartextTraffic" format="boolean" /> <!-- Declare that code from this application will need to be loaded into other @@ -1164,13 +1163,13 @@ "com.google". --> <attr name="requiredAccountType" format="string"/> <attr name="isGame" /> - <!-- Declare that this application may use cleartext traffic (e.g., HTTP rather than HTTPS; - WebSockets rather than WebSockets Secure; XMPP, IMAP, STMP without STARTTLS or TLS). - Defaults to true. If set to false {@code false}, the app declares that it does not - intend to use cleartext network traffic, in which case platform components (e.g., - HTTP stacks, {@code WebView}, {@code MediaPlayer}) will refuse app's requests to use - cleartext traffic. Third-party libraries are encouraged to honor this flag as well. - @hide --> + <!-- Declare that this application may use cleartext traffic, such as HTTP rather than + HTTPS; WebSockets rather than WebSockets Secure; XMPP, IMAP, STMP without STARTTLS or + TLS). Defaults to true. If set to false {@code false}, the application declares that it + does not intend to use cleartext network traffic, in which case platform components + (e.g. HTTP stacks, {@code WebView}, {@code MediaPlayer}) will refuse applications's + requests to use cleartext traffic. Third-party libraries are encouraged to honor this + flag as well. --> <attr name="usesCleartextTraffic" /> <attr name="multiArch" /> <attr name="extractNativeLibs" /> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 37c9598..1b2e952 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1112,6 +1112,18 @@ device does not support multiple advertisement--> <integer translatable="false" name="config_bluetooth_max_advertisers">0</integer> + <!-- Idle current for bluetooth controller. 0 by default--> + <integer translatable="false" name="config_bluetooth_idle_cur_ma">1</integer> + + <!-- Rx current for bluetooth controller. 0 by default--> + <integer translatable="false" name="config_bluetooth_rx_cur_ma">2</integer> + + <!-- Tx current for bluetooth controller. 0 by default--> + <integer translatable="false" name="config_bluetooth_tx_cur_ma">3</integer> + + <!-- Operating volatage for bluetooth controller. 0 by default--> + <integer translatable="false" name="config_bluetooth_operating_voltage_mv">4</integer> + <!-- The default data-use polling period. --> <integer name="config_datause_polling_period_sec">600</integer> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 6c6d2cc..3431f35 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -386,4 +386,11 @@ <item type="dimen" format="float" name="ambient_shadow_alpha">0.075</item> <item type="dimen" format="float" name="spot_shadow_alpha">0.15</item> + <!-- Floating toolbar dimensions --> + <dimen name="floating_toolbar_height">48dp</dimen> + <dimen name="floating_toolbar_menu_button_side_padding">8dp</dimen> + <dimen name="floating_toolbar_text_size">14sp</dimen> + <dimen name="floating_toolbar_menu_button_minimum_width">48dp</dimen> + <dimen name="floating_toolbar_default_width">250dp</dimen> + <dimen name="floating_toolbar_minimum_overflow_height">192dp</dimen> </resources> diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml index 6108b27..7e963954 100644 --- a/core/res/res/values/ids.xml +++ b/core/res/res/values/ids.xml @@ -93,4 +93,5 @@ <item type="id" name="undo" /> <item type="id" name="redo" /> <item type="id" name="replaceText" /> + <item type="id" name="accessibility_action_show_on_screen" /> </resources> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 5e4b039..ef7bfaf 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2652,4 +2652,5 @@ <public type="attr" name="colorBackgroundFloating" /> <public type="attr" name="extractNativeLibs" /> + <public type="attr" name="usesCleartextTraffic" /> </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 7672e93..88225bd 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -251,6 +251,8 @@ <string-array name="wfcOperatorErrorCodes" translatable="false" /> <!-- WFC Operator Error Messages --> <string-array name="wfcOperatorErrorMessages" /> + <!-- Template for showing cellular network operator name while WFC is active --> + <string name="wfcSpnFormat">%s</string> <!-- {0} is one of "bearerServiceCode*" @@ -2226,6 +2228,36 @@ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_useFingerprint">Allows the app to use fingerprint hardware for authentication</string> + <!-- Message shown during fingerprint acquisision when the fingerprint cannot be recognized --> + <string name="fingerprint_acquired_partial">Partial fingerprint detected. Please try again.</string> + <!-- Message shown during fingerprint acquisision when the fingerprint cannot be recognized --> + <string name="fingerprint_acquired_insufficient">Couldn\'t process fingerprint. Please try again.</string> + <!-- Message shown during fingerprint acquisision when the fingerprint sensor needs cleaning --> + <string name="fingerprint_acquired_imager_dirty">Fingerprint sensor is dirty. Please clean and try again.</string> + <!-- Message shown during fingerprint acquisision when the user removes their finger from the sensor too quickly --> + <string name="fingerprint_acquired_too_fast">Finger moved to fast. Please try again.</string> + <!-- Message shown during fingerprint acquisision when the user moves their finger too slowly --> + <string name="fingerprint_acquired_too_slow">Finger moved to slow. Please try again.</string> + <!-- Array containing custom messages shown during fingerprint acquisision from vendor. Vendor is expected to add and translate these strings --> + <string-array name="fingerprint_acquired_vendor"> + <item>Vendor-specific acquisition error message 0</item> + </string-array> + + <!-- Generic error message shown when the fingerprint hardware can't recognize the fingerprint --> + <string name="fingerprint_error_unable_to_process">Unable to process. Try again.</string> + <!-- Error message shown when the fingerprint hardware can't be accessed --> + <string name="fingerprint_error_hw_not_available">Hardware not available.</string> + <!-- Error message shown when the fingerprint hardware has run out of room for storing fingerprints --> + <string name="fingerprint_error_no_space">Fingerprint can\'t be stored. Please remove an existing fingerprint.</string> + <!-- Error message shown when the fingerprint hardware timer has expired and the user needs to restart the operation. --> + <string name="fingerprint_error_timeout">Fingerprint time out reached. Try again.</string> + <!-- Error message shown when the fingerprint hardware timer has expired and the user needs to restart the operation. --> + <string name="fingerprint_error_vendor">Fingerprint time out reached. Try again.</string> + <!-- Array containing custom error messages from vendor. Vendor is expected to add and translate these strings --> + <string-array name="fingerprint_error_vendor"> + <item>Vendor-specifc error message.</item> + </string-array> + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_readSyncSettings">read sync settings</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index c4e9e8e..67d5472 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -349,6 +349,10 @@ <java-symbol type="integer" name="config_burnInProtectionMinVerticalOffset" /> <java-symbol type="integer" name="config_burnInProtectionMaxVerticalOffset" /> <java-symbol type="integer" name="config_burnInProtectionMaxRadius" /> + <java-symbol type="integer" name="config_bluetooth_idle_cur_ma" /> + <java-symbol type="integer" name="config_bluetooth_rx_cur_ma" /> + <java-symbol type="integer" name="config_bluetooth_tx_cur_ma" /> + <java-symbol type="integer" name="config_bluetooth_operating_voltage_mv" /> <java-symbol type="integer" name="config_cursorWindowSize" /> <java-symbol type="integer" name="config_drawLockTimeoutMillis" /> <java-symbol type="integer" name="config_doublePressOnPowerBehavior" /> @@ -756,6 +760,7 @@ <java-symbol type="string" name="wfcRegErrorTitle" /> <java-symbol type="array" name="wfcOperatorErrorCodes" /> <java-symbol type="array" name="wfcOperatorErrorMessages" /> + <java-symbol type="string" name="wfcSpnFormat" /> <java-symbol type="string" name="policydesc_disableCamera" /> <java-symbol type="string" name="policydesc_encryptedStorage" /> <java-symbol type="string" name="policydesc_expirePassword" /> @@ -2061,6 +2066,19 @@ <!-- From KeyguardServiceDelegate --> <java-symbol type="string" name="config_keyguardComponent" /> + <!-- Fingerprint messages --> + <java-symbol type="string" name="fingerprint_error_unable_to_process" /> + <java-symbol type="string" name="fingerprint_error_hw_not_available" /> + <java-symbol type="string" name="fingerprint_error_no_space" /> + <java-symbol type="string" name="fingerprint_error_timeout" /> + <java-symbol type="array" name="fingerprint_error_vendor" /> + <java-symbol type="string" name="fingerprint_acquired_partial" /> + <java-symbol type="string" name="fingerprint_acquired_insufficient" /> + <java-symbol type="string" name="fingerprint_acquired_imager_dirty" /> + <java-symbol type="string" name="fingerprint_acquired_too_slow" /> + <java-symbol type="string" name="fingerprint_acquired_too_fast" /> + <java-symbol type="array" name="fingerprint_acquired_vendor" /> + <!-- From various Material changes --> <java-symbol type="attr" name="titleTextAppearance" /> <java-symbol type="attr" name="subtitleTextAppearance" /> @@ -2174,4 +2192,17 @@ <java-symbol type="style" name="TextAppearance.Material.Widget.Calendar.Day" /> <java-symbol type="dimen" name="day_picker_padding_top"/> <java-symbol type="dimen" name="date_picker_day_of_week_height"/> + + <java-symbol type="id" name="accessibility_action_show_on_screen" /> + + <!-- Floating toolbar --> + <java-symbol type="layout" name="floating_popup_container" /> + <java-symbol type="layout" name="floating_popup_menu_button" /> + <java-symbol type="layout" name="floating_popup_open_overflow_button" /> + <java-symbol type="dimen" name="floating_toolbar_height" /> + <java-symbol type="dimen" name="floating_toolbar_menu_button_side_padding" /> + <java-symbol type="dimen" name="floating_toolbar_text_size" /> + <java-symbol type="dimen" name="floating_toolbar_menu_button_minimum_width" /> + <java-symbol type="dimen" name="floating_toolbar_default_width" /> + <java-symbol type="dimen" name="floating_toolbar_minimum_overflow_height" /> </resources> diff --git a/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java new file mode 100644 index 0000000..1a50432 --- /dev/null +++ b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java @@ -0,0 +1,82 @@ +/* + * 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.net; + +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; + +public class NetworkStatsBenchmark extends SimpleBenchmark { + private static final String UNDERLYING_IFACE = "wlan0"; + private static final String TUN_IFACE = "tun0"; + private static final int TUN_UID = 999999999; + + @Param({"100", "1000"}) + private int mSize; + private NetworkStats mNetworkStats; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + mNetworkStats = new NetworkStats(0, mSize + 2); + int uid = 0; + NetworkStats.Entry recycle = new NetworkStats.Entry(); + for (int i = 0; i < mSize; i++) { + recycle.iface = (i < mSize / 2) ? TUN_IFACE : UNDERLYING_IFACE; + recycle.uid = uid; + recycle.set = i % 2; + recycle.tag = NetworkStats.TAG_NONE; + recycle.rxBytes = 60000; + recycle.rxPackets = 60; + recycle.txBytes = 150000; + recycle.txPackets = 1500; + recycle.operations = 0; + mNetworkStats.addValues(recycle); + if (recycle.set == 1) { + uid++; + } + } + recycle.iface = UNDERLYING_IFACE; + recycle.uid = TUN_UID; + recycle.set = NetworkStats.SET_FOREGROUND; + recycle.tag = NetworkStats.TAG_NONE; + recycle.rxBytes = 90000 * mSize; + recycle.rxPackets = 40 * mSize; + recycle.txBytes = 180000 * mSize; + recycle.txPackets = 1200 * mSize; + recycle.operations = 0; + mNetworkStats.addValues(recycle); + } + + public void timeMigrateTun(int reps) { + for (int i = 0; i < reps; i++) { + NetworkStats stats = mNetworkStats.clone(); + stats.migrateTun(TUN_UID, TUN_IFACE, UNDERLYING_IFACE); + } + } + + /** + * Since timeMigrateTun() includes a clone() call on the NetworkStats object, + * we need to measure the cost of the clone() call itself in order to get more + * accurate measurement on the migrateTun() method. + */ + public void timeClone(int reps) { + for (int i = 0; i < reps; i++) { + NetworkStats stats = mNetworkStats.clone(); + } + } +} diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java index fd922a2..a470de1 100644 --- a/core/tests/coretests/src/android/net/NetworkStatsTest.java +++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java @@ -18,6 +18,8 @@ package android.net; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; +import static android.net.NetworkStats.SET_DBG_VPN_IN; +import static android.net.NetworkStats.SET_DBG_VPN_OUT; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.TAG_NONE; @@ -346,7 +348,7 @@ public class NetworkStatsTest extends TestCase { .addValues(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L); assertTrue(delta.migrateTun(tunUid, tunIface, underlyingIface)); - assertEquals(17, delta.size()); + assertEquals(21, delta.size()); // tunIface and TEST_IFACE entries are not changed. assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, @@ -377,14 +379,33 @@ public class NetworkStatsTest extends TestCase { 0L, 0L, 0L, 0L, 0L); // New entries are added for new application's underlying Iface traffic - assertValues(delta, 13, underlyingIface, 10120, SET_DEFAULT, TAG_NONE, + assertContains(delta, underlyingIface, 10120, SET_DEFAULT, TAG_NONE, 72667L, 197L, 41872l, 219L, 0L); - assertValues(delta, 14, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE, + assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE, 9297L, 17L, 3936, 19L, 0L); - assertValues(delta, 15, underlyingIface, 10120, SET_DEFAULT, testTag1, + assertContains(delta, underlyingIface, 10120, SET_DEFAULT, testTag1, 21691L, 41L, 13179L, 46L, 0L); - assertValues(delta, 16, underlyingIface, 10120, SET_FOREGROUND, testTag1, + assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, testTag1, 1281L, 2L, 634L, 1L, 0L); + + // New entries are added for debug purpose + assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, + 39605L, 46L, 11690, 49, 0); + assertContains(delta, underlyingIface, 10120, SET_DBG_VPN_IN, TAG_NONE, + 81964, 214, 45808, 238, 0); + assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_IN, TAG_NONE, + 4983, 10, 1717, 10, 0); + assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, + 126552, 270, 59215, 297, 0); + + } + + private static void assertContains(NetworkStats stats, String iface, int uid, int set, + int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { + int index = stats.findIndex(iface, uid, set, tag); + assertTrue(index != -1); + assertValues(stats, index, iface, uid, set, tag, + rxBytes, rxPackets, txBytes, txPackets, operations); } private static void assertValues(NetworkStats stats, int index, String iface, int uid, int set, |
