Merge "Fixing AVD animation with startOffset" into lmp-dev
diff --git a/Android.mk b/Android.mk
index 80b860b..6280332 100644
--- a/Android.mk
+++ b/Android.mk
@@ -156,6 +156,7 @@
core/java/android/hardware/hdmi/IHdmiDeviceEventListener.aidl \
core/java/android/hardware/hdmi/IHdmiHotplugEventListener.aidl \
core/java/android/hardware/hdmi/IHdmiInputChangeListener.aidl \
+ core/java/android/hardware/hdmi/IHdmiMhlScratchpadCommandListener.aidl \
core/java/android/hardware/hdmi/IHdmiRecordListener.aidl \
core/java/android/hardware/hdmi/IHdmiSystemAudioModeChangeListener.aidl \
core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index c7cf940..547ec6c 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -221,6 +221,8 @@
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services.core_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/inputflinger $(PRODUCT_OUT)/symbols/system/bin/inputflinger)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/RsFountainFbo_intermediates)
# ******************************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
diff --git a/api/current.txt b/api/current.txt
index 8f75785..dfa95a0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -309,6 +309,7 @@
field public static final int addStatesFromChildren = 16842992; // 0x10100f0
field public static final int adjustViewBounds = 16843038; // 0x101011e
field public static final int advancedPrintOptionsActivity = 16843761; // 0x10103f1
+ field public static final int ageHint = 16843962; // 0x10104ba
field public static final int alertDialogIcon = 16843605; // 0x1010355
field public static final int alertDialogStyle = 16842845; // 0x101005d
field public static final int alertDialogTheme = 16843529; // 0x1010309
@@ -467,6 +468,7 @@
field public static final int controlX2 = 16843800; // 0x1010418
field public static final int controlY1 = 16843799; // 0x1010417
field public static final int controlY2 = 16843801; // 0x1010419
+ field public static final int country = 16843963; // 0x10104bb
field public static final int cropToPadding = 16843043; // 0x1010123
field public static final int cursorVisible = 16843090; // 0x1010152
field public static final int customNavigationLayout = 16843474; // 0x10102d2
@@ -929,6 +931,7 @@
field public static final int orderingFromXml = 16843239; // 0x10101e7
field public static final int orientation = 16842948; // 0x10100c4
field public static final int outAnimation = 16843128; // 0x1010178
+ field public static final int outlineProvider = 16843961; // 0x10104b9
field public static final int overScrollFooter = 16843459; // 0x10102c3
field public static final int overScrollHeader = 16843458; // 0x10102c2
field public static final int overScrollMode = 16843457; // 0x10102c1
@@ -1025,6 +1028,8 @@
field public static final int readPermission = 16842759; // 0x1010007
field public static final int recognitionService = 16843932; // 0x101049c
field public static final int relinquishTaskIdentity = 16843894; // 0x1010476
+ field public static final int reparent = 16843965; // 0x10104bd
+ field public static final int reparentWithOverlay = 16843966; // 0x10104be
field public static final int repeatCount = 16843199; // 0x10101bf
field public static final int repeatMode = 16843200; // 0x10101c0
field public static final int reqFiveWayNav = 16843314; // 0x1010232
@@ -1442,6 +1447,7 @@
field public static final int windowSharedElementExitTransition = 16843834; // 0x101043a
field public static final int windowSharedElementReenterTransition = 16843954; // 0x10104b2
field public static final int windowSharedElementReturnTransition = 16843953; // 0x10104b1
+ field public static final int windowSharedElementsUseOverlay = 16843964; // 0x10104bc
field public static final int windowShowAnimation = 16842934; // 0x10100b6
field public static final int windowShowWallpaper = 16843410; // 0x1010292
field public static final int windowSoftInputMode = 16843307; // 0x101022b
@@ -3592,8 +3598,11 @@
}
public class ActivityManager {
+ method public int addAppTask(android.app.Activity, android.content.Intent, android.app.ActivityManager.TaskDescription, android.graphics.Bitmap);
method public boolean clearApplicationUserData();
method public void dumpPackageState(java.io.FileDescriptor, java.lang.String);
+ method public int getAppTaskThumbnailHeight();
+ method public int getAppTaskThumbnailWidth();
method public java.util.List<android.app.ActivityManager.AppTask> getAppTasks();
method public android.content.pm.ConfigurationInfo getDeviceConfigurationInfo();
method public int getLargeMemoryClass();
@@ -3627,6 +3636,7 @@
public static class ActivityManager.AppTask {
method public void finishAndRemoveTask();
method public android.app.ActivityManager.RecentTaskInfo getTaskInfo();
+ method public void setExcludeFromRecents(boolean);
}
public static class ActivityManager.MemoryInfo implements android.os.Parcelable {
@@ -5409,7 +5419,6 @@
method public java.lang.String[] getAccountTypesWithManagementDisabled();
method public java.util.List<android.content.ComponentName> getActiveAdmins();
method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String);
- method public boolean getBlockUninstall(android.content.ComponentName, java.lang.String);
method public boolean getCameraDisabled(android.content.ComponentName);
method public boolean getCrossProfileCallerIdDisabled(android.content.ComponentName);
method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName);
@@ -5430,10 +5439,13 @@
method public int getPasswordMinimumSymbols(android.content.ComponentName);
method public int getPasswordMinimumUpperCase(android.content.ComponentName);
method public int getPasswordQuality(android.content.ComponentName);
+ method public java.util.List<java.lang.String> getPermittedAccessibilityServices(android.content.ComponentName);
+ method public java.util.List<java.lang.String> getPermittedInputMethods(android.content.ComponentName);
method public boolean getScreenCaptureDisabled(android.content.ComponentName);
method public boolean getStorageEncryption(android.content.ComponentName);
method public int getStorageEncryptionStatus();
method public java.util.List<java.lang.String> getTrustAgentFeaturesEnabled(android.content.ComponentName, android.content.ComponentName);
+ method public boolean getUninstallBlocked(android.content.ComponentName, java.lang.String);
method public boolean hasCaCertInstalled(byte[]);
method public boolean hasGrantedPolicy(android.content.ComponentName, int);
method public boolean installCaCert(android.content.ComponentName, byte[]);
@@ -5452,8 +5464,6 @@
method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean);
method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
- method public int setApplicationsHidden(android.content.ComponentName, android.content.Intent, boolean);
- method public void setBlockUninstall(android.content.ComponentName, java.lang.String, boolean);
method public void setCameraDisabled(android.content.ComponentName, boolean);
method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
@@ -5472,6 +5482,8 @@
method public void setPasswordMinimumSymbols(android.content.ComponentName, int);
method public void setPasswordMinimumUpperCase(android.content.ComponentName, int);
method public void setPasswordQuality(android.content.ComponentName, int);
+ method public boolean setPermittedAccessibilityServices(android.content.ComponentName, java.util.List<java.lang.String>);
+ method public boolean setPermittedInputMethods(android.content.ComponentName, java.util.List<java.lang.String>);
method public void setProfileEnabled(android.content.ComponentName);
method public void setProfileName(android.content.ComponentName, java.lang.String);
method public void setRecommendedGlobalProxy(android.content.ComponentName, android.net.ProxyInfo);
@@ -5480,6 +5492,7 @@
method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public int setStorageEncryption(android.content.ComponentName, boolean);
method public void setTrustAgentFeaturesEnabled(android.content.ComponentName, android.content.ComponentName, java.util.List<java.lang.String>);
+ method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean);
method public boolean switchUser(android.content.ComponentName, android.os.UserHandle);
method public void uninstallAllUserCaCerts(android.content.ComponentName);
method public void uninstallCaCert(android.content.ComponentName, byte[]);
@@ -5494,23 +5507,23 @@
field public static final int ENCRYPTION_STATUS_UNSUPPORTED = 0; // 0x0
field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
- field public static final java.lang.String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME = "android.app.extra.defaultManagedProfileName";
- field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.deviceAdminPackageChecksum";
- field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.deviceAdminPackageDownloadCookieHeader";
- field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.deviceAdminPackageDownloadLocation";
- field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.deviceAdminPackageName";
- field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.ManagedProfileEmailAddress";
- field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.locale";
- field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.localTime";
- field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.timeZone";
- field public static final java.lang.String EXTRA_PROVISIONING_WIFI_HIDDEN = "android.app.extra.wifiHidden";
- field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PAC_URL = "android.app.extra.wifiPacUrl";
- field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PASSWORD = "android.app.extra.wifiPassword";
- field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_BYPASS = "android.app.extra.wifiProxyBypassHosts";
- field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_HOST = "android.app.extra.wifiProxyHost";
- field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_PORT = "android.app.extra.wifiProxyPort";
- field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE = "android.app.extra.wifiSecurityType";
- field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SSID = "android.app.extra.wifiSsid";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME = "android.app.extra.DEFAULT_MANAGED_PROFILE_NAME";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.DEVICE_ADMIN_PACKAGE_CHECKSUM";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.DEVICE_ADMIN_PACKAGE_NAME";
+ field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.MANAGED_PROFILE_EMAIL_ADDRESS";
+ field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.LOCALE";
+ field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.LOCAL_TIME";
+ field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.TIME_ZONE";
+ field public static final java.lang.String EXTRA_PROVISIONING_WIFI_HIDDEN = "android.app.extra.WIFI_HIDDEN";
+ field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PAC_URL = "android.app.extra.WIFI_PAC_URL";
+ field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PASSWORD = "android.app.extra.WIFI_PASSWORD";
+ field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_BYPASS = "android.app.extra.WIFI_PROXY_BYPASS_HOSTS";
+ field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_HOST = "android.app.extra.WIFI_PROXY_HOST";
+ field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_PORT = "android.app.extra.WIFI_PROXY_PORT";
+ field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE = "android.app.extra.WIFI_SECURITY_TYPE";
+ field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SSID = "android.app.extra.WIFI_SSID";
field public static int FLAG_MANAGED_CAN_ACCESS_PARENT;
field public static int FLAG_PARENT_CAN_ACCESS_MANAGED;
field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff
@@ -5521,6 +5534,7 @@
field public static final int KEYGUARD_DISABLE_TRUST_AGENTS = 16; // 0x10
field public static final int KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS = 8; // 0x8
field public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 1; // 0x1
+ field public static final java.lang.String MIME_TYPE_PROVISIONING_NFC = "application/com.android.managedprovisioning";
field public static final int PASSWORD_QUALITY_ALPHABETIC = 262144; // 0x40000
field public static final int PASSWORD_QUALITY_ALPHANUMERIC = 327680; // 0x50000
field public static final int PASSWORD_QUALITY_BIOMETRIC_WEAK = 32768; // 0x8000
@@ -5529,7 +5543,6 @@
field public static final int PASSWORD_QUALITY_NUMERIC_COMPLEX = 196608; // 0x30000
field public static final int PASSWORD_QUALITY_SOMETHING = 65536; // 0x10000
field public static final int PASSWORD_QUALITY_UNSPECIFIED = 0; // 0x0
- field public static final java.lang.String PROVISIONING_NFC_MIME_TYPE = "application/com.android.managedprovisioning";
field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1
}
@@ -6319,7 +6332,6 @@
method public deprecated void abortReliableWrite(android.bluetooth.BluetoothDevice);
method public boolean beginReliableWrite();
method public void close();
- method public boolean configureMTU(int);
method public boolean connect();
method public void disconnect();
method public boolean discoverServices();
@@ -6333,14 +6345,15 @@
method public boolean readCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
method public boolean readDescriptor(android.bluetooth.BluetoothGattDescriptor);
method public boolean readRemoteRssi();
- method public boolean requestConnectionParameterUpdate(int);
+ method public boolean requestConnectionPriority(int);
+ method public boolean requestMtu(int);
method public boolean setCharacteristicNotification(android.bluetooth.BluetoothGattCharacteristic, boolean);
method public boolean writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
method public boolean writeDescriptor(android.bluetooth.BluetoothGattDescriptor);
- field public static final int GATT_CONNECTION_BALANCED = 0; // 0x0
+ field public static final int CONNECTION_PRIORITY_BALANCED = 0; // 0x0
+ field public static final int CONNECTION_PRIORITY_HIGH = 1; // 0x1
+ field public static final int CONNECTION_PRIORITY_LOW_POWER = 2; // 0x2
field public static final int GATT_CONNECTION_CONGESTED = 143; // 0x8f
- field public static final int GATT_CONNECTION_HIGH_PRIORITY = 1; // 0x1
- field public static final int GATT_CONNECTION_LOW_POWER = 2; // 0x2
field public static final int GATT_FAILURE = 257; // 0x101
field public static final int GATT_INSUFFICIENT_AUTHENTICATION = 5; // 0x5
field public static final int GATT_INSUFFICIENT_ENCRYPTION = 15; // 0xf
@@ -6357,11 +6370,11 @@
method public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
method public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
method public void onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
- method public void onConfigureMTU(android.bluetooth.BluetoothGatt, int, int);
method public void onConnectionCongested(android.bluetooth.BluetoothGatt, boolean);
method public void onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int);
method public void onDescriptorRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
method public void onDescriptorWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
+ method public void onMtuChanged(android.bluetooth.BluetoothGatt, int, int);
method public void onReadRemoteRssi(android.bluetooth.BluetoothGatt, int, int);
method public void onReliableWriteCompleted(android.bluetooth.BluetoothGatt, int);
method public void onServicesDiscovered(android.bluetooth.BluetoothGatt, int);
@@ -8667,7 +8680,7 @@
method public void removeSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
method public void uninstall(java.lang.String, android.content.IntentSender);
field public static final java.lang.String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
- field public static final java.lang.String EXTRA_PACKAGE_NAMES = "android.content.pm.extra.PACKAGE_NAMES";
+ field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
field public static final java.lang.String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID";
field public static final java.lang.String EXTRA_STATUS = "android.content.pm.extra.STATUS";
field public static final java.lang.String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE";
@@ -12676,7 +12689,7 @@
method public T get(android.hardware.camera2.CameraCharacteristics.Key<T>);
method public java.util.List<android.hardware.camera2.CaptureRequest.Key<?>> getAvailableCaptureRequestKeys();
method public java.util.List<android.hardware.camera2.CaptureResult.Key<?>> getAvailableCaptureResultKeys();
- field public static final android.hardware.camera2.CameraCharacteristics.Key COLOR_CORRECTION_AVAILABLE_ABERRATION_CORRECTION_MODES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AE_AVAILABLE_ANTIBANDING_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AE_AVAILABLE_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES;
@@ -12790,9 +12803,9 @@
public abstract class CameraMetadata {
method public java.util.List<TKey> getKeys();
- field public static final int COLOR_CORRECTION_ABERRATION_CORRECTION_MODE_FAST = 1; // 0x1
- field public static final int COLOR_CORRECTION_ABERRATION_CORRECTION_MODE_HIGH_QUALITY = 2; // 0x2
- field public static final int COLOR_CORRECTION_ABERRATION_CORRECTION_MODE_OFF = 0; // 0x0
+ field public static final int COLOR_CORRECTION_ABERRATION_MODE_FAST = 1; // 0x1
+ field public static final int COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY = 2; // 0x2
+ field public static final int COLOR_CORRECTION_ABERRATION_MODE_OFF = 0; // 0x0
field public static final int COLOR_CORRECTION_MODE_FAST = 1; // 0x1
field public static final int COLOR_CORRECTION_MODE_HIGH_QUALITY = 2; // 0x2
field public static final int COLOR_CORRECTION_MODE_TRANSFORM_MATRIX = 0; // 0x0
@@ -12968,7 +12981,7 @@
}
public class CaptureFailure {
- method public int getFrameNumber();
+ method public long getFrameNumber();
method public int getReason();
method public android.hardware.camera2.CaptureRequest getRequest();
method public int getSequenceId();
@@ -12983,7 +12996,7 @@
method public java.lang.Object getTag();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.hardware.camera2.CaptureRequest.Key BLACK_LEVEL_LOCK;
- field public static final android.hardware.camera2.CaptureRequest.Key COLOR_CORRECTION_ABERRATION_CORRECTION_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key COLOR_CORRECTION_ABERRATION_MODE;
field public static final android.hardware.camera2.CaptureRequest.Key COLOR_CORRECTION_GAINS;
field public static final android.hardware.camera2.CaptureRequest.Key COLOR_CORRECTION_MODE;
field public static final android.hardware.camera2.CaptureRequest.Key COLOR_CORRECTION_TRANSFORM;
@@ -13055,7 +13068,7 @@
method public android.hardware.camera2.CaptureRequest getRequest();
method public int getSequenceId();
field public static final android.hardware.camera2.CaptureResult.Key BLACK_LEVEL_LOCK;
- field public static final android.hardware.camera2.CaptureResult.Key COLOR_CORRECTION_ABERRATION_CORRECTION_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key COLOR_CORRECTION_ABERRATION_MODE;
field public static final android.hardware.camera2.CaptureResult.Key COLOR_CORRECTION_GAINS;
field public static final android.hardware.camera2.CaptureResult.Key COLOR_CORRECTION_MODE;
field public static final android.hardware.camera2.CaptureResult.Key COLOR_CORRECTION_TRANSFORM;
@@ -13561,7 +13574,7 @@
method public void onStartInput(android.view.inputmethod.EditorInfo, boolean);
method public void onStartInputView(android.view.inputmethod.EditorInfo, boolean);
method public void onUnbindInput();
- method public void onUpdateCursor(android.graphics.Rect);
+ method public deprecated void onUpdateCursor(android.graphics.Rect);
method public void onUpdateCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfo);
method public void onUpdateExtractedText(int, android.view.inputmethod.ExtractedText);
method public void onUpdateExtractingViews(android.view.inputmethod.EditorInfo);
@@ -16381,16 +16394,16 @@
method public void addCallback(android.media.session.MediaController.Callback, android.os.Handler);
method public void adjustVolume(int, int);
method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
- method public android.media.session.MediaController.AudioInfo getAudioInfo();
method public android.os.Bundle getExtras();
method public long getFlags();
- method public android.app.PendingIntent getLaunchActivity();
method public android.media.MediaMetadata getMetadata();
method public java.lang.String getPackageName();
+ method public android.media.session.MediaController.PlaybackInfo getPlaybackInfo();
method public android.media.session.PlaybackState getPlaybackState();
method public java.util.List<android.media.session.MediaSession.Item> getQueue();
method public java.lang.CharSequence getQueueTitle();
method public int getRatingType();
+ method public android.app.PendingIntent getSessionActivity();
method public android.media.session.MediaSession.Token getSessionToken();
method public android.media.session.MediaController.TransportControls getTransportControls();
method public void removeCallback(android.media.session.MediaController.Callback);
@@ -16398,17 +16411,9 @@
method public void setVolumeTo(int, int);
}
- public static final class MediaController.AudioInfo {
- method public android.media.AudioAttributes getAudioAttributes();
- method public int getCurrentVolume();
- method public int getMaxVolume();
- method public int getVolumeControl();
- method public int getVolumeType();
- }
-
public static abstract class MediaController.Callback {
ctor public MediaController.Callback();
- method public void onAudioInfoChanged(android.media.session.MediaController.AudioInfo);
+ method public void onAudioInfoChanged(android.media.session.MediaController.PlaybackInfo);
method public void onExtrasChanged(android.os.Bundle);
method public void onMetadataChanged(android.media.MediaMetadata);
method public void onPlaybackStateChanged(android.media.session.PlaybackState);
@@ -16418,6 +16423,16 @@
method public void onSessionEvent(java.lang.String, android.os.Bundle);
}
+ public static final class MediaController.PlaybackInfo {
+ method public android.media.AudioAttributes getAudioAttributes();
+ method public int getCurrentVolume();
+ method public int getMaxVolume();
+ method public int getPlaybackType();
+ method public int getVolumeControl();
+ field public static final int PLAYBACK_TYPE_LOCAL = 1; // 0x1
+ field public static final int PLAYBACK_TYPE_REMOTE = 2; // 0x2
+ }
+
public final class MediaController.TransportControls {
method public void fastForward();
method public void pause();
@@ -16447,7 +16462,6 @@
method public void setCallback(android.media.session.MediaSession.Callback, android.os.Handler);
method public void setExtras(android.os.Bundle);
method public void setFlags(int);
- method public void setLaunchActivity(android.app.PendingIntent);
method public void setMediaButtonReceiver(android.app.PendingIntent);
method public void setMetadata(android.media.MediaMetadata);
method public void setPlaybackState(android.media.session.PlaybackState);
@@ -16455,10 +16469,9 @@
method public void setPlaybackToRemote(android.media.VolumeProvider);
method public void setQueue(java.util.List<android.media.session.MediaSession.Item>);
method public void setQueueTitle(java.lang.CharSequence);
+ method public void setSessionActivity(android.app.PendingIntent);
field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
- field public static final int PLAYBACK_TYPE_LOCAL = 1; // 0x1
- field public static final int PLAYBACK_TYPE_REMOTE = 2; // 0x2
}
public static abstract class MediaSession.Callback {
@@ -16505,6 +16518,7 @@
public final class MediaSessionManager {
method public void addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName);
+ method public void addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName, android.os.Handler);
method public java.util.List<android.media.session.MediaController> getActiveSessions(android.content.ComponentName);
method public void removeOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener);
}
@@ -16516,7 +16530,7 @@
public final class PlaybackState implements android.os.Parcelable {
method public int describeContents();
method public long getActions();
- method public long getBufferPosition();
+ method public long getBufferedPosition();
method public java.util.List<android.media.session.PlaybackState.CustomAction> getCustomActions();
method public java.lang.CharSequence getErrorMessage();
method public long getLastPositionUpdateTime();
@@ -16560,7 +16574,7 @@
method public android.media.session.PlaybackState build();
method public android.media.session.PlaybackState.Builder setActions(long);
method public android.media.session.PlaybackState.Builder setActiveItem(long);
- method public android.media.session.PlaybackState.Builder setBufferPosition(long);
+ method public android.media.session.PlaybackState.Builder setBufferedPosition(long);
method public android.media.session.PlaybackState.Builder setErrorMessage(java.lang.CharSequence);
method public android.media.session.PlaybackState.Builder setState(int, long, float, long);
method public android.media.session.PlaybackState.Builder setState(int, long, float);
@@ -17201,12 +17215,12 @@
}
public class Network implements android.os.Parcelable {
+ method public void bindSocket(java.net.Socket) throws java.io.IOException;
method public int describeContents();
method public java.net.InetAddress[] getAllByName(java.lang.String) throws java.net.UnknownHostException;
- method public java.net.URL getBoundURL(java.net.URL) throws java.net.MalformedURLException;
method public java.net.InetAddress getByName(java.lang.String) throws java.net.UnknownHostException;
method public javax.net.SocketFactory getSocketFactory();
- method public static void setNetworkBoundURLFactory(android.net.NetworkBoundURLFactory);
+ method public java.net.URLConnection openConnection(java.net.URL) throws java.io.IOException;
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
@@ -18463,25 +18477,8 @@
package android.net.wifi.passpoint {
public abstract interface IWifiPasspointManager implements android.os.IInterface {
- method public abstract boolean addCredential(android.net.wifi.passpoint.WifiPasspointCredential) throws android.os.RemoteException;
- method public abstract java.util.List<android.net.wifi.passpoint.WifiPasspointCredential> getCredentials() throws android.os.RemoteException;
method public abstract android.os.Messenger getMessenger() throws android.os.RemoteException;
method public abstract int getPasspointState() throws android.os.RemoteException;
- method public abstract boolean removeCredential(android.net.wifi.passpoint.WifiPasspointCredential) throws android.os.RemoteException;
- method public abstract java.util.List<android.net.wifi.passpoint.WifiPasspointPolicy> requestCredentialMatch(java.util.List<android.net.wifi.ScanResult>) throws android.os.RemoteException;
- method public abstract boolean updateCredential(android.net.wifi.passpoint.WifiPasspointCredential) throws android.os.RemoteException;
- }
-
- public class WifiPasspointCredential implements android.os.Parcelable {
- ctor public WifiPasspointCredential(java.lang.String, java.lang.String, android.net.wifi.WifiEnterpriseConfig);
- method public int describeContents();
- method public android.net.wifi.WifiEnterpriseConfig getEnterpriseConfig();
- method public java.lang.String getHomeSpFqdn();
- method public java.lang.String getRealm();
- method public void setEnterpriseConfig(android.net.wifi.WifiEnterpriseConfig);
- method public void setHomeFqdn(java.lang.String);
- method public void setRealm(java.lang.String);
- method public void writeToParcel(android.os.Parcel, int);
}
public class WifiPasspointInfo implements android.os.Parcelable {
@@ -18654,17 +18651,6 @@
field public java.lang.String ssid;
}
- public class WifiPasspointPolicy implements android.os.Parcelable {
- method public android.net.wifi.WifiConfiguration createWifiConfiguration();
- method public int describeContents();
- method public java.lang.String getBssid();
- method public android.net.wifi.passpoint.WifiPasspointCredential getCredential();
- method public int getCredentialPriority();
- method public int getRoamingPriority();
- method public java.lang.String getSsid();
- method public void writeToParcel(android.os.Parcel, int);
- }
-
}
package android.nfc {
@@ -18733,7 +18719,6 @@
method public boolean invokeBeam(android.app.Activity);
method public boolean isEnabled();
method public boolean isNdefPushEnabled();
- method public boolean registerLockscreenDispatch(android.nfc.NfcAdapter.NfcLockscreenDispatch, java.lang.String[]);
method public void setBeamPushUris(android.net.Uri[], android.app.Activity);
method public void setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity);
method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...);
@@ -18769,10 +18754,6 @@
method public abstract android.nfc.NdefMessage createNdefMessage(android.nfc.NfcEvent);
}
- public static abstract interface NfcAdapter.NfcLockscreenDispatch {
- method public abstract boolean onTagDetected(android.nfc.Tag);
- }
-
public static abstract interface NfcAdapter.OnNdefPushCompleteCallback {
method public abstract void onNdefPushComplete(android.nfc.NfcEvent);
}
@@ -28516,12 +28497,12 @@
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
- field public static int ROUTE_ALL;
- field public static int ROUTE_BLUETOOTH;
- field public static int ROUTE_EARPIECE;
- field public static int ROUTE_SPEAKER;
- field public static int ROUTE_WIRED_HEADSET;
- field public static int ROUTE_WIRED_OR_EARPIECE;
+ field public static final int ROUTE_ALL = 15; // 0xf
+ field public static final int ROUTE_BLUETOOTH = 2; // 0x2
+ field public static final int ROUTE_EARPIECE = 1; // 0x1
+ field public static final int ROUTE_SPEAKER = 8; // 0x8
+ field public static final int ROUTE_WIRED_HEADSET = 4; // 0x4
+ field public static final int ROUTE_WIRED_OR_EARPIECE = 5; // 0x5
field public final boolean isMuted;
field public final int route;
field public final int supportedRouteMask;
@@ -28569,14 +28550,12 @@
method public final int getCallerDisplayNamePresentation();
method public final android.telecomm.Conference getConference();
method public final java.util.List<android.telecomm.Connection> getConferenceableConnections();
- method public final int getFailureCode();
- method public final java.lang.String getFailureMessage();
+ method public final int getDisconnectCause();
+ method public final java.lang.String getDisconnectMessage();
method public final android.net.Uri getHandle();
method public final int getHandlePresentation();
method public final int getState();
method public final android.telecomm.StatusHints getStatusHints();
- method public final android.telecomm.Connection.VideoProvider getVideoProvider();
- method public final int getVideoState();
method public final boolean isRequestingRingback();
method public void onAbort();
method public void onAnswer(int);
@@ -28608,8 +28587,6 @@
method public final void setRequestingRingback(boolean);
method public final void setRinging();
method public final void setStatusHints(android.telecomm.StatusHints);
- method public final void setVideoProvider(android.telecomm.Connection.VideoProvider);
- method public final void setVideoState(int);
method public final void startActivityFromInCall(android.app.PendingIntent);
method public static java.lang.String stateToString(int);
field public static final int STATE_ACTIVE = 4; // 0x4
@@ -28621,35 +28598,6 @@
field public static final int STATE_RINGING = 2; // 0x2
}
- public static abstract class Connection.VideoProvider {
- ctor public Connection.VideoProvider();
- method public void changeCallDataUsage(int);
- method public void changeCameraCapabilities(android.telecomm.CameraCapabilities);
- method public void changePeerDimensions(int, int);
- method public void handleCallSessionEvent(int);
- method public abstract void onRequestCallDataUsage();
- method public abstract void onRequestCameraCapabilities();
- method public abstract void onSendSessionModifyRequest(android.telecomm.VideoProfile);
- method public abstract void onSendSessionModifyResponse(android.telecomm.VideoProfile);
- method public abstract void onSetCamera(java.lang.String);
- method public abstract void onSetDeviceOrientation(int);
- method public abstract void onSetDisplaySurface(android.view.Surface);
- method public abstract void onSetPauseImage(java.lang.String);
- method public abstract void onSetPreviewSurface(android.view.Surface);
- method public abstract void onSetZoom(float);
- method public void receiveSessionModifyRequest(android.telecomm.VideoProfile);
- method public void receiveSessionModifyResponse(int, android.telecomm.VideoProfile, android.telecomm.VideoProfile);
- field public static final int SESSION_EVENT_CAMERA_FAILURE = 5; // 0x5
- field public static final int SESSION_EVENT_CAMERA_READY = 6; // 0x6
- field public static final int SESSION_EVENT_RX_PAUSE = 1; // 0x1
- field public static final int SESSION_EVENT_RX_RESUME = 2; // 0x2
- field public static final int SESSION_EVENT_TX_START = 3; // 0x3
- field public static final int SESSION_EVENT_TX_STOP = 4; // 0x4
- field public static final int SESSION_MODIFY_REQUEST_FAIL = 2; // 0x2
- field public static final int SESSION_MODIFY_REQUEST_INVALID = 3; // 0x3
- field public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1; // 0x1
- }
-
public final class ConnectionRequest implements android.os.Parcelable {
ctor public ConnectionRequest(android.telecomm.PhoneAccountHandle, android.net.Uri, int, android.os.Bundle, int);
method public int describeContents();
@@ -28657,7 +28605,6 @@
method public android.os.Bundle getExtras();
method public android.net.Uri getHandle();
method public int getHandlePresentation();
- method public int getVideoState();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
@@ -28769,7 +28716,6 @@
method public android.telecomm.RemoteConnection getParent();
method public int getState();
method public android.telecomm.StatusHints getStatusHints();
- method public int getVideoState();
method public void hold();
method public boolean isRequestingRingback();
method public void playDtmfTone(char);
@@ -28797,7 +28743,6 @@
method public void onStartActivityFromInCall(android.telecomm.RemoteConnection, android.app.PendingIntent);
method public void onStateChanged(android.telecomm.RemoteConnection, int);
method public void onStatusHintsChanged(android.telecomm.RemoteConnection, android.telecomm.StatusHints);
- method public void onVideoStateChanged(android.telecomm.RemoteConnection, int);
}
public abstract interface Response {
@@ -28836,35 +28781,6 @@
field public static final java.lang.String EXTRA_CONNECTION_SERVICE = "android.telecomm.extra.CONNECTION_SERVICE";
field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.intent.extra.PHONE_ACCOUNT_HANDLE";
field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.intent.extra.START_CALL_WITH_SPEAKERPHONE";
- field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.intent.extra.START_CALL_WITH_VIDEO_STATE";
- }
-
- public class VideoProfile implements android.os.Parcelable {
- ctor public VideoProfile(int);
- ctor public VideoProfile(int, int);
- method public int describeContents();
- method public int getQuality();
- method public int getVideoState();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator CREATOR;
- field public static final int QUALITY_DEFAULT = 4; // 0x4
- field public static final int QUALITY_HIGH = 1; // 0x1
- field public static final int QUALITY_LOW = 3; // 0x3
- field public static final int QUALITY_MEDIUM = 2; // 0x2
- }
-
- public static class VideoProfile.VideoState {
- ctor public VideoProfile.VideoState();
- method public static boolean isAudioOnly(int);
- method public static boolean isBidirectional(int);
- method public static boolean isPaused(int);
- method public static boolean isReceptionEnabled(int);
- method public static boolean isTransmissionEnabled(int);
- field public static final int AUDIO_ONLY = 0; // 0x0
- field public static final int BIDIRECTIONAL = 3; // 0x3
- field public static final int PAUSED = 4; // 0x4
- field public static final int RX_ENABLED = 2; // 0x2
- field public static final int TX_ENABLED = 1; // 0x1
}
}
@@ -31534,7 +31450,7 @@
field public static final java.lang.String CASE_GENITIVE = "android.genitive";
field public static final java.lang.String CASE_INSTRUMENTAL = "android.instrumental";
field public static final java.lang.String CASE_LOCATIVE = "android.locative";
- field public static final java.lang.String CASE_NOMINATIVE = "android.nomative";
+ field public static final java.lang.String CASE_NOMINATIVE = "android.nominative";
field public static final java.lang.String CASE_VOCATIVE = "android.vocative";
field public static final java.lang.String GENDER_FEMALE = "android.female";
field public static final java.lang.String GENDER_MALE = "android.male";
@@ -31824,7 +31740,7 @@
ctor public ChangeBounds(android.content.Context, android.util.AttributeSet);
method public void captureEndValues(android.transition.TransitionValues);
method public void captureStartValues(android.transition.TransitionValues);
- method public void setReparent(boolean);
+ method public deprecated void setReparent(boolean);
method public void setResizeClip(boolean);
}
@@ -31847,6 +31763,10 @@
ctor public ChangeTransform(android.content.Context, android.util.AttributeSet);
method public void captureEndValues(android.transition.TransitionValues);
method public void captureStartValues(android.transition.TransitionValues);
+ method public boolean getReparent();
+ method public boolean getReparentWithOverlay();
+ method public void setReparent(boolean);
+ method public void setReparentWithOverlay(boolean);
}
public class CircularPropagation extends android.transition.VisibilityPropagation {
@@ -33402,6 +33322,7 @@
field public static final int KEYCODE_U = 49; // 0x31
field public static final int KEYCODE_UNKNOWN = 0; // 0x0
field public static final int KEYCODE_V = 50; // 0x32
+ field public static final int KEYCODE_VOICE_ASSIST = 231; // 0xe7
field public static final int KEYCODE_VOLUME_DOWN = 25; // 0x19
field public static final int KEYCODE_VOLUME_MUTE = 164; // 0xa4
field public static final int KEYCODE_VOLUME_UP = 24; // 0x18
@@ -34958,6 +34879,8 @@
ctor public ViewOutlineProvider();
method public abstract void getOutline(android.view.View, android.graphics.Outline);
field public static final android.view.ViewOutlineProvider BACKGROUND;
+ field public static final android.view.ViewOutlineProvider BOUNDS;
+ field public static final android.view.ViewOutlineProvider PADDED_BOUNDS;
}
public class ViewOverlay {
@@ -35157,6 +35080,7 @@
method public android.transition.Transition getSharedElementExitTransition();
method public android.transition.Transition getSharedElementReenterTransition();
method public android.transition.Transition getSharedElementReturnTransition();
+ method public boolean getSharedElementsUseOverlay();
method public abstract int getStatusBarColor();
method public long getTransitionBackgroundFadeDuration();
method public android.transition.TransitionManager getTransitionManager();
@@ -35218,6 +35142,7 @@
method public void setSharedElementExitTransition(android.transition.Transition);
method public void setSharedElementReenterTransition(android.transition.Transition);
method public void setSharedElementReturnTransition(android.transition.Transition);
+ method public void setSharedElementsUseOverlay(boolean);
method public void setSoftInputMode(int);
method public abstract void setStatusBarColor(int);
method public abstract void setTitle(java.lang.CharSequence);
@@ -36198,7 +36123,7 @@
method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
method public static final void removeComposingSpans(android.text.Spannable);
method public boolean reportFullscreenMode(boolean);
- method public int requestCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfoRequest);
+ method public boolean requestUpdateCursorAnchorInfo(int);
method public boolean sendKeyEvent(android.view.KeyEvent);
method public boolean setComposingRegion(int, int);
method public static void setComposingSpans(android.text.Spannable);
@@ -36264,25 +36189,6 @@
method public android.view.inputmethod.CursorAnchorInfo.Builder setSelectionRange(int, int);
}
- public final class CursorAnchorInfoRequest implements android.os.Parcelable {
- ctor public CursorAnchorInfoRequest(int, int);
- ctor public CursorAnchorInfoRequest(android.os.Parcel);
- method public int describeContents();
- method public int getRequestFlags();
- method public int getRequestType();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator CREATOR;
- field public static final int FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE = 2; // 0x2
- field public static final int FLAG_CURSOR_ANCHOR_INFO_MONITOR = 1; // 0x1
- field public static final int FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES = 2; // 0x2
- field public static final int FLAG_CURSOR_RECT_MONITOR = 1; // 0x1
- field public static final int FLAG_CURSOR_RECT_WITH_VIEW_MATRIX = 4; // 0x4
- field public static final int RESULT_NOT_HANDLED = 0; // 0x0
- field public static final int RESULT_SCHEDULED = 1; // 0x1
- field public static final int TYPE_CURSOR_ANCHOR_INFO = 1; // 0x1
- field public static final int TYPE_CURSOR_RECT = 2; // 0x2
- }
-
public class EditorInfo implements android.text.InputType android.os.Parcelable {
ctor public EditorInfo();
method public int describeContents();
@@ -36380,13 +36286,15 @@
method public abstract boolean performEditorAction(int);
method public abstract boolean performPrivateCommand(java.lang.String, android.os.Bundle);
method public abstract boolean reportFullscreenMode(boolean);
- method public abstract int requestCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfoRequest);
+ method public abstract boolean requestUpdateCursorAnchorInfo(int);
method public abstract boolean sendKeyEvent(android.view.KeyEvent);
method public abstract boolean setComposingRegion(int, int);
method public abstract boolean setComposingText(java.lang.CharSequence, int);
method public abstract boolean setSelection(int, int);
field public static final int GET_EXTRACTED_TEXT_MONITOR = 1; // 0x1
field public static final int GET_TEXT_WITH_STYLES = 1; // 0x1
+ field public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE = 1; // 0x1
+ field public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR = 2; // 0x2
}
public class InputConnectionWrapper implements android.view.inputmethod.InputConnection {
@@ -36408,7 +36316,7 @@
method public boolean performEditorAction(int);
method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
method public boolean reportFullscreenMode(boolean);
- method public int requestCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfoRequest);
+ method public boolean requestUpdateCursorAnchorInfo(int);
method public boolean sendKeyEvent(android.view.KeyEvent);
method public boolean setComposingRegion(int, int);
method public boolean setComposingText(java.lang.CharSequence, int);
@@ -36474,7 +36382,7 @@
method public boolean isActive(android.view.View);
method public boolean isActive();
method public boolean isFullscreenMode();
- method public boolean isWatchingCursor(android.view.View);
+ method public deprecated boolean isWatchingCursor(android.view.View);
method public void restartInput(android.view.View);
method public void sendAppPrivateCommand(android.view.View, java.lang.String, android.os.Bundle);
method public void setAdditionalInputMethodSubtypes(java.lang.String, android.view.inputmethod.InputMethodSubtype[]);
@@ -36492,7 +36400,7 @@
method public boolean switchToNextInputMethod(android.os.IBinder, boolean);
method public void toggleSoftInput(int, int);
method public void toggleSoftInputFromWindow(android.os.IBinder, int, int);
- method public void updateCursor(android.view.View, int, int, int, int);
+ method public deprecated void updateCursor(android.view.View, int, int, int, int);
method public void updateCursorAnchorInfo(android.view.View, android.view.inputmethod.CursorAnchorInfo);
method public void updateExtractedText(android.view.View, int, android.view.inputmethod.ExtractedText);
method public void updateSelection(android.view.View, int, int, int, int);
@@ -39781,6 +39689,7 @@
method public void setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener);
method public void setVideoPath(java.lang.String);
method public void setVideoURI(android.net.Uri);
+ method public void setVideoURI(android.net.Uri, java.util.Map<java.lang.String, java.lang.String>);
method public void start();
method public void stopPlayback();
method public void suspend();
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index 5f80ed7..3720c81 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -370,6 +370,7 @@
* @hide
*/
public void reverse() {
+ throw new IllegalStateException("Reverse is not supported");
}
/**
diff --git a/core/java/android/animation/RevealAnimator.java b/core/java/android/animation/RevealAnimator.java
index e363a77..0f85f49 100644
--- a/core/java/android/animation/RevealAnimator.java
+++ b/core/java/android/animation/RevealAnimator.java
@@ -26,148 +26,21 @@
*
* @hide
*/
-public class RevealAnimator extends ValueAnimator {
+public class RevealAnimator extends RenderNodeAnimator {
private View mClipView;
- private int mX, mY;
- private float mStartRadius, mEndRadius;
- private float mDelta;
- private boolean mMayRunAsync;
-
- // If this is null, we are running on the UI thread driven by the base
- // ValueAnimator class. If this is not null, forward requests on to this
- // Animator instead.
- private RenderNodeAnimator mRtAnimator;
public RevealAnimator(View clipView, int x, int y,
float startRadius, float endRadius) {
+ super(x, y, startRadius, endRadius);
mClipView = clipView;
- mStartRadius = startRadius;
- mEndRadius = endRadius;
- mDelta = endRadius - startRadius;
- mX = x;
- mY = y;
- super.setValues(PropertyValuesHolder.ofFloat("radius", startRadius, endRadius));
+ setTarget(mClipView);
}
@Override
- void animateValue(float fraction) {
- super.animateValue(fraction);
- fraction = getAnimatedFraction();
- float radius = mStartRadius + (mDelta * fraction);
- mClipView.setRevealClip(true, mX, mY, radius);
- }
-
- @Override
- protected void endAnimation(AnimationHandler handler) {
+ protected void onFinished() {
mClipView.setRevealClip(false, 0, 0, 0);
- super.endAnimation(handler);
+ super.onFinished();
}
- @Override
- public void setAllowRunningAsynchronously(boolean mayRunAsync) {
- mMayRunAsync = mayRunAsync;
- }
-
- private boolean canRunAsync() {
- if (!mMayRunAsync) {
- return false;
- }
- if (mUpdateListeners != null && mUpdateListeners.size() > 0) {
- return false;
- }
- // TODO: Have RNA support this
- if (getRepeatCount() != 0) {
- return false;
- }
- return true;
- }
-
- @Override
- public void start() {
- if (mRtAnimator != null) {
- mRtAnimator.end();
- mRtAnimator = null;
- }
- if (canRunAsync()) {
- mRtAnimator = new RenderNodeAnimator(mX, mY, mStartRadius, mEndRadius);
- mRtAnimator.setDuration(getDuration());
- mRtAnimator.setInterpolator(getInterpolator());
- mRtAnimator.setTarget(mClipView);
- // TODO: Listeners
- mRtAnimator.start();
- } else {
- super.start();
- }
- }
-
- @Override
- public void cancel() {
- if (mRtAnimator != null) {
- mRtAnimator.cancel();
- } else {
- super.cancel();
- }
- }
-
- @Override
- public void end() {
- if (mRtAnimator != null) {
- mRtAnimator.end();
- } else {
- super.end();
- }
- }
-
- @Override
- public void resume() {
- if (mRtAnimator != null) {
- // TODO: Support? Reject?
- } else {
- super.resume();
- }
- }
-
- @Override
- public void pause() {
- if (mRtAnimator != null) {
- // TODO: see resume()
- } else {
- super.pause();
- }
- }
-
- @Override
- public boolean isRunning() {
- if (mRtAnimator != null) {
- return mRtAnimator.isRunning();
- } else {
- return super.isRunning();
- }
- }
-
- @Override
- public boolean isStarted() {
- if (mRtAnimator != null) {
- return mRtAnimator.isStarted();
- } else {
- return super.isStarted();
- }
- }
-
- @Override
- public void reverse() {
- if (mRtAnimator != null) {
- // TODO support
- } else {
- super.reverse();
- }
- }
-
- @Override
- public RevealAnimator clone() {
- RevealAnimator anim = (RevealAnimator) super.clone();
- anim.mRtAnimator = null;
- return anim;
- }
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index f5ac5f7..2e66a4c 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -54,7 +54,6 @@
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.session.MediaController;
-import android.media.session.MediaSession;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -5021,6 +5020,9 @@
}
}
}
+ if (mActionBar != null) {
+ mActionBar.setTitle(title);
+ }
}
protected void onChildTitleChanged(Activity childActivity, CharSequence title) {
@@ -5638,8 +5640,8 @@
if (info.taskAffinity == null) {
return false;
}
- return !ActivityManagerNative.getDefault()
- .targetTaskAffinityMatchesActivity(mToken, info.taskAffinity);
+ return ActivityManagerNative.getDefault()
+ .shouldUpRecreateTask(mToken, info.taskAffinity);
} catch (RemoteException e) {
return false;
} catch (NameNotFoundException e) {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 4b022ff..b86621f 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -16,6 +16,11 @@
package android.app;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Point;
import android.os.BatteryStats;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
@@ -47,16 +52,13 @@
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.DisplayMetrics;
-import android.util.Log;
import android.util.Slog;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
/**
* Interact with the overall activities running in the system.
@@ -297,6 +299,8 @@
/** @hide Process is being cached for later use and is empty. */
public static final int PROCESS_STATE_CACHED_EMPTY = 13;
+ Point mAppTaskThumbnailSize;
+
/*package*/ ActivityManager(Context context, Handler handler) {
mContext = context;
mHandler = handler;
@@ -994,6 +998,103 @@
}
/**
+ * Return the current design width for {@link AppTask} thumbnails, for use
+ * with {@link #addAppTask}.
+ */
+ public int getAppTaskThumbnailWidth() {
+ synchronized (this) {
+ ensureAppTaskThumbnailSizeLocked();
+ return mAppTaskThumbnailSize.x;
+ }
+ }
+
+ /**
+ * Return the current design height for {@link AppTask} thumbnails, for use
+ * with {@link #addAppTask}.
+ */
+ public int getAppTaskThumbnailHeight() {
+ synchronized (this) {
+ ensureAppTaskThumbnailSizeLocked();
+ return mAppTaskThumbnailSize.y;
+ }
+ }
+
+ private void ensureAppTaskThumbnailSizeLocked() {
+ if (mAppTaskThumbnailSize == null) {
+ try {
+ mAppTaskThumbnailSize = ActivityManagerNative.getDefault().getAppTaskThumbnailSize();
+ } catch (RemoteException e) {
+ throw new IllegalStateException("System dead?", e);
+ }
+ }
+ }
+
+ /**
+ * Add a new {@link AppTask} for the calling application. This will create a new
+ * recents entry that is added to the <b>end</b> of all existing recents.
+ *
+ * @param activity The activity that is adding the entry. This is used to help determine
+ * the context that the new recents entry will be in.
+ * @param intent The Intent that describes the recents entry. This is the same Intent that
+ * you would have used to launch the activity for it. In generally you will want to set
+ * both {@link Intent#FLAG_ACTIVITY_NEW_DOCUMENT} and
+ * {@link Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS}; the latter is required since this recents
+ * entry will exist without an activity, so it doesn't make sense to not retain it when
+ * its activity disappears. The given Intent here also must have an explicit ComponentName
+ * set on it.
+ * @param description Optional additional description information.
+ * @param thumbnail Thumbnail to use for the recents entry. Should be the size given by
+ * {@link #getAppTaskThumbnailWidth()} and {@link #getAppTaskThumbnailHeight()}. If the
+ * bitmap is not that exact size, it will be recreated in your process, probably in a way
+ * you don't like, before the recents entry is added.
+ *
+ * @return Returns the task id of the newly added app task, or -1 if the add failed. The
+ * most likely cause of failure is that there is no more room for more tasks for your app.
+ */
+ public int addAppTask(@NonNull Activity activity, @NonNull Intent intent,
+ @Nullable TaskDescription description, @NonNull Bitmap thumbnail) {
+ Point size;
+ synchronized (this) {
+ ensureAppTaskThumbnailSizeLocked();
+ size = mAppTaskThumbnailSize;
+ }
+ final int tw = thumbnail.getWidth();
+ final int th = thumbnail.getHeight();
+ if (tw != size.x || th != size.y) {
+ Bitmap bm = Bitmap.createBitmap(size.x, size.y, thumbnail.getConfig());
+
+ // Use ScaleType.CENTER_CROP, except we leave the top edge at the top.
+ float scale;
+ float dx = 0, dy = 0;
+ if (tw * size.x > size.y * th) {
+ scale = (float) size.x / (float) th;
+ dx = (size.y - tw * scale) * 0.5f;
+ } else {
+ scale = (float) size.y / (float) tw;
+ dy = (size.x - th * scale) * 0.5f;
+ }
+ Matrix matrix = new Matrix();
+ matrix.setScale(scale, scale);
+ matrix.postTranslate((int) (dx + 0.5f), 0);
+
+ Canvas canvas = new Canvas(bm);
+ canvas.drawBitmap(thumbnail, matrix, null);
+ canvas.setBitmap(null);
+
+ thumbnail = bm;
+ }
+ if (description == null) {
+ description = new TaskDescription();
+ }
+ try {
+ return ActivityManagerNative.getDefault().addAppTask(activity.getActivityToken(),
+ intent, description, thumbnail);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("System dead?", e);
+ }
+ }
+
+ /**
* Return a list of the tasks that are currently running, with
* the most recent being first and older ones after in order. Note that
* "running" does not mean any of the task's code is currently loaded or
@@ -2514,5 +2615,20 @@
return null;
}
}
+
+ /**
+ * Modify the {@link Intent#FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS} flag in the root
+ * Intent of this AppTask.
+ *
+ * @param exclude If true, {@link Intent#FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS} will
+ * be set; otherwise, it will be cleared.
+ */
+ public void setExcludeFromRecents(boolean exclude) {
+ try {
+ mAppTaskImpl.setExcludeFromRecents(exclude);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Invalid AppTask", e);
+ }
+ }
}
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 1cb1047..5b81cc3 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -30,6 +30,8 @@
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.graphics.Point;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
@@ -564,6 +566,27 @@
return true;
}
+ case ADD_APP_TASK_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder activityToken = data.readStrongBinder();
+ Intent intent = Intent.CREATOR.createFromParcel(data);
+ ActivityManager.TaskDescription descr
+ = ActivityManager.TaskDescription.CREATOR.createFromParcel(data);
+ Bitmap thumbnail = Bitmap.CREATOR.createFromParcel(data);
+ int res = addAppTask(activityToken, intent, descr, thumbnail);
+ reply.writeNoException();
+ reply.writeInt(res);
+ return true;
+ }
+
+ case GET_APP_TASK_THUMBNAIL_SIZE_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ Point size = getAppTaskThumbnailSize();
+ reply.writeNoException();
+ size.writeToParcel(reply, 0);
+ return true;
+ }
+
case GET_TASKS_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
int maxNum = data.readInt();
@@ -1974,11 +1997,11 @@
return true;
}
- case TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION: {
+ case SHOULD_UP_RECREATE_TASK_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
String destAffinity = data.readString();
- boolean res = targetTaskAffinityMatchesActivity(token, destAffinity);
+ boolean res = shouldUpRecreateTask(token, destAffinity);
reply.writeNoException();
reply.writeInt(res ? 1 : 0);
return true;
@@ -2877,6 +2900,33 @@
reply.recycle();
return list;
}
+ public int addAppTask(IBinder activityToken, Intent intent,
+ ActivityManager.TaskDescription description, Bitmap thumbnail) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(activityToken);
+ intent.writeToParcel(data, 0);
+ description.writeToParcel(data, 0);
+ thumbnail.writeToParcel(data, 0);
+ mRemote.transact(ADD_APP_TASK_TRANSACTION, data, reply, 0);
+ reply.readException();
+ int res = reply.readInt();
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
+ public Point getAppTaskThumbnailSize() throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(GET_APP_TASK_THUMBNAIL_SIZE_TRANSACTION, data, reply, 0);
+ reply.readException();
+ Point size = Point.CREATOR.createFromParcel(reply);
+ data.recycle();
+ reply.recycle();
+ return size;
+ }
public List getTasks(int maxNum, int flags) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -4808,14 +4858,14 @@
reply.recycle();
}
- public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity)
+ public boolean shouldUpRecreateTask(IBinder token, String destAffinity)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(token);
data.writeString(destAffinity);
- mRemote.transact(TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION, data, reply, 0);
+ mRemote.transact(SHOULD_UP_RECREATE_TASK_TRANSACTION, data, reply, 0);
reply.readException();
boolean result = reply.readInt() != 0;
data.recycle();
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 7d2f677..e4f2b88 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -665,6 +665,9 @@
}
protected void moveSharedElementsToOverlay() {
+ if (!mWindow.getSharedElementsUseOverlay()) {
+ return;
+ }
int numSharedElements = mSharedElements.size();
ViewGroup decor = getDecor();
if (decor != null) {
@@ -700,6 +703,17 @@
}
protected void moveSharedElementsFromOverlay() {
+ int numListeners = mGhostViewListeners.size();
+ for (int i = 0; i < numListeners; i++) {
+ GhostViewListeners listener = mGhostViewListeners.get(i);
+ ViewGroup parent = (ViewGroup) listener.getView().getParent();
+ parent.getViewTreeObserver().removeOnPreDrawListener(listener);
+ }
+ mGhostViewListeners.clear();
+
+ if (mWindow == null || !mWindow.getSharedElementsUseOverlay()) {
+ return;
+ }
ViewGroup decor = getDecor();
if (decor != null) {
ViewGroupOverlay overlay = decor.getOverlay();
@@ -709,13 +723,6 @@
GhostView.removeGhost(sharedElement);
}
}
- int numListeners = mGhostViewListeners.size();
- for (int i = 0; i < numListeners; i++) {
- GhostViewListeners listener = mGhostViewListeners.get(i);
- ViewGroup parent = (ViewGroup) listener.getView().getParent();
- parent.getViewTreeObserver().removeOnPreDrawListener(listener);
- }
- mGhostViewListeners.clear();
}
protected void setGhostVisibility(int visibility) {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 0d2ad08..66928ca 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -16,25 +16,25 @@
package android.app;
-import android.Manifest;
+import android.annotation.SystemApi;
+import android.app.usage.UsageStatsManager;
+import android.content.Context;
import android.media.AudioAttributes.AttributeUsage;
import android.os.Binder;
import android.os.IBinder;
-import android.os.UserManager;
-import android.util.ArrayMap;
-
-import com.android.internal.app.IAppOpsService;
-import com.android.internal.app.IAppOpsCallback;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Process;
import android.os.RemoteException;
+import android.os.UserManager;
+import android.util.ArrayMap;
+
+import com.android.internal.app.IAppOpsCallback;
+import com.android.internal.app.IAppOpsService;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
/**
* API for interacting with "application operation" tracking.
@@ -203,8 +203,10 @@
public static final int OP_TOAST_WINDOW = 45;
/** @hide Capture the device's display contents and/or audio */
public static final int OP_PROJECT_MEDIA = 46;
+ /** @hide Activate a VPN connection without user intervention. */
+ public static final int OP_ACTIVATE_VPN = 47;
/** @hide */
- public static final int _NUM_OP = 47;
+ public static final int _NUM_OP = 48;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION =
@@ -218,6 +220,9 @@
/** Continually monitoring location data with a relatively high power request. */
public static final String OPSTR_MONITOR_HIGH_POWER_LOCATION
= "android:monitor_location_high_power";
+ /** Activate a VPN connection without user intervention. @hide */
+ @SystemApi
+ public static final String OPSTR_ACTIVATE_VPN = "android:activate_vpn";
/**
* This maps each operation to the operation that serves as the
@@ -275,6 +280,7 @@
OP_MUTE_MICROPHONE,
OP_TOAST_WINDOW,
OP_PROJECT_MEDIA,
+ OP_ACTIVATE_VPN,
};
/**
@@ -329,6 +335,7 @@
null,
null,
null,
+ OPSTR_ACTIVATE_VPN,
};
/**
@@ -383,6 +390,7 @@
"MUTE_MICROPHONE",
"TOAST_WINDOW",
"PROJECT_MEDIA",
+ "ACTIVATE_VPN",
};
/**
@@ -437,6 +445,7 @@
null, // no permission for muting/unmuting microphone
null, // no permission for displaying toasts
null, // no permission for projecting media
+ null, // no permission for activating vpn
};
/**
@@ -492,6 +501,7 @@
UserManager.DISALLOW_UNMUTE_MICROPHONE, // MUTE_MICROPHONE
UserManager.DISALLOW_CREATE_WINDOWS, // TOAST_WINDOW
null, //PROJECT_MEDIA
+ UserManager.DISALLOW_CONFIG_VPN, // ACTIVATE_VPN
};
/**
@@ -546,6 +556,7 @@
false, //MUTE_MICROPHONE
true, //TOAST_WINDOW
false, //PROJECT_MEDIA
+ false, //ACTIVATE_VPN
};
/**
@@ -599,6 +610,7 @@
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_IGNORED, // OP_PROJECT_MEDIA
+ AppOpsManager.MODE_IGNORED, // OP_ACTIVATE_VPN
};
/**
@@ -656,6 +668,7 @@
false,
false,
false,
+ false,
};
private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>();
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index b2812e3..9342ae5 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -749,10 +749,10 @@
putCachedIcon(name, dr);
return dr;
} catch (NameNotFoundException e) {
- Log.w("PackageManager", "Failure retrieving resources for"
+ Log.w("PackageManager", "Failure retrieving resources for "
+ appInfo.packageName);
} catch (Resources.NotFoundException e) {
- Log.w("PackageManager", "Failure retrieving resources for"
+ Log.w("PackageManager", "Failure retrieving resources for "
+ appInfo.packageName + ": " + e.getMessage());
} catch (RuntimeException e) {
// If an exception was thrown, fall through to return
@@ -1100,7 +1100,7 @@
putCachedString(name, text);
return text;
} catch (NameNotFoundException e) {
- Log.w("PackageManager", "Failure retrieving resources for"
+ Log.w("PackageManager", "Failure retrieving resources for "
+ appInfo.packageName);
} catch (RuntimeException e) {
// If an exception was thrown, fall through to return
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 8e21899..1664408 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -36,6 +36,7 @@
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
+import android.graphics.Point;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
@@ -119,6 +120,9 @@
public String getCallingPackage(IBinder token) throws RemoteException;
public ComponentName getCallingActivity(IBinder token) throws RemoteException;
public List<IAppTask> getAppTasks() throws RemoteException;
+ public int addAppTask(IBinder activityToken, Intent intent,
+ ActivityManager.TaskDescription description, Bitmap thumbnail) throws RemoteException;
+ public Point getAppTaskThumbnailSize() throws RemoteException;
public List<RunningTaskInfo> getTasks(int maxNum, int flags) throws RemoteException;
public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
int flags, int userId) throws RemoteException;
@@ -389,7 +393,7 @@
public void keyguardWaitingForActivityDrawn() throws RemoteException;
- public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity)
+ public boolean shouldUpRecreateTask(IBinder token, String destAffinity)
throws RemoteException;
public boolean navigateUpTo(IBinder token, Intent target, int resultCode, Intent resultData)
@@ -698,7 +702,7 @@
int GET_MY_MEMORY_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+142;
int KILL_PROCESSES_BELOW_FOREGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+143;
int GET_CURRENT_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+144;
- int TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+145;
+ int SHOULD_UP_RECREATE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+145;
int NAVIGATE_UP_TO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+146;
int SET_LOCK_SCREEN_SHOWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+147;
int FINISH_ACTIVITY_AFFINITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+148;
@@ -765,4 +769,6 @@
int NOTIFY_ENTER_ANIMATION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+230;
int KEYGUARD_WAITING_FOR_ACTIVITY_DRAWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+231;
int START_ACTIVITY_AS_CALLER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+232;
+ int ADD_APP_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+233;
+ int GET_APP_TASK_THUMBNAIL_SIZE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+234;
}
diff --git a/core/java/android/app/IAppTask.aidl b/core/java/android/app/IAppTask.aidl
index 268b4dd..4e38c36 100644
--- a/core/java/android/app/IAppTask.aidl
+++ b/core/java/android/app/IAppTask.aidl
@@ -22,4 +22,5 @@
interface IAppTask {
void finishAndRemoveTask();
ActivityManager.RecentTaskInfo getTaskInfo();
+ void setExcludeFromRecents(boolean exclude);
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 70ba8ea..f7300aa 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -40,6 +40,7 @@
import android.os.UserManager;
import android.text.TextUtils;
import android.util.Log;
+import android.util.MathUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
@@ -1755,6 +1756,7 @@
*/
public static class Builder {
private static final int MAX_ACTION_BUTTONS = 3;
+ private static final float LARGE_TEXT_SCALE = 1.3f;
/**
* @hide
@@ -2577,34 +2579,35 @@
return bitmap;
}
- private RemoteViews applyStandardTemplate(int resId, boolean fitIn1U) {
- final boolean largeFontScale
- = mContext.getResources().getConfiguration().fontScale >= 1.25f;
+ private boolean addProfileBadge(RemoteViews contentView, int resId) {
+ Bitmap profileBadge = getProfileBadge();
- Bitmap profileIcon = getProfileBadge();
+ contentView.setViewVisibility(R.id.profile_badge_large_template, View.GONE);
+ contentView.setViewVisibility(R.id.profile_badge_line2, View.GONE);
+ contentView.setViewVisibility(R.id.profile_badge_line3, View.GONE);
+
+ if (profileBadge != null) {
+ contentView.setImageViewBitmap(resId, profileBadge);
+ contentView.setViewVisibility(resId, View.VISIBLE);
+
+ // Make sure Line 3 is visible. As badge will be here if there
+ // is no text to display.
+ if (resId == R.id.profile_badge_line3) {
+ contentView.setViewVisibility(R.id.line3, View.VISIBLE);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private RemoteViews applyStandardTemplate(int resId) {
RemoteViews contentView = new BuilderRemoteViews(mContext.getPackageName(),
mOriginatingUserId, resId);
- if (largeFontScale) {
- // Make a little extra room for the bigger text.
- final int margin = (int) mContext.getResources()
- .getDimensionPixelSize(R.dimen.notification_large_font_vert_pad);
- contentView.setViewPadding(R.id.line1, 0, margin, 0, 0);
- contentView.setViewPadding(R.id.line3, 0, 0, 0, margin);
- }
-
boolean showLine3 = false;
boolean showLine2 = false;
+ boolean contentTextInLine2 = false;
- if (mPriority < PRIORITY_LOW) {
- // TODO: Low priority presentation
- }
- if (profileIcon != null) {
- contentView.setImageViewBitmap(R.id.profile_icon, profileIcon);
- contentView.setViewVisibility(R.id.profile_icon, View.VISIBLE);
- } else {
- contentView.setViewVisibility(R.id.profile_icon, View.GONE);
- }
if (mLargeIcon != null) {
contentView.setImageViewBitmap(R.id.icon, mLargeIcon);
processLargeIcon(mLargeIcon, contentView);
@@ -2651,6 +2654,7 @@
contentView.setTextViewText(R.id.text2, processLegacyText(mContentText));
contentView.setViewVisibility(R.id.text2, View.VISIBLE);
showLine2 = true;
+ contentTextInLine2 = true;
} else {
contentView.setViewVisibility(R.id.text2, View.GONE);
}
@@ -2666,15 +2670,12 @@
}
}
if (showLine2) {
- if (fitIn1U) {
- // need to shrink all the type to make sure everything fits
- final Resources res = mContext.getResources();
- final float subTextSize = res.getDimensionPixelSize(
- R.dimen.notification_subtext_size);
- contentView.setTextViewTextSize(R.id.text, TypedValue.COMPLEX_UNIT_PX, subTextSize);
- }
- // vertical centering
- contentView.setViewPadding(R.id.line1, 0, 0, 0, 0);
+
+ // need to shrink all the type to make sure everything fits
+ final Resources res = mContext.getResources();
+ final float subTextSize = res.getDimensionPixelSize(
+ R.dimen.notification_subtext_size);
+ contentView.setTextViewTextSize(R.id.text, TypedValue.COMPLEX_UNIT_PX, subTextSize);
}
if (mWhen != 0 && mShowWhen) {
@@ -2691,13 +2692,60 @@
contentView.setViewVisibility(R.id.time, View.GONE);
}
+ // Adjust padding depending on line count and font size.
+ contentView.setViewPadding(R.id.line1, 0, calculateTopPadding(mContext,
+ hasThreeLines(), mContext.getResources().getConfiguration().fontScale),
+ 0, 0);
+
+ // We want to add badge to first line of text.
+ boolean addedBadge = addProfileBadge(contentView,
+ contentTextInLine2 ? R.id.profile_badge_line2 : R.id.profile_badge_line3);
+ // If we added the badge to line 3 then we should show line 3.
+ if (addedBadge && !contentTextInLine2) {
+ showLine3 = true;
+ }
+
+ // Note getStandardView may hide line 3 again.
contentView.setViewVisibility(R.id.line3, showLine3 ? View.VISIBLE : View.GONE);
contentView.setViewVisibility(R.id.overflow_divider, showLine3 ? View.VISIBLE : View.GONE);
return contentView;
}
+ /**
+ * Logic to find out whether the notification is going to have three lines in the contracted
+ * layout. This is used to adjust the top padding.
+ *
+ * @return true if the notification is going to have three lines; false if the notification
+ * is going to have one or two lines
+ */
+ private boolean hasThreeLines() {
+ boolean hasLine3 = mContentText != null || mContentInfo != null || mNumber > 0;
+ boolean hasLine2 = (mSubText != null && mContentText != null) ||
+ (mSubText == null && (mProgressMax != 0 || mProgressIndeterminate));
+ return hasLine2 && hasLine3;
+ }
+
+ /**
+ * @hide
+ */
+ public static int calculateTopPadding(Context ctx, boolean hasThreeLines,
+ float fontScale) {
+ int padding = ctx.getResources().getDimensionPixelSize(hasThreeLines
+ ? R.dimen.notification_top_pad_narrow
+ : R.dimen.notification_top_pad);
+ int largePadding = ctx.getResources().getDimensionPixelSize(hasThreeLines
+ ? R.dimen.notification_top_pad_large_text_narrow
+ : R.dimen.notification_top_pad_large_text);
+ float largeFactor = (MathUtils.constrain(fontScale, 1.0f, LARGE_TEXT_SCALE) - 1f)
+ / (LARGE_TEXT_SCALE - 1f);
+
+ // Linearly interpolate the padding between large and normal with the font scale ranging
+ // from 1f to LARGE_TEXT_SCALE
+ return Math.round((1 - largeFactor) * padding + largeFactor * largePadding);
+ }
+
private RemoteViews applyStandardTemplateWithActions(int layoutId) {
- RemoteViews big = applyStandardTemplate(layoutId, false);
+ RemoteViews big = applyStandardTemplate(layoutId);
int N = mActions.size();
if (N > 0) {
@@ -2717,7 +2765,7 @@
if (mContentView != null) {
return mContentView;
} else {
- return applyStandardTemplate(getBaseLayoutResource(), true); // no more special large_icon flavor
+ return applyStandardTemplate(getBaseLayoutResource());
}
}
@@ -2810,7 +2858,7 @@
*/
private void applyLargeIconBackground(RemoteViews contentView) {
contentView.setInt(R.id.icon, "setBackgroundResource",
- R.drawable.notification_icon_legacy_bg_inset);
+ R.drawable.notification_icon_legacy_bg);
contentView.setDrawableParameters(
R.id.icon,
@@ -2819,6 +2867,10 @@
resolveColor(),
PorterDuff.Mode.SRC_ATOP,
-1);
+
+ int padding = mContext.getResources().getDimensionPixelSize(
+ R.dimen.notification_large_icon_circle_padding);
+ contentView.setViewPadding(R.id.icon, padding, padding, padding, padding);
}
private void removeLargeIconBackground(RemoteViews contentView) {
@@ -3234,7 +3286,7 @@
}
private int getBigTextLayoutResource() {
- return getBigBaseLayoutResource();
+ return R.layout.notification_template_material_big_text;
}
private int getInboxLayoutResource() {
@@ -3320,6 +3372,8 @@
contentView.setViewVisibility(R.id.overflow_divider, View.VISIBLE);
contentView.setViewVisibility(R.id.line3, View.VISIBLE);
} else {
+ // Clear text in case we use the line to show the profile badge.
+ contentView.setTextViewText(R.id.text, "");
contentView.setViewVisibility(R.id.overflow_divider, View.GONE);
contentView.setViewVisibility(R.id.line3, View.GONE);
}
@@ -3328,6 +3382,19 @@
}
/**
+ * Changes the padding of the first line such that the big and small content view have the
+ * same top padding.
+ *
+ * @hide
+ */
+ protected void applyTopPadding(RemoteViews contentView) {
+ int topPadding = Builder.calculateTopPadding(mBuilder.mContext,
+ mBuilder.hasThreeLines(),
+ mBuilder.mContext.getResources().getConfiguration().fontScale);
+ contentView.setViewPadding(R.id.line1, 0, topPadding, 0, 0);
+ }
+
+ /**
* @hide
*/
public void addExtras(Bundle extras) {
@@ -3465,6 +3532,11 @@
contentView.setImageViewBitmap(R.id.big_picture, mPicture);
+ applyTopPadding(contentView);
+
+ boolean twoTextLines = mBuilder.mSubText != null && mBuilder.mContentText != null;
+ mBuilder.addProfileBadge(contentView,
+ twoTextLines ? R.id.profile_badge_line2 : R.id.profile_badge_line3);
return contentView;
}
@@ -3575,8 +3647,6 @@
}
private RemoteViews makeBigContentView() {
- // Remove the content text so line3 only shows if you have a summary
- final boolean hadThreeLines = (mBuilder.mContentText != null && mBuilder.mSubText != null);
// Nasty
CharSequence oldBuilderContentText = mBuilder.mContentText;
@@ -3586,15 +3656,14 @@
mBuilder.mContentText = oldBuilderContentText;
- if (hadThreeLines) {
- // vertical centering
- contentView.setViewPadding(R.id.line1, 0, 0, 0, 0);
- }
-
contentView.setTextViewText(R.id.big_text, mBuilder.processLegacyText(mBigText));
contentView.setViewVisibility(R.id.big_text, View.VISIBLE);
contentView.setViewVisibility(R.id.text2, View.GONE);
+ applyTopPadding(contentView);
+
+ mBuilder.addProfileBadge(contentView, R.id.profile_badge_large_template);
+
return contentView;
}
@@ -3706,13 +3775,20 @@
contentView.setViewVisibility(rowId, View.GONE);
}
-
+ final boolean largeText =
+ mBuilder.mContext.getResources().getConfiguration().fontScale > 1f;
+ final float subTextSize = mBuilder.mContext.getResources().getDimensionPixelSize(
+ R.dimen.notification_subtext_size);
int i=0;
while (i < mTexts.size() && i < rowIds.length) {
CharSequence str = mTexts.get(i);
if (str != null && !str.equals("")) {
contentView.setViewVisibility(rowIds[i], View.VISIBLE);
contentView.setTextViewText(rowIds[i], mBuilder.processLegacyText(str));
+ if (largeText) {
+ contentView.setTextViewTextSize(rowIds[i], TypedValue.COMPLEX_UNIT_PX,
+ subTextSize);
+ }
}
i++;
}
@@ -3723,6 +3799,10 @@
contentView.setViewVisibility(R.id.inbox_more,
mTexts.size() > rowIds.length ? View.VISIBLE : View.GONE);
+ applyTopPadding(contentView);
+
+ mBuilder.addProfileBadge(contentView, R.id.profile_badge_large_template);
+
return contentView;
}
@@ -3876,7 +3956,7 @@
private RemoteViews makeMediaContentView() {
RemoteViews view = mBuilder.applyStandardTemplate(
- R.layout.notification_template_material_media, true /* 1U */);
+ R.layout.notification_template_material_media);
final int numActions = mBuilder.mActions.size();
final int N = mActionsToShowInCompact == null
@@ -3901,7 +3981,7 @@
private RemoteViews makeMediaBigContentView() {
RemoteViews big = mBuilder.applyStandardTemplate(
- R.layout.notification_template_material_big_media, false);
+ R.layout.notification_template_material_big_media);
final int N = Math.min(mBuilder.mActions.size(), MAX_MEDIA_BUTTONS);
if (N > 0) {
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 3c13115..1691d8e 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -178,8 +178,13 @@
//}
AssetManager assets = new AssetManager();
- if (assets.addAssetPath(resDir) == 0) {
- return null;
+ // resDir can be null if the 'android' package is creating a new Resources object.
+ // This is fine, since each AssetManager automatically loads the 'android' package
+ // already.
+ if (resDir != null) {
+ if (assets.addAssetPath(resDir) == 0) {
+ return null;
+ }
}
if (splitResDirs != null) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 053afb7..0dc8f66 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -55,7 +55,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Set;
/**
* Public interface for managing policies enforced on a device. Most clients
@@ -124,10 +123,10 @@
* application that started provisioning. The package will be set as profile owner in that case.
*
* <p>This package is set as device owner when device owner provisioning is started by an Nfc
- * message containing an Nfc record with MIME type {@link #PROVISIONING_NFC_MIME_TYPE}.
+ * message containing an Nfc record with MIME type {@link #MIME_TYPE_PROVISIONING_NFC}.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME
- = "android.app.extra.deviceAdminPackageName";
+ = "android.app.extra.DEVICE_ADMIN_PACKAGE_NAME";
/**
* A String extra holding the default name of the profile that is created during managed profile
@@ -136,7 +135,7 @@
* <p>Use with {@link #ACTION_PROVISION_MANAGED_PROFILE}
*/
public static final String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME
- = "android.app.extra.defaultManagedProfileName";
+ = "android.app.extra.DEFAULT_MANAGED_PROFILE_NAME";
/**
* A String extra that, holds the email address of the account which a managed profile is
@@ -150,137 +149,137 @@
* It is usually used to avoid that the user has to enter their email address twice.
*/
public static final String EXTRA_PROVISIONING_EMAIL_ADDRESS
- = "android.app.extra.ManagedProfileEmailAddress";
+ = "android.app.extra.MANAGED_PROFILE_EMAIL_ADDRESS";
/**
* A String extra holding the time zone {@link android.app.AlarmManager} that the device
* will be set to.
*
- * <p>Use in an Nfc record with {@link #PROVISIONING_NFC_MIME_TYPE} that starts device owner
+ * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_TIME_ZONE
- = "android.app.extra.timeZone";
+ = "android.app.extra.TIME_ZONE";
/**
- * A Long extra holding the local time {@link android.app.AlarmManager} that the device
- * will be set to.
+ * A Long extra holding the wall clock time (in milliseconds) to be set on the device's
+ * {@link android.app.AlarmManager}.
*
- * <p>Use in an Nfc record with {@link #PROVISIONING_NFC_MIME_TYPE} that starts device owner
+ * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_LOCAL_TIME
- = "android.app.extra.localTime";
+ = "android.app.extra.LOCAL_TIME";
/**
* A String extra holding the {@link java.util.Locale} that the device will be set to.
* Format: xx_yy, where xx is the language code, and yy the country code.
*
- * <p>Use in an Nfc record with {@link #PROVISIONING_NFC_MIME_TYPE} that starts device owner
+ * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_LOCALE
- = "android.app.extra.locale";
+ = "android.app.extra.LOCALE";
/**
* A String extra holding the ssid of the wifi network that should be used during nfc device
* owner provisioning for downloading the mobile device management application.
*
- * <p>Use in an Nfc record with {@link #PROVISIONING_NFC_MIME_TYPE} that starts device owner
+ * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_SSID
- = "android.app.extra.wifiSsid";
+ = "android.app.extra.WIFI_SSID";
/**
* A boolean extra indicating whether the wifi network in {@link #EXTRA_PROVISIONING_WIFI_SSID}
* is hidden or not.
*
- * <p>Use in an Nfc record with {@link #PROVISIONING_NFC_MIME_TYPE} that starts device owner
+ * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_HIDDEN
- = "android.app.extra.wifiHidden";
+ = "android.app.extra.WIFI_HIDDEN";
/**
* A String extra indicating the security type of the wifi network in
* {@link #EXTRA_PROVISIONING_WIFI_SSID}.
*
- * <p>Use in an Nfc record with {@link #PROVISIONING_NFC_MIME_TYPE} that starts device owner
+ * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE
- = "android.app.extra.wifiSecurityType";
+ = "android.app.extra.WIFI_SECURITY_TYPE";
/**
* A String extra holding the password of the wifi network in
* {@link #EXTRA_PROVISIONING_WIFI_SSID}.
*
- * <p>Use in an Nfc record with {@link #PROVISIONING_NFC_MIME_TYPE} that starts device owner
+ * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_PASSWORD
- = "android.app.extra.wifiPassword";
+ = "android.app.extra.WIFI_PASSWORD";
/**
* A String extra holding the proxy host for the wifi network in
* {@link #EXTRA_PROVISIONING_WIFI_SSID}.
*
- * <p>Use in an Nfc record with {@link #PROVISIONING_NFC_MIME_TYPE} that starts device owner
+ * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_PROXY_HOST
- = "android.app.extra.wifiProxyHost";
+ = "android.app.extra.WIFI_PROXY_HOST";
/**
* An int extra holding the proxy port for the wifi network in
* {@link #EXTRA_PROVISIONING_WIFI_SSID}.
*
- * <p>Use in an Nfc record with {@link #PROVISIONING_NFC_MIME_TYPE} that starts device owner
+ * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_PROXY_PORT
- = "android.app.extra.wifiProxyPort";
+ = "android.app.extra.WIFI_PROXY_PORT";
/**
* A String extra holding the proxy bypass for the wifi network in
* {@link #EXTRA_PROVISIONING_WIFI_SSID}.
*
- * <p>Use in an Nfc record with {@link #PROVISIONING_NFC_MIME_TYPE} that starts device owner
+ * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_PROXY_BYPASS
- = "android.app.extra.wifiProxyBypassHosts";
+ = "android.app.extra.WIFI_PROXY_BYPASS_HOSTS";
/**
* A String extra holding the proxy auto-config (PAC) URL for the wifi network in
* {@link #EXTRA_PROVISIONING_WIFI_SSID}.
*
- * <p>Use in an Nfc record with {@link #PROVISIONING_NFC_MIME_TYPE} that starts device owner
+ * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_PAC_URL
- = "android.app.extra.wifiPacUrl";
+ = "android.app.extra.WIFI_PAC_URL";
/**
* A String extra holding a url that specifies the download location of the device admin
* package. When not provided it is assumed that the device admin package is already installed.
*
- * <p>Use in an Nfc record with {@link #PROVISIONING_NFC_MIME_TYPE} that starts device owner
+ * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION
- = "android.app.extra.deviceAdminPackageDownloadLocation";
+ = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
/**
* 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_ADMIN_PACKAGE_DOWNLOAD_LOCATION}.
*
- * <p>Use in an Nfc record with {@link #PROVISIONING_NFC_MIME_TYPE} that starts device owner
+ * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER
- = "android.app.extra.deviceAdminPackageDownloadCookieHeader";
+ = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
/**
* A String extra holding the SHA-1 checksum of the file at download location specified in
@@ -288,11 +287,11 @@
* 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 #PROVISIONING_NFC_MIME_TYPE} that starts device owner
+ * <p>Use in an Nfc record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM
- = "android.app.extra.deviceAdminPackageChecksum";
+ = "android.app.extra.DEVICE_ADMIN_PACKAGE_CHECKSUM";
/**
* This MIME type is used for starting the Device Owner provisioning.
@@ -336,7 +335,7 @@
* <p>Input: Nothing.</p>
* <p>Output: Nothing</p>
*/
- public static final String PROVISIONING_NFC_MIME_TYPE
+ public static final String MIME_TYPE_PROVISIONING_NFC
= "application/com.android.managedprovisioning";
/**
@@ -1875,12 +1874,16 @@
}
/**
- * Called by a device/profile owner to set whether the screen capture is disabled.
+ * Called by a device/profile owner to set whether the screen capture is disabled. Disabling
+ * screen capture also prevents the content from being shown on display devices that do not have
+ * a secure video output. See {@link android.view.Display#FLAG_SECURE} for more details about
+ * secure surfaces and secure displays.
*
* <p>The calling device admin must be a device or profile owner. If it is not, a
* security exception will be thrown.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param disabled Whether or not screen capture should be disabled.
*/
public void setScreenCaptureDisabled(ComponentName admin, boolean disabled) {
if (mService != null) {
@@ -2157,6 +2160,7 @@
}
/** @hide */
+ @SystemApi
public String getDeviceOwner() {
if (mService != null) {
try {
@@ -2365,6 +2369,7 @@
* owner has been set for that user.
* @throws IllegalArgumentException if the userId is invalid.
*/
+ @SystemApi
public ComponentName getProfileOwner() throws IllegalArgumentException {
return getProfileOwnerAsUser(Process.myUserHandle().getIdentifier());
}
@@ -2406,6 +2411,27 @@
}
/**
+ * @hide
+ * @param user The user for whom to fetch the profile owner name, if any.
+ * @return the human readable name of the organisation associated with this profile owner or
+ * null if one is not set.
+ * @throws IllegalArgumentException if the userId is invalid.
+ */
+ @SystemApi
+ public String getProfileOwnerNameAsUser(UserHandle user) throws IllegalArgumentException {
+ if (mService != null) {
+ try {
+ return mService.getProfileOwnerName(user.getIdentifier());
+ } catch (RemoteException re) {
+ Log.w(TAG, "Failed to get profile owner");
+ throw new IllegalArgumentException(
+ "Requested profile owner for invalid userId", re);
+ }
+ }
+ return null;
+ }
+
+ /**
* Called by a profile owner or device owner to add a default intent handler activity for
* intents that match a certain intent filter. This activity will remain the default intent
* handler even if the set of potential event handlers for the intent filter changes and if
@@ -2622,6 +2648,161 @@
}
/**
+ * Called by a profile or device owner to set the permitted accessibility services. When
+ * set by a device owner or profile owner the restriction applies to all profiles of the
+ * user the device owner or profile owner is an admin for.
+ *
+ * By default the user can use any accessiblity service. When zero or more packages have
+ * been added, accessiblity services that are not in the list and not part of the system
+ * can not be enabled by the user.
+ *
+ * <p> Calling with a null value for the list disables the restriction so that all services
+ * can be used, calling with an empty list only allows the builtin system's services.
+ *
+ * <p> System accesibility services are always available to the user the list can't modify
+ * this.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param packageNames List of accessibility service package names.
+ *
+ * @return true if setting the restriction succeeded. It fail if there is
+ * one or more non-system accessibility services enabled, that are not in the list.
+ */
+ public boolean setPermittedAccessibilityServices(ComponentName admin,
+ List<String> packageNames) {
+ if (mService != null) {
+ try {
+ return mService.setPermittedAccessibilityServices(admin, packageNames);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the list of permitted accessibility services set by this device or profile owner.
+ *
+ * <p>An empty list means no accessibility services except system services are allowed.
+ * Null means all accessibility services are allowed.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @return List of accessiblity service package names.
+ */
+ public List<String> getPermittedAccessibilityServices(ComponentName admin) {
+ if (mService != null) {
+ try {
+ return mService.getPermittedAccessibilityServices(admin);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the list of accessibility services permitted by the device or profiles
+ * owners of this user.
+ *
+ * <p>Null means all accessibility services are allowed, if a non-null list is returned
+ * it will contain the intersection of the permitted lists for any device or profile
+ * owners that apply to this user. It will also include any system accessibility services.
+ *
+ * @param userId which user to check for.
+ * @return List of accessiblity service package names.
+ * @hide
+ */
+ @SystemApi
+ public List<String> getPermittedAccessibilityServices(int userId) {
+ if (mService != null) {
+ try {
+ return mService.getPermittedAccessibilityServicesForUser(userId);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Called by a profile or device owner to set the permitted input methods services. When
+ * set by a device owner or profile owner the restriction applies to all profiles of the
+ * user the device owner or profile owner is an admin for.
+ *
+ * By default the user can use any input method. When zero or more packages have
+ * been added, input method that are not in the list and not part of the system
+ * can not be enabled by the user.
+ *
+ * This method will fail if it is called for a admin that is not for the foreground user
+ * or a profile of the foreground user.
+ *
+ * <p> Calling with a null value for the list disables the restriction so that all input methods
+ * can be used, calling with an empty list disables all but the system's own input methods.
+ *
+ * <p> System input methods are always available to the user this method can't modify this.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param packageNames List of input method package names.
+ * @return true if setting the restriction succeeded. It will fail if there is
+ * one or more input method enabled, that are not in the list or user if the foreground
+ * user.
+ */
+ public boolean setPermittedInputMethods(ComponentName admin, List<String> packageNames) {
+ if (mService != null) {
+ try {
+ return mService.setPermittedInputMethods(admin, packageNames);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * Returns the list of permitted input methods set by this device or profile owner.
+ *
+ * <p>An empty list means no input methods except system input methods are allowed.
+ * Null means all input methods are allowed.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @return List of input method package names.
+ */
+ public List<String> getPermittedInputMethods(ComponentName admin) {
+ if (mService != null) {
+ try {
+ return mService.getPermittedInputMethods(admin);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the list of input methods permitted by the device or profiles
+ * owners of the current user.
+ *
+ * <p>Null means all input methods are allowed, if a non-null list is returned
+ * it will contain the intersection of the permitted lists for any device or profile
+ * owners that apply to this user. It will also include any system input methods.
+ *
+ * @return List of input method package names.
+ * @hide
+ */
+ @SystemApi
+ public List<String> getPermittedInputMethodsForCurrentUser() {
+ if (mService != null) {
+ try {
+ return mService.getPermittedInputMethodsForCurrentUser();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return null;
+ }
+
+ /**
* Called by a device owner to create a user with the specified name. The UserHandle returned
* by this method should not be persisted as user handles are recycled as users are removed and
* created. If you need to persist an identifier for this user, use
@@ -2802,28 +2983,6 @@
}
/**
- * Called by profile or device owner to hide or unhide currently installed packages. This
- * should only be called by a profile or device owner running within a managed profile.
- *
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @param intent An intent matching the app(s) to be updated. All apps that resolve for this
- * intent will be updated in the current profile.
- * @param hidden {@code true} if the packages should be hidden, {@code false} if they should
- * be unhidden.
- * @return int The number of activities that matched the intent and were updated.
- */
- public int setApplicationsHidden(ComponentName admin, Intent intent, boolean hidden) {
- if (mService != null) {
- try {
- return mService.setApplicationsHidden(admin, intent, hidden);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed talking with device policy service", e);
- }
- }
- return 0;
- }
-
- /**
* Called by device or profile owner to determine if a package is hidden.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
@@ -3089,12 +3248,13 @@
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param packageName package to change.
- * @param blockUninstall true if the user shouldn't be able to uninstall the package.
+ * @param uninstallBlocked true if the user shouldn't be able to uninstall the package.
*/
- public void setBlockUninstall(ComponentName admin, String packageName, boolean blockUninstall) {
+ public void setUninstallBlocked(ComponentName admin, String packageName,
+ boolean uninstallBlocked) {
if (mService != null) {
try {
- mService.setBlockUninstall(admin, packageName, blockUninstall);
+ mService.setUninstallBlocked(admin, packageName, uninstallBlocked);
} catch (RemoteException re) {
Log.w(TAG, "Failed to call block uninstall on device policy service");
}
@@ -3109,10 +3269,10 @@
* @param packageName package to check.
* @return true if the user shouldn't be able to uninstall the package.
*/
- public boolean getBlockUninstall(ComponentName admin, String packageName) {
+ public boolean getUninstallBlocked(ComponentName admin, String packageName) {
if (mService != null) {
try {
- return mService.getBlockUninstall(admin, packageName);
+ return mService.getUninstallBlocked(admin, packageName);
} catch (RemoteException re) {
Log.w(TAG, "Failed to call block uninstall on device policy service");
}
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index edd8199..a1f1d92 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -26,6 +26,22 @@
public abstract class DevicePolicyManagerInternal {
/**
+ * Listener for changes in the white-listed packages to show cross-profile
+ * widgets.
+ */
+ public interface OnCrossProfileWidgetProvidersChangeListener {
+
+ /**
+ * Called when the white-listed packages to show cross-profile widgets
+ * have changed for a given user.
+ *
+ * @param profileId The profile for which the white-listed packages changed.
+ * @param packages The white-listed packages.
+ */
+ public void onCrossProfileWidgetProvidersChanged(int profileId, List<String> packages);
+ }
+
+ /**
* Gets the packages whose widget providers are white-listed to be
* available in the parent user.
*
@@ -35,4 +51,13 @@
* profile.
*/
public abstract List<String> getCrossProfileWidgetProviders(int profileId);
+
+ /**
+ * Adds a listener for changes in the white-listed packages to show
+ * cross-profile app widgets.
+ *
+ * @param listener The listener to add.
+ */
+ public abstract void addOnCrossProfileWidgetProvidersChangeListener(
+ OnCrossProfileWidgetProvidersChangeListener listener);
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 324b963..1e17bb6 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -24,6 +24,7 @@
import android.os.Bundle;
import android.os.RemoteCallback;
import android.os.UserHandle;
+import java.util.List;
/**
* Internal IPC interface to the device policy service.
@@ -137,8 +138,15 @@
void addCrossProfileIntentFilter(in ComponentName admin, in IntentFilter filter, int flags);
void clearCrossProfileIntentFilters(in ComponentName admin);
+ boolean setPermittedAccessibilityServices(in ComponentName admin,in List packageList);
+ List getPermittedAccessibilityServices(in ComponentName admin);
+ List getPermittedAccessibilityServicesForUser(int userId);
+
+ boolean setPermittedInputMethods(in ComponentName admin,in List packageList);
+ List getPermittedInputMethods(in ComponentName admin);
+ List getPermittedInputMethodsForCurrentUser();
+
boolean setApplicationHidden(in ComponentName admin, in String packageName, boolean hidden);
- int setApplicationsHidden(in ComponentName admin, in Intent intent, boolean hidden);
boolean isApplicationHidden(in ComponentName admin, in String packageName);
UserHandle createUser(in ComponentName who, in String name);
@@ -165,8 +173,8 @@
void notifyLockTaskModeChanged(boolean isEnabled, String pkg, int userId);
- void setBlockUninstall(in ComponentName admin, in String packageName, boolean blockUninstall);
- boolean getBlockUninstall(in ComponentName admin, in String packageName);
+ void setUninstallBlocked(in ComponentName admin, in String packageName, boolean uninstallBlocked);
+ boolean getUninstallBlocked(in ComponentName admin, in String packageName);
void setCrossProfileCallerIdDisabled(in ComponentName who, boolean disabled);
boolean getCrossProfileCallerIdDisabled(in ComponentName who);
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 936e205..b7af544 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -434,6 +434,12 @@
* @return The job object to hand to the JobScheduler. This object is immutable.
*/
public JobInfo build() {
+ // Allow tasks with no constraints. What am I, a database?
+ if (!mHasEarlyConstraint && !mHasLateConstraint && !mRequiresCharging &&
+ !mRequiresDeviceIdle && mNetworkCapabilities == NetworkType.NONE) {
+ throw new IllegalArgumentException("You're trying to build a job with no " +
+ "constraints, this is not allowed.");
+ }
mExtras = new PersistableBundle(mExtras); // Make our own copy.
// Check that a deadline was not set on a periodic job.
if (mIsPeriodic && (mMaxExecutionDelayMillis != 0L)) {
diff --git a/core/java/android/app/job/JobScheduler.java b/core/java/android/app/job/JobScheduler.java
index 7fe192c..ca7022d 100644
--- a/core/java/android/app/job/JobScheduler.java
+++ b/core/java/android/app/job/JobScheduler.java
@@ -22,7 +22,13 @@
/**
* Class for scheduling various types of jobs with the scheduling framework on the device.
- *
+ * See {@link android.app.job.JobInfo} for more description of the types of jobs that can be run
+ * and how to construct them.
+ * The framework will be intelligent about when you receive your callbacks, and attempt to batch
+ * and defer them as much as possible. Typically if you don't specify a deadline on your job, it
+ * can be run at any moment depending on the current state of the JobScheduler's internal queue,
+ * however it might be deferred as long as until the next time the device is connected to a power
+ * source.
* <p>You do not
* instantiate this class directly; instead, retrieve it through
* {@link android.content.Context#getSystemService
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 59d7956..d77a77b 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -96,19 +96,19 @@
* Bluetooth SIG. This is the default value if no connection parameter update
* is requested.
*/
- public static final int GATT_CONNECTION_BALANCED = 0;
+ public static final int CONNECTION_PRIORITY_BALANCED = 0;
/**
* Connection paramter update - Request a high priority, low latency connection.
* An application should only request high priority connection paramters to transfer
* large amounts of data over LE quickly. Once the transfer is complete, the application
- * should request {@link BluetoothGatt#GATT_CONNECTION_BALANCED} connectoin parameters
+ * should request {@link BluetoothGatt#CONNECTION_PRIORITY_BALANCED} connectoin parameters
* to reduce energy use.
*/
- public static final int GATT_CONNECTION_HIGH_PRIORITY = 1;
+ public static final int CONNECTION_PRIORITY_HIGH = 1;
/** Connection paramter update - Request low power, reduced data rate connection parameters. */
- public static final int GATT_CONNECTION_LOW_POWER = 2;
+ public static final int CONNECTION_PRIORITY_LOW_POWER = 2;
/**
* No authentication required.
@@ -601,7 +601,7 @@
return;
}
try {
- mCallback.onConfigureMTU(BluetoothGatt.this, mtu, status);
+ mCallback.onMtuChanged(BluetoothGatt.this, mtu, status);
} catch (Exception ex) {
Log.w(TAG, "Unhandled exception in callback", ex);
}
@@ -1239,20 +1239,20 @@
}
/**
- * Configure the MTU used for a given connection.
+ * Request an MTU size used for a given connection.
*
* <p>When performing a write request operation (write without response),
* the data sent is truncated to the MTU size. This function may be used
- * to request a larget MTU size to be able to send more data at once.
+ * to request a larger MTU size to be able to send more data at once.
*
- * <p>A {@link BluetoothGattCallback#onConfigureMTU} callback will indicate
+ * <p>A {@link BluetoothGattCallback#onMtuChanged} callback will indicate
* whether this operation was successful.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return true, if the new MTU value has been requested successfully
*/
- public boolean configureMTU(int mtu) {
+ public boolean requestMtu(int mtu) {
if (DBG) Log.d(TAG, "configureMTU() - device: " + mDevice.getAddress()
+ " mtu: " + mtu);
if (mService == null || mClientIf == 0) return false;
@@ -1274,19 +1274,19 @@
* remote device.
*
* @param connectionPriority Request a specific connection priority. Must be one of
- * {@link BluetoothGatt#GATT_CONNECTION_BALANCED},
- * {@link BluetoothGatt#GATT_CONNECTION_HIGH_PRIORITY}
- * or {@link BluetoothGatt#GATT_CONNECTION_LOW_POWER}.
+ * {@link BluetoothGatt#CONNECTION_PRIORITY_BALANCED},
+ * {@link BluetoothGatt#CONNECTION_PRIORITY_HIGH}
+ * or {@link BluetoothGatt#CONNECTION_PRIORITY_LOW_POWER}.
* @throws IllegalArgumentException If the parameters are outside of their
* specified range.
*/
- public boolean requestConnectionParameterUpdate(int connectionPriority) {
- if (connectionPriority < GATT_CONNECTION_BALANCED ||
- connectionPriority > GATT_CONNECTION_LOW_POWER) {
+ public boolean requestConnectionPriority(int connectionPriority) {
+ if (connectionPriority < CONNECTION_PRIORITY_BALANCED ||
+ connectionPriority > CONNECTION_PRIORITY_LOW_POWER) {
throw new IllegalArgumentException("connectionPriority not within valid range");
}
- if (DBG) Log.d(TAG, "requestConnectionParameterUpdate() - params: " + connectionPriority);
+ if (DBG) Log.d(TAG, "requestConnectionPriority() - params: " + connectionPriority);
if (mService == null || mClientIf == 0) return false;
try {
diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java
index 5817d68..19900ec 100644
--- a/core/java/android/bluetooth/BluetoothGattCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattCallback.java
@@ -143,14 +143,14 @@
* Callback indicating the MTU for a given device connection has changed.
*
* This callback is triggered in response to the
- * {@link BluetoothGatt#configureMTU} function, or in response to a connection
+ * {@link BluetoothGatt#requestMtu} function, or in response to a connection
* event.
*
- * @param gatt GATT client invoked {@link BluetoothGatt#configureMTU}
+ * @param gatt GATT client invoked {@link BluetoothGatt#requestMtu}
* @param mtu The new MTU size
* @param status {@link BluetoothGatt#GATT_SUCCESS} if the MTU has been changed successfully
*/
- public void onConfigureMTU(BluetoothGatt gatt, int mtu, int status) {
+ public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
}
/**
diff --git a/core/java/android/bluetooth/BluetoothGattServerCallback.java b/core/java/android/bluetooth/BluetoothGattServerCallback.java
index 3a1b38ee..b0ddc26 100644
--- a/core/java/android/bluetooth/BluetoothGattServerCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattServerCallback.java
@@ -141,7 +141,7 @@
* notifications.
*
* @param device The remote device the notification has been sent to
- * @param status 0 if the operation was successful
+ * @param status {@link BluetoothGatt#GATT_SUCCESS} if the operation was successful
*/
public void onNotificationSent(BluetoothDevice device, int status) {
}
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index f6315ac..3568f26 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -21,7 +21,6 @@
import android.bluetooth.BluetoothGattCallbackWrapper;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.IBluetoothGatt;
-import android.bluetooth.IBluetoothGattCallback;
import android.bluetooth.IBluetoothManager;
import android.os.Handler;
import android.os.Looper;
@@ -30,7 +29,6 @@
import android.util.Log;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -108,41 +106,37 @@
public void startAdvertising(AdvertiseSettings settings,
AdvertiseData advertiseData, AdvertiseData scanResponse,
final AdvertiseCallback callback) {
- checkAdapterState();
- if (callback == null) {
- throw new IllegalArgumentException("callback cannot be null");
- }
- if (totalBytes(advertiseData) > MAX_ADVERTISING_DATA_BYTES ||
- totalBytes(scanResponse) > MAX_ADVERTISING_DATA_BYTES) {
- postCallbackFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
- return;
- }
- if (mLeAdvertisers.containsKey(callback)) {
- postCallbackFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED);
- return;
- }
- IBluetoothGatt gatt;
- try {
- gatt = mBluetoothManager.getBluetoothGatt();
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
- postCallbackFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
- return;
- }
- if (!mBluetoothAdapter.isMultipleAdvertisementSupported()) {
- postCallbackFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_FEATURE_UNSUPPORTED);
- return;
- }
- AdvertiseCallbackWrapper wrapper = new AdvertiseCallbackWrapper(callback, advertiseData,
- scanResponse, settings, gatt);
- UUID uuid = UUID.randomUUID();
- try {
- gatt.registerClient(new ParcelUuid(uuid), wrapper);
- if (wrapper.advertiseStarted()) {
- mLeAdvertisers.put(callback, wrapper);
+ synchronized (mLeAdvertisers) {
+ checkAdapterState();
+ if (callback == null) {
+ throw new IllegalArgumentException("callback cannot be null");
}
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to stop advertising", e);
+ if (!mBluetoothAdapter.isMultipleAdvertisementSupported()) {
+ postStartFailure(callback,
+ AdvertiseCallback.ADVERTISE_FAILED_FEATURE_UNSUPPORTED);
+ return;
+ }
+ if (totalBytes(advertiseData) > MAX_ADVERTISING_DATA_BYTES ||
+ totalBytes(scanResponse) > MAX_ADVERTISING_DATA_BYTES) {
+ postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
+ return;
+ }
+ if (mLeAdvertisers.containsKey(callback)) {
+ postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED);
+ return;
+ }
+
+ IBluetoothGatt gatt;
+ try {
+ gatt = mBluetoothManager.getBluetoothGatt();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
+ postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
+ return;
+ }
+ AdvertiseCallbackWrapper wrapper = new AdvertiseCallbackWrapper(callback, advertiseData,
+ scanResponse, settings, gatt);
+ wrapper.startRegisteration();
}
}
@@ -155,23 +149,14 @@
* @param callback {@link AdvertiseCallback} identifies the advertising instance to stop.
*/
public void stopAdvertising(final AdvertiseCallback callback) {
- checkAdapterState();
- if (callback == null) {
- throw new IllegalArgumentException("callback cannot be null");
- }
- AdvertiseCallbackWrapper wrapper = mLeAdvertisers.get(callback);
- if (wrapper == null)
- return;
- try {
- IBluetoothGatt gatt = mBluetoothManager.getBluetoothGatt();
- if (gatt != null)
- gatt.stopMultiAdvertising(wrapper.mClientIf);
-
- if (wrapper.advertiseStopped()) {
- mLeAdvertisers.remove(callback);
+ synchronized (mLeAdvertisers) {
+ checkAdapterState();
+ if (callback == null) {
+ throw new IllegalArgumentException("callback cannot be null");
}
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to stop advertising", e);
+ AdvertiseCallbackWrapper wrapper = mLeAdvertisers.get(callback);
+ if (wrapper == null) return;
+ wrapper.stopAdvertising();
}
}
@@ -186,9 +171,7 @@
// Compute the size of the advertise data.
private int totalBytes(AdvertiseData data) {
- if (data == null) {
- return 0;
- }
+ if (data == null) return 0;
int size = FLAGS_FIELD_BYTES; // flags field is always set.
if (data.getServiceUuids() != null) {
int num16BitUuids = 0;
@@ -243,7 +226,7 @@
/**
* Bluetooth GATT interface callbacks for advertising.
*/
- private static class AdvertiseCallbackWrapper extends BluetoothGattCallbackWrapper {
+ private class AdvertiseCallbackWrapper extends BluetoothGattCallbackWrapper {
private static final int LE_CALLBACK_TIMEOUT_MILLIS = 2000;
private final AdvertiseCallback mAdvertiseCallback;
private final AdvertiseData mAdvertisement;
@@ -269,30 +252,40 @@
mClientIf = 0;
}
- public boolean advertiseStarted() {
- boolean started = false;
+ public void startRegisteration() {
synchronized (this) {
- if (mClientIf == -1) {
- return false;
- }
+ if (mClientIf == -1) return;
+
try {
+ UUID uuid = UUID.randomUUID();
+ mBluetoothGatt.registerClient(new ParcelUuid(uuid), this);
wait(LE_CALLBACK_TIMEOUT_MILLIS);
- } catch (InterruptedException e) {
- Log.e(TAG, "Callback reg wait interrupted: ", e);
+ } catch (InterruptedException | RemoteException e) {
+ Log.e(TAG, "Failed to start registeration", e);
}
- started = (mClientIf > 0 && mIsAdvertising);
+ if (mClientIf > 0 && mIsAdvertising) {
+ mLeAdvertisers.put(mAdvertiseCallback, this);
+ } else {
+ postStartFailure(mAdvertiseCallback,
+ AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
+ }
}
- return started;
}
- public boolean advertiseStopped() {
+ public void stopAdvertising() {
synchronized (this) {
try {
+ mBluetoothGatt.stopMultiAdvertising(mClientIf);
wait(LE_CALLBACK_TIMEOUT_MILLIS);
- } catch (InterruptedException e) {
- Log.e(TAG, "Callback reg wait interrupted: " + e);
+ } catch (InterruptedException | RemoteException e) {
+ Log.e(TAG, "Failed to stop advertising", e);
}
- return !mIsAdvertising;
+ // Advertise callback should have been removed from LeAdvertisers when
+ // onMultiAdvertiseCallback was called. In case onMultiAdvertiseCallback is never
+ // invoked and wait timeout expires, remove callback here.
+ if (mLeAdvertisers.containsKey(mAdvertiseCallback)) {
+ mLeAdvertisers.remove(mAdvertiseCallback);
+ }
}
}
@@ -308,16 +301,14 @@
try {
mBluetoothGatt.startMultiAdvertising(mClientIf, mAdvertisement,
mScanResponse, mSettings);
+ return;
} catch (RemoteException e) {
- Log.e(TAG, "fail to start le advertise: " + e);
- mClientIf = -1;
- notifyAll();
+ Log.e(TAG, "failed to start advertising", e);
}
- } else {
- // registration failed
- mClientIf = -1;
- notifyAll();
}
+ // Registration failed.
+ mClientIf = -1;
+ notifyAll();
}
}
@@ -328,11 +319,11 @@
if (isStart) {
if (status == AdvertiseCallback.ADVERTISE_SUCCESS) {
// Start success
- mAdvertiseCallback.onStartSuccess(settings);
mIsAdvertising = true;
+ postStartSuccess(mAdvertiseCallback, settings);
} else {
// Start failure.
- mAdvertiseCallback.onStartFailure(status);
+ postStartFailure(mAdvertiseCallback, status);
}
} else {
// unregister client for stop.
@@ -340,6 +331,7 @@
mBluetoothGatt.unregisterClient(mClientIf);
mClientIf = -1;
mIsAdvertising = false;
+ mLeAdvertisers.remove(mAdvertiseCallback);
} catch (RemoteException e) {
Log.e(TAG, "remote exception when unregistering", e);
}
@@ -357,12 +349,23 @@
}
}
- private void postCallbackFailure(final AdvertiseCallback callback, final int error) {
+ private void postStartFailure(final AdvertiseCallback callback, final int error) {
mHandler.post(new Runnable() {
- @Override
+ @Override
public void run() {
callback.onStartFailure(error);
}
});
}
+
+ private void postStartSuccess(final AdvertiseCallback callback,
+ final AdvertiseSettings settings) {
+ mHandler.post(new Runnable() {
+
+ @Override
+ public void run() {
+ callback.onStartSuccess(settings);
+ }
+ });
+ }
}
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index 988cea5..e1d4bbd2 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -130,20 +130,7 @@
}
BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters,
settings, callback, resultStorages);
- try {
- UUID uuid = UUID.randomUUID();
- gatt.registerClient(new ParcelUuid(uuid), wrapper);
- if (wrapper.scanStarted()) {
- mLeScanClients.put(callback, wrapper);
- } else {
- postCallbackError(callback,
- ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED);
- return;
- }
- } catch (RemoteException e) {
- Log.e(TAG, "GATT service exception when starting scan", e);
- postCallbackError(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR);
- }
+ wrapper.startRegisteration();
}
}
@@ -159,8 +146,7 @@
synchronized (mLeScanClients) {
BleScanCallbackWrapper wrapper = mLeScanClients.remove(callback);
if (wrapper == null) {
- if (DBG)
- Log.d(TAG, "could not find callback wrapper");
+ if (DBG) Log.d(TAG, "could not find callback wrapper");
return;
}
wrapper.stopLeScan();
@@ -220,8 +206,8 @@
/**
* Bluetooth GATT interface callbacks
*/
- private static class BleScanCallbackWrapper extends BluetoothGattCallbackWrapper {
- private static final int REGISTRATION_CALLBACK_TIMEOUT_SECONDS = 5;
+ private class BleScanCallbackWrapper extends BluetoothGattCallbackWrapper {
+ private static final int REGISTRATION_CALLBACK_TIMEOUT_MILLIS = 2000;
private final ScanCallback mScanCallback;
private final List<ScanFilter> mFilters;
@@ -245,18 +231,25 @@
mResultStorages = resultStorages;
}
- public boolean scanStarted() {
+ public void startRegisteration() {
synchronized (this) {
- if (mClientIf == -1) {
- return false;
- }
+ // Scan stopped.
+ if (mClientIf == -1) return;
try {
- wait(REGISTRATION_CALLBACK_TIMEOUT_SECONDS);
- } catch (InterruptedException e) {
- Log.e(TAG, "Callback reg wait interrupted: " + e);
+ UUID uuid = UUID.randomUUID();
+ mBluetoothGatt.registerClient(new ParcelUuid(uuid), this);
+ wait(REGISTRATION_CALLBACK_TIMEOUT_MILLIS);
+ } catch (InterruptedException | RemoteException e) {
+ Log.e(TAG, "application registeration exception", e);
+ postCallbackError(mScanCallback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR);
+ }
+ if (mClientIf > 0) {
+ mLeScanClients.put(mScanCallback, this);
+ } else {
+ postCallbackError(mScanCallback,
+ ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED);
}
}
- return mClientIf > 0;
}
public void stopLeScan() {
@@ -272,7 +265,6 @@
Log.e(TAG, "Failed to stop scan and unregister", e);
}
mClientIf = -1;
- notifyAll();
}
}
@@ -297,11 +289,9 @@
public void onClientRegistered(int status, int clientIf) {
Log.d(TAG, "onClientRegistered() - status=" + status +
" clientIf=" + clientIf);
-
synchronized (this) {
if (mClientIf == -1) {
- if (DBG)
- Log.d(TAG, "onClientRegistered LE scan canceled");
+ if (DBG) Log.d(TAG, "onClientRegistered LE scan canceled");
}
if (status == BluetoothGatt.GATT_SUCCESS) {
@@ -328,17 +318,15 @@
*/
@Override
public void onScanResult(final ScanResult scanResult) {
- if (DBG)
- Log.d(TAG, "onScanResult() - " + scanResult.toString());
+ if (DBG) Log.d(TAG, "onScanResult() - " + scanResult.toString());
// Check null in case the scan has been stopped
synchronized (this) {
- if (mClientIf <= 0)
- return;
+ if (mClientIf <= 0) return;
}
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
- @Override
+ @Override
public void run() {
mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult);
}
@@ -350,7 +338,7 @@
public void onBatchScanResults(final List<ScanResult> results) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
- @Override
+ @Override
public void run() {
mScanCallback.onBatchScanResults(results);
}
@@ -394,7 +382,7 @@
private void postCallbackError(final ScanCallback callback, final int errorCode) {
mHandler.post(new Runnable() {
- @Override
+ @Override
public void run() {
callback.onScanFailed(errorCode);
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 4ac701f..7419ebc 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -105,10 +105,14 @@
public static final String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE";
/**
- * List of package names that are relevant to a status.
+ * Package name relevant to a status.
*
- * @see Intent#getStringArrayExtra(String)
+ * @see Intent#getStringExtra(String)
*/
+ public static final String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
+
+ /** {@hide} */
+ @Deprecated
public static final String EXTRA_PACKAGE_NAMES = "android.content.pm.extra.PACKAGE_NAMES";
/** {@hide} */
@@ -178,8 +182,8 @@
* permission, incompatible certificates, etc. The user may be able to
* uninstall another app to fix the issue.
* <p>
- * The result may also contain {@link #EXTRA_PACKAGE_NAMES} with the
- * specific packages identified as the cause of the conflict.
+ * The result may also contain {@link #EXTRA_PACKAGE_NAME} with the
+ * specific package identified as the cause of the conflict.
*
* @see #EXTRA_STATUS_MESSAGE
*/
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 2c50f25..eb8b762 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -596,7 +596,7 @@
public final static int PARSE_ON_SDCARD = 1<<5;
public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
public final static int PARSE_IS_PRIVILEGED = 1<<7;
- public final static int PARSE_GET_SIGNATURES = 1<<8;
+ public final static int PARSE_COLLECT_CERTIFICATES = 1<<8;
public final static int PARSE_TRUSTED_OVERLAY = 1<<9;
private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
@@ -1087,34 +1087,6 @@
}
}
- /**
- * Only collect certificates on the manifest; does not validate signatures
- * across remainder of package.
- */
- private static Signature[] collectManifestCertificates(File apkFile)
- throws PackageParserException {
- final String apkPath = apkFile.getAbsolutePath();
- try {
- final StrictJarFile jarFile = new StrictJarFile(apkPath);
- try {
- final ZipEntry jarEntry = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
- if (jarEntry == null) {
- throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
- "Package " + apkPath + " has no manifest");
- }
-
- final Certificate[][] certs = loadCertificates(jarFile, jarEntry);
- return convertToSignatures(certs);
-
- } finally {
- jarFile.close();
- }
- } catch (GeneralSecurityException | IOException | RuntimeException e) {
- throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING,
- "Failed to collect certificates from " + apkPath, e);
- }
- }
-
private static Signature[] convertToSignatures(Certificate[][] certs)
throws CertificateEncodingException {
final Signature[] res = new Signature[certs.length];
@@ -1129,7 +1101,8 @@
* file, including package name, split name, and install location.
*
* @param apkFile path to a single APK
- * @param flags optional parse flags, such as {@link #PARSE_GET_SIGNATURES}
+ * @param flags optional parse flags, such as
+ * {@link #PARSE_COLLECT_CERTIFICATES}
*/
public static ApkLite parseApkLite(File apkFile, int flags)
throws PackageParserException {
@@ -1154,11 +1127,12 @@
final Resources res = new Resources(assets, metrics, null);
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
- // Only collect certificates on the manifest; does not validate
- // signatures across remainder of package.
final Signature[] signatures;
- if ((flags & PARSE_GET_SIGNATURES) != 0) {
- signatures = collectManifestCertificates(apkFile);
+ if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
+ // TODO: factor signature related items out of Package object
+ final Package tempPkg = new Package(null);
+ collectCertificates(tempPkg, apkFile, 0);
+ signatures = tempPkg.mSignatures;
} else {
signatures = null;
}
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index a83bd4a..d19418b 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1470,6 +1470,12 @@
case 320:
parts.add("xhdpi");
break;
+ case 480:
+ parts.add("xxhdpi");
+ break;
+ case 640:
+ parts.add("xxxhdpi");
+ break;
default:
parts.add(config.densityDpi + "dpi");
break;
@@ -1542,7 +1548,7 @@
break;
}
- parts.add("v" + Build.VERSION.SDK_INT);
+ parts.add("v" + Build.VERSION.RESOURCES_SDK_INT);
return TextUtils.join("-", parts);
}
}
diff --git a/core/java/android/content/res/ResourcesKey.java b/core/java/android/content/res/ResourcesKey.java
index 53e0f2c..e0f1b3a 100644
--- a/core/java/android/content/res/ResourcesKey.java
+++ b/core/java/android/content/res/ResourcesKey.java
@@ -62,8 +62,12 @@
return false;
}
ResourcesKey peer = (ResourcesKey) obj;
- if (!mResDir.equals(peer.mResDir)) {
- return false;
+ if (mResDir != peer.mResDir) {
+ if (mResDir == null || peer.mResDir == null) {
+ return false;
+ } else if (!mResDir.equals(peer.mResDir)) {
+ return false;
+ }
}
if (mDisplayId != peer.mDisplayId) {
return false;
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index d60a2c2..b52a0c5 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -348,7 +348,7 @@
* A sensor of this type returns the number of steps taken by the user since the last reboot
* while activated. The value is returned as a float (with the fractional part set to zero) and
* is reset to zero only on a system reboot. The timestamp of the event is set to the time when
- * the first step for that event was taken. This sensor is implemented in hardware and is
+ * the last step for that event was taken. This sensor is implemented in hardware and is
* expected to be low power.
* <p>
* See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 4e7f9dd..c525348 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -313,18 +313,18 @@
/**
* <p>The set of aberration correction modes supported by this camera device.</p>
- * <p>This metadata lists the valid modes for {@link CaptureRequest#COLOR_CORRECTION_ABERRATION_CORRECTION_MODE android.colorCorrection.aberrationCorrectionMode}.
+ * <p>This metadata lists the valid modes for {@link CaptureRequest#COLOR_CORRECTION_ABERRATION_MODE android.colorCorrection.aberrationMode}.
* If no aberration correction modes are available for a device, this list will solely include
* OFF mode.</p>
* <p>For FULL capability device ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} <code>==</code> FULL), OFF must be
* included.</p>
*
- * @see CaptureRequest#COLOR_CORRECTION_ABERRATION_CORRECTION_MODE
+ * @see CaptureRequest#COLOR_CORRECTION_ABERRATION_MODE
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
*/
@PublicKey
- public static final Key<int[]> COLOR_CORRECTION_AVAILABLE_ABERRATION_CORRECTION_MODES =
- new Key<int[]>("android.colorCorrection.availableAberrationCorrectionModes", int[].class);
+ public static final Key<int[]> COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES =
+ new Key<int[]>("android.colorCorrection.availableAberrationModes", int[].class);
/**
* <p>The set of auto-exposure antibanding modes that are
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 9bdfe8b..3c9b7b3 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -386,8 +386,8 @@
* </ul>
* </li>
* <li>Manual aberration correction control (if aberration correction is supported)<ul>
- * <li>{@link CaptureRequest#COLOR_CORRECTION_ABERRATION_CORRECTION_MODE android.colorCorrection.aberrationCorrectionMode}</li>
- * <li>{@link CameraCharacteristics#COLOR_CORRECTION_AVAILABLE_ABERRATION_CORRECTION_MODES android.colorCorrection.availableAberrationCorrectionModes}</li>
+ * <li>{@link CaptureRequest#COLOR_CORRECTION_ABERRATION_MODE android.colorCorrection.aberrationMode}</li>
+ * <li>{@link CameraCharacteristics#COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES android.colorCorrection.availableAberrationModes}</li>
* </ul>
* </li>
* </ul>
@@ -396,8 +396,8 @@
* <p>A given camera device may also support additional post-processing
* controls, but this capability only covers the above list of controls.</p>
*
- * @see CaptureRequest#COLOR_CORRECTION_ABERRATION_CORRECTION_MODE
- * @see CameraCharacteristics#COLOR_CORRECTION_AVAILABLE_ABERRATION_CORRECTION_MODES
+ * @see CaptureRequest#COLOR_CORRECTION_ABERRATION_MODE
+ * @see CameraCharacteristics#COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES
* @see CaptureRequest#COLOR_CORRECTION_GAINS
* @see CaptureRequest#COLOR_CORRECTION_TRANSFORM
* @see CaptureRequest#SHADING_MODE
@@ -739,28 +739,28 @@
public static final int COLOR_CORRECTION_MODE_HIGH_QUALITY = 2;
//
- // Enumeration values for CaptureRequest#COLOR_CORRECTION_ABERRATION_CORRECTION_MODE
+ // Enumeration values for CaptureRequest#COLOR_CORRECTION_ABERRATION_MODE
//
/**
* <p>No aberration correction is applied.</p>
- * @see CaptureRequest#COLOR_CORRECTION_ABERRATION_CORRECTION_MODE
+ * @see CaptureRequest#COLOR_CORRECTION_ABERRATION_MODE
*/
- public static final int COLOR_CORRECTION_ABERRATION_CORRECTION_MODE_OFF = 0;
+ public static final int COLOR_CORRECTION_ABERRATION_MODE_OFF = 0;
/**
* <p>Aberration correction will not slow down capture rate
* relative to sensor raw output.</p>
- * @see CaptureRequest#COLOR_CORRECTION_ABERRATION_CORRECTION_MODE
+ * @see CaptureRequest#COLOR_CORRECTION_ABERRATION_MODE
*/
- public static final int COLOR_CORRECTION_ABERRATION_CORRECTION_MODE_FAST = 1;
+ public static final int COLOR_CORRECTION_ABERRATION_MODE_FAST = 1;
/**
* <p>Aberration correction operates at improved quality but reduced
* capture rate (relative to sensor raw output).</p>
- * @see CaptureRequest#COLOR_CORRECTION_ABERRATION_CORRECTION_MODE
+ * @see CaptureRequest#COLOR_CORRECTION_ABERRATION_MODE
*/
- public static final int COLOR_CORRECTION_ABERRATION_CORRECTION_MODE_HIGH_QUALITY = 2;
+ public static final int COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY = 2;
//
// Enumeration values for CaptureRequest#CONTROL_AE_ANTIBANDING_MODE
@@ -1213,7 +1213,8 @@
* image while recording video) use case.</p>
* <p>The camera device should take the highest-quality image
* possible (given the other settings) without disrupting the
- * frame rate of video recording. </p>
+ * frame rate of video recording.<br />
+ * </p>
* @see CaptureRequest#CONTROL_CAPTURE_INTENT
*/
public static final int CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT = 4;
diff --git a/core/java/android/hardware/camera2/CaptureFailure.java b/core/java/android/hardware/camera2/CaptureFailure.java
index 2c505e5..b6d3b08 100644
--- a/core/java/android/hardware/camera2/CaptureFailure.java
+++ b/core/java/android/hardware/camera2/CaptureFailure.java
@@ -47,13 +47,13 @@
private final int mReason;
private final boolean mDropped;
private final int mSequenceId;
- private final int mFrameNumber;
+ private final long mFrameNumber;
/**
* @hide
*/
public CaptureFailure(CaptureRequest request, int reason, boolean dropped, int sequenceId,
- int frameNumber) {
+ long frameNumber) {
mRequest = request;
mReason = reason;
mDropped = dropped;
@@ -95,9 +95,9 @@
* for every new result or failure; and the scope is the lifetime of the
* {@link CameraDevice}.</p>
*
- * @return int frame number
+ * @return long frame number
*/
- public int getFrameNumber() {
+ public long getFrameNumber() {
return mFrameNumber;
}
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 97077e6..bcdcd62 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -569,7 +569,7 @@
/**
* <p>Mode of operation for the chromatic aberration correction algorithm.</p>
* <p>This must be set to a valid mode from
- * {@link CameraCharacteristics#COLOR_CORRECTION_AVAILABLE_ABERRATION_CORRECTION_MODES android.colorCorrection.availableAberrationCorrectionModes}.</p>
+ * {@link CameraCharacteristics#COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES android.colorCorrection.availableAberrationModes}.</p>
* <p>Chromatic (color) aberration is caused by the fact that different wavelengths of light
* can not focus on the same point after exiting from the lens. This metadata defines
* the high level control of chromatic aberration correction algorithm, which aims to
@@ -581,14 +581,14 @@
* capture rate. FAST means the camera device will not slow down capture rate when
* applying aberration correction.</p>
*
- * @see CameraCharacteristics#COLOR_CORRECTION_AVAILABLE_ABERRATION_CORRECTION_MODES
- * @see #COLOR_CORRECTION_ABERRATION_CORRECTION_MODE_OFF
- * @see #COLOR_CORRECTION_ABERRATION_CORRECTION_MODE_FAST
- * @see #COLOR_CORRECTION_ABERRATION_CORRECTION_MODE_HIGH_QUALITY
+ * @see CameraCharacteristics#COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES
+ * @see #COLOR_CORRECTION_ABERRATION_MODE_OFF
+ * @see #COLOR_CORRECTION_ABERRATION_MODE_FAST
+ * @see #COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY
*/
@PublicKey
- public static final Key<Integer> COLOR_CORRECTION_ABERRATION_CORRECTION_MODE =
- new Key<Integer>("android.colorCorrection.aberrationCorrectionMode", int.class);
+ public static final Key<Integer> COLOR_CORRECTION_ABERRATION_MODE =
+ new Key<Integer>("android.colorCorrection.aberrationMode", int.class);
/**
* <p>The desired setting for the camera device's auto-exposure
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 63dff55..f9c4df4 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -420,7 +420,7 @@
/**
* <p>Mode of operation for the chromatic aberration correction algorithm.</p>
* <p>This must be set to a valid mode from
- * {@link CameraCharacteristics#COLOR_CORRECTION_AVAILABLE_ABERRATION_CORRECTION_MODES android.colorCorrection.availableAberrationCorrectionModes}.</p>
+ * {@link CameraCharacteristics#COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES android.colorCorrection.availableAberrationModes}.</p>
* <p>Chromatic (color) aberration is caused by the fact that different wavelengths of light
* can not focus on the same point after exiting from the lens. This metadata defines
* the high level control of chromatic aberration correction algorithm, which aims to
@@ -432,14 +432,14 @@
* capture rate. FAST means the camera device will not slow down capture rate when
* applying aberration correction.</p>
*
- * @see CameraCharacteristics#COLOR_CORRECTION_AVAILABLE_ABERRATION_CORRECTION_MODES
- * @see #COLOR_CORRECTION_ABERRATION_CORRECTION_MODE_OFF
- * @see #COLOR_CORRECTION_ABERRATION_CORRECTION_MODE_FAST
- * @see #COLOR_CORRECTION_ABERRATION_CORRECTION_MODE_HIGH_QUALITY
+ * @see CameraCharacteristics#COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES
+ * @see #COLOR_CORRECTION_ABERRATION_MODE_OFF
+ * @see #COLOR_CORRECTION_ABERRATION_MODE_FAST
+ * @see #COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY
*/
@PublicKey
- public static final Key<Integer> COLOR_CORRECTION_ABERRATION_CORRECTION_MODE =
- new Key<Integer>("android.colorCorrection.aberrationCorrectionMode", int.class);
+ public static final Key<Integer> COLOR_CORRECTION_ABERRATION_MODE =
+ new Key<Integer>("android.colorCorrection.aberrationMode", int.class);
/**
* <p>The desired setting for the camera device's auto-exposure
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index a15028c..621968b 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -68,6 +68,8 @@
/** This session is closed; all further calls will throw ISE */
private boolean mClosed = false;
+ /** This session failed to be configured successfully */
+ private final boolean mConfigureSuccess;
/** Do not unconfigure if this is set; another session will overwrite configuration */
private boolean mSkipUnconfigure = false;
@@ -119,10 +121,12 @@
if (configureSuccess) {
mStateListener.onConfigured(this);
if (VERBOSE) Log.v(TAG, "ctor - Created session successfully");
+ mConfigureSuccess = true;
} else {
mStateListener.onConfigureFailed(this);
mClosed = true; // do not fire any other callbacks, do not allow any other work
Log.e(TAG, "Failed to create capture session; configuration failed");
+ mConfigureSuccess = false;
}
}
@@ -285,9 +289,9 @@
// - This session is active, so close() below starts the shutdown drain
// - This session is mid-shutdown drain, and hasn't yet reached the idle drain listener.
// - This session is already closed and has executed the idle drain listener, and
- // configureOutputs(null) has already been called.
+ // configureOutputsChecked(null) has already been called.
//
- // Do not call configureOutputs(null) going forward, since it would race with the
+ // Do not call configureOutputsChecked(null) going forward, since it would race with the
// configuration for the new session. If it was already called, then we don't care, since it
// won't get called again.
mSkipUnconfigure = true;
@@ -506,7 +510,7 @@
public void onUnconfigured(CameraDevice camera) {
synchronized (session) {
// Ignore #onUnconfigured before #close is called
- if (mClosed) {
+ if (mClosed && mConfigureSuccess) {
mUnconfigureDrainer.taskFinished();
}
}
@@ -619,7 +623,7 @@
try {
mUnconfigureDrainer.taskStarted();
- mDeviceImpl.configureOutputs(null); // begin transition to unconfigured state
+ mDeviceImpl.configureOutputsChecked(null); // begin transition to unconfigured
} catch (CameraAccessException e) {
// OK: do not throw checked exceptions.
Log.e(TAG, "Exception while configuring outputs: ", e);
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 71eb0e9..79ce9df 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -312,10 +312,33 @@
}
public void configureOutputs(List<Surface> outputs) throws CameraAccessException {
+ // Leave this here for backwards compatibility with older code using this directly
+ configureOutputsChecked(outputs);
+ }
+
+ /**
+ * Attempt to configure the outputs; the device goes to idle and then configures the
+ * new outputs if possible.
+ *
+ * <p>The configuration may gracefully fail, if there are too many outputs, if the formats
+ * are not supported, or if the sizes for that format is not supported. In this case this
+ * function will return {@code false} and the unconfigured callback will be fired.</p>
+ *
+ * <p>If the configuration succeeds (with 1 or more outputs), then the idle callback is fired.
+ * Unconfiguring the device always fires the idle callback.</p>
+ *
+ * @param outputs a list of one or more surfaces, or {@code null} to unconfigure
+ * @return whether or not the configuration was successful
+ *
+ * @throws CameraAccessException if there were any unexpected problems during configuration
+ */
+ public boolean configureOutputsChecked(List<Surface> outputs) throws CameraAccessException {
// Treat a null input the same an empty list
if (outputs == null) {
outputs = new ArrayList<Surface>();
}
+ boolean success = false;
+
synchronized(mInterfaceLock) {
checkIfCameraClosedOrInError();
@@ -355,7 +378,17 @@
mConfiguredOutputs.put(streamId, s);
}
- mRemoteDevice.endConfigure();
+ try {
+ mRemoteDevice.endConfigure();
+ }
+ catch (IllegalArgumentException e) {
+ // OK. camera service can reject stream config if it's not supported by HAL
+ // This is only the result of a programmer misusing the camera2 api.
+ Log.e(TAG, "Stream configuration failed", e);
+ return false;
+ }
+
+ success = true;
} catch (CameraRuntimeException e) {
if (e.getReason() == CAMERA_IN_USE) {
throw new IllegalStateException("The camera is currently busy." +
@@ -365,15 +398,18 @@
throw e.asChecked();
} catch (RemoteException e) {
// impossible
- return;
- }
-
- if (outputs.size() > 0) {
- mDeviceHandler.post(mCallOnIdle);
- } else {
- mDeviceHandler.post(mCallOnUnconfigured);
+ return false;
+ } finally {
+ if (success && outputs.size() > 0) {
+ mDeviceHandler.post(mCallOnIdle);
+ } else {
+ // Always return to the 'unconfigured' state if we didn't hit a fatal error
+ mDeviceHandler.post(mCallOnUnconfigured);
+ }
}
}
+
+ return success;
}
@Override
@@ -397,7 +433,7 @@
boolean configureSuccess = true;
CameraAccessException pendingException = null;
try {
- configureOutputs(outputs); // and then block until IDLE
+ configureSuccess = configureOutputsChecked(outputs); // and then block until IDLE
} catch (CameraAccessException e) {
configureSuccess = false;
pendingException = e;
diff --git a/core/java/android/hardware/camera2/params/ColorSpaceTransform.java b/core/java/android/hardware/camera2/params/ColorSpaceTransform.java
index b4289db2..1e1c4b1 100644
--- a/core/java/android/hardware/camera2/params/ColorSpaceTransform.java
+++ b/core/java/android/hardware/camera2/params/ColorSpaceTransform.java
@@ -225,7 +225,18 @@
}
if (obj instanceof ColorSpaceTransform) {
final ColorSpaceTransform other = (ColorSpaceTransform) obj;
- return Arrays.equals(mElements, other.mElements);
+ for (int i = 0, j = 0; i < COUNT; ++i, j += RATIONAL_SIZE) {
+ int numerator = mElements[j + OFFSET_NUMERATOR];
+ int denominator = mElements[j + OFFSET_DENOMINATOR];
+ int numeratorOther = other.mElements[j + OFFSET_NUMERATOR];
+ int denominatorOther = other.mElements[j + OFFSET_DENOMINATOR];
+ Rational r = new Rational(numerator, denominator);
+ Rational rOther = new Rational(numeratorOther, denominatorOther);
+ if (!r.equals(rOther)) {
+ return false;
+ }
+ }
+ return true;
}
return false;
}
@@ -238,5 +249,51 @@
return HashCodeHelpers.hashCode(mElements);
}
+ /**
+ * Return the color space transform as a string representation.
+ *
+ * <p> Example:
+ * {@code "ColorSpaceTransform([1/1, 0/1, 0/1], [0/1, 1/1, 0/1], [0/1, 0/1, 1/1])"} is an
+ * identity transform. Elements are printed in row major order. </p>
+ *
+ * @return string representation of color space transform
+ */
+ @Override
+ public String toString() {
+ return String.format("ColorSpaceTransform%s", toShortString());
+ }
+
+ /**
+ * Return the color space transform as a compact string representation.
+ *
+ * <p> Example:
+ * {@code "([1/1, 0/1, 0/1], [0/1, 1/1, 0/1], [0/1, 0/1, 1/1])"} is an identity transform.
+ * Elements are printed in row major order. </p>
+ *
+ * @return compact string representation of color space transform
+ */
+ private String toShortString() {
+ StringBuilder sb = new StringBuilder("(");
+ for (int row = 0, i = 0; row < ROWS; row++) {
+ sb.append("[");
+ for (int col = 0; col < COLUMNS; col++, i += RATIONAL_SIZE) {
+ int numerator = mElements[i + OFFSET_NUMERATOR];
+ int denominator = mElements[i + OFFSET_DENOMINATOR];
+ sb.append(numerator);
+ sb.append("/");
+ sb.append(denominator);
+ if (col < COLUMNS - 1) {
+ sb.append(", ");
+ }
+ }
+ sb.append("]");
+ if (row < ROWS - 1) {
+ sb.append(", ");
+ }
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
private final int[] mElements;
-};
+}
diff --git a/core/java/android/hardware/camera2/params/RggbChannelVector.java b/core/java/android/hardware/camera2/params/RggbChannelVector.java
index cf3e1de..e08ec55d 100644
--- a/core/java/android/hardware/camera2/params/RggbChannelVector.java
+++ b/core/java/android/hardware/camera2/params/RggbChannelVector.java
@@ -190,6 +190,32 @@
Float.floatToIntBits(mBlue);
}
+ /**
+ * Return the RggbChannelVector as a string representation.
+ *
+ * <p> {@code "RggbChannelVector{R:%f, G_even:%f, G_odd:%f, B:%f}"}, where each
+ * {@code %f} respectively represents one of the the four color channels. </p>
+ *
+ * @return string representation of {@link RggbChannelVector}
+ */
+ @Override
+ public String toString() {
+ return String.format("RggbChannelVector%s", toShortString());
+ }
+
+ /**
+ * Return the RggbChannelVector as a string in compact form.
+ *
+ * <p> {@code "{R:%f, G_even:%f, G_odd:%f, B:%f}"}, where each {@code %f}
+ * respectively represents one of the the four color channels. </p>
+ *
+ * @return compact string representation of {@link RggbChannelVector}
+ */
+ private String toShortString() {
+ return String.format("{R:%f, G_even:%f, G_odd:%f, B:%f}",
+ mRed, mGreenEven, mGreenOdd, mBlue);
+ }
+
private final float mRed;
private final float mGreenEven;
private final float mGreenOdd;
diff --git a/core/java/android/hardware/hdmi/HdmiClient.java b/core/java/android/hardware/hdmi/HdmiClient.java
index f95ed0f..aba90e47 100644
--- a/core/java/android/hardware/hdmi/HdmiClient.java
+++ b/core/java/android/hardware/hdmi/HdmiClient.java
@@ -50,7 +50,7 @@
try {
mService.sendKeyEvent(getDeviceType(), keyCode, isPressed);
} catch (RemoteException e) {
- Log.e(TAG, "queryDisplayStatus threw exception ", e);
+ Log.e(TAG, "sendKeyEvent threw exception ", e);
}
}
diff --git a/core/java/android/hardware/hdmi/HdmiTvClient.java b/core/java/android/hardware/hdmi/HdmiTvClient.java
index 354c05e..c37fb5b 100644
--- a/core/java/android/hardware/hdmi/HdmiTvClient.java
+++ b/core/java/android/hardware/hdmi/HdmiTvClient.java
@@ -35,6 +35,11 @@
public final class HdmiTvClient extends HdmiClient {
private static final String TAG = "HdmiTvClient";
+ /**
+ * Size of MHL scratchpad register.
+ */
+ public static final int SCRATCHPAD_DATA_SIZE = 16;
+
HdmiTvClient(IHdmiControlService service) {
super(service);
}
@@ -80,6 +85,15 @@
}
}
+ private static IHdmiControlCallback getCallbackWrapper(final SelectCallback callback) {
+ return new IHdmiControlCallback.Stub() {
+ @Override
+ public void onComplete(int result) {
+ callback.onComplete(result);
+ }
+ };
+ }
+
/**
* Select a HDMI port to be a new route path.
*
@@ -126,6 +140,15 @@
}
}
+ private static IHdmiInputChangeListener getListenerWrapper(final InputChangeListener listener) {
+ return new IHdmiInputChangeListener.Stub() {
+ @Override
+ public void onChanged(HdmiDeviceInfo info) {
+ listener.onChanged(info);
+ }
+ };
+ }
+
/**
* Set system audio volume
*
@@ -170,6 +193,38 @@
}
}
+ private static IHdmiRecordListener getListenerWrapper(final HdmiRecordListener callback) {
+ return new IHdmiRecordListener.Stub() {
+ @Override
+ public byte[] getOneTouchRecordSource(int recorderAddress) {
+ HdmiRecordSources.RecordSource source =
+ callback.getOneTouchRecordSource(recorderAddress);
+ if (source == null) {
+ return EmptyArray.BYTE;
+ }
+ byte[] data = new byte[source.getDataSize(true)];
+ source.toByteArray(true, data, 0);
+ return data;
+ }
+
+ @Override
+ public void onOneTouchRecordResult(int result) {
+ callback.onOneTouchRecordResult(result);
+ }
+
+ @Override
+ public void onTimerRecordingResult(int result) {
+ callback.onTimerRecordingResult(
+ HdmiRecordListener.TimerStatusData.parseFrom(result));
+ }
+
+ @Override
+ public void onClearTimerRecordingResult(int result) {
+ callback.onClearTimerRecordingResult(result);
+ }
+ };
+ }
+
/**
* Start one touch recording with the given recorder address and recorder source.
* <p>
@@ -276,53 +331,63 @@
}
}
- private static IHdmiControlCallback getCallbackWrapper(final SelectCallback callback) {
- return new IHdmiControlCallback.Stub() {
+ /**
+ * Interface used to get incoming MHL scratchpad command.
+ */
+ public interface HdmiMhlScratchpadCommandListener {
+ void onReceived(int portId, int offset, int length, byte[] data);
+ }
+
+ /**
+ * Set {@link HdmiMhlScratchpadCommandListener} to get incoming MHL sSratchpad command.
+ *
+ * @param listener to receive incoming MHL Scratchpad command
+ */
+ public void setHdmiMhlScratchpadCommandListener(HdmiMhlScratchpadCommandListener listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null.");
+ }
+ try {
+ mService.addHdmiMhlScratchpadCommandListener(getListenerWrapper(listener));
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to set hdmi mhl scratchpad command listener: ", e);
+ }
+ }
+
+ private IHdmiMhlScratchpadCommandListener getListenerWrapper(
+ final HdmiMhlScratchpadCommandListener listener) {
+ return new IHdmiMhlScratchpadCommandListener.Stub() {
@Override
- public void onComplete(int result) {
- callback.onComplete(result);
+ public void onReceived(int portId, int offset, int length, byte[] data) {
+ listener.onReceived(portId, offset, length, data);
}
};
}
- private static IHdmiInputChangeListener getListenerWrapper(final InputChangeListener listener) {
- return new IHdmiInputChangeListener.Stub() {
- @Override
- public void onChanged(HdmiDeviceInfo info) {
- listener.onChanged(info);
- }
- };
- }
+ /**
+ * Send MHL Scratchpad command to the device connected to a port of the given portId.
+ *
+ * @param portId id of port to send MHL Scratchpad command
+ * @param offset offset in the in given data
+ * @param length length of data. offset + length should be bound to length of data.
+ * @param data container for Scratchpad data. It should be 16 bytes.
+ * @throws IllegalArgumentException if the given parameters are invalid
+ */
+ public void sendScratchpadCommand(int portId, int offset, int length, byte[] data) {
+ if (data == null || data.length != SCRATCHPAD_DATA_SIZE) {
+ throw new IllegalArgumentException("Invalid scratchpad data.");
+ }
+ if (offset < 0 || offset >= SCRATCHPAD_DATA_SIZE) {
+ throw new IllegalArgumentException("Invalid offset:" + offset);
+ }
+ if (length < 0 || offset + length > SCRATCHPAD_DATA_SIZE) {
+ throw new IllegalArgumentException("Invalid length:" + length);
+ }
- private static IHdmiRecordListener getListenerWrapper(final HdmiRecordListener callback) {
- return new IHdmiRecordListener.Stub() {
- @Override
- public byte[] getOneTouchRecordSource(int recorderAddress) {
- HdmiRecordSources.RecordSource source =
- callback.getOneTouchRecordSource(recorderAddress);
- if (source == null) {
- return EmptyArray.BYTE;
- }
- byte[] data = new byte[source.getDataSize(true)];
- source.toByteArray(true, data, 0);
- return data;
- }
-
- @Override
- public void onOneTouchRecordResult(int result) {
- callback.onOneTouchRecordResult(result);
- }
-
- @Override
- public void onTimerRecordingResult(int result) {
- callback.onTimerRecordingResult(
- HdmiRecordListener.TimerStatusData.parseFrom(result));
- }
-
- @Override
- public void onClearTimerRecordingResult(int result) {
- callback.onClearTimerRecordingResult(result);
- }
- };
+ try {
+ mService.sendScratchpadCommand(portId, offset, length, data);
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to send scratchpad command: ", e);
+ }
}
}
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index 17f290b..3bd45ed 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -22,6 +22,7 @@
import android.hardware.hdmi.IHdmiDeviceEventListener;
import android.hardware.hdmi.IHdmiHotplugEventListener;
import android.hardware.hdmi.IHdmiInputChangeListener;
+import android.hardware.hdmi.IHdmiMhlScratchpadCommandListener;
import android.hardware.hdmi.IHdmiRecordListener;
import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener;
import android.hardware.hdmi.IHdmiVendorCommandListener;
@@ -66,4 +67,6 @@
void stopOneTouchRecord(int recorderAddress);
void startTimerRecording(int recorderAddress, int sourceType, in byte[] recordSource);
void clearTimerRecording(int recorderAddress, int sourceType, in byte[] recordSource);
+ void sendScratchpadCommand(int portId, int offset, int length, in byte[] data);
+ void addHdmiMhlScratchpadCommandListener(IHdmiMhlScratchpadCommandListener listener);
}
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.aidl b/core/java/android/hardware/hdmi/IHdmiMhlScratchpadCommandListener.aidl
similarity index 69%
rename from core/java/android/view/inputmethod/CursorAnchorInfoRequest.aidl
rename to core/java/android/hardware/hdmi/IHdmiMhlScratchpadCommandListener.aidl
index 41ef7cc6..4176597 100644
--- a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiMhlScratchpadCommandListener.aidl
@@ -14,6 +14,14 @@
* limitations under the License.
*/
-package android.view.inputmethod;
+package android.hardware.hdmi;
-parcelable CursorAnchorInfoRequest;
+ /**
+ * Callback interface definition for MHL client to get the scratchpad
+ * command.
+ *
+ * @hide
+ */
+ oneway interface IHdmiMhlScratchpadCommandListener {
+ void onReceived(int portId, int offset, int length, in byte[] data);
+ }
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index ba811b7..2eb42a7 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -53,7 +53,6 @@
import android.view.animation.AnimationUtils;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CursorAnchorInfo;
-import android.view.inputmethod.CursorAnchorInfoRequest;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
@@ -1711,13 +1710,12 @@
}
/**
- * Called when the application has reported a new location of its text cursor. This is only
- * called if explicitly requested by the input method. The default implementation does nothing.
- * @param newCursor The new cursor position, in screen coordinates if the input method calls
- * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} with
- * {@link CursorAnchorInfoRequest#FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES}. Otherwise,
- * this is in local coordinates.
+ * Called when the application has reported a new location of its text
+ * cursor. This is only called if explicitly requested by the input method.
+ * The default implementation does nothing.
+ * @deprecated Use {#link onUpdateCursorAnchorInfo(CursorAnchorInfo)} instead.
*/
+ @Deprecated
public void onUpdateCursor(Rect newCursor) {
// Intentionally empty
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 0814e0f..b2fc3be 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -108,6 +108,8 @@
boolean prepareVpn(String oldPackage, String newPackage);
+ void setVpnPackageAuthorization(boolean authorized);
+
ParcelFileDescriptor establishVpn(in VpnConfig config);
VpnConfig getVpnConfig();
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 0de3f26..d2a4728 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -16,10 +16,10 @@
package android.net;
-import android.net.NetworkBoundURLFactory;
import android.net.NetworkUtils;
import android.os.Parcelable;
import android.os.Parcel;
+import android.system.ErrnoException;
import java.io.IOException;
import java.net.InetAddress;
@@ -30,6 +30,7 @@
import java.net.SocketException;
import java.net.UnknownHostException;
import java.net.URL;
+import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.concurrent.atomic.AtomicReference;
import javax.net.SocketFactory;
@@ -54,7 +55,7 @@
public final int netId;
// Objects used to perform per-network operations such as getSocketFactory
- // and getBoundURL, and a lock to protect access to them.
+ // and openConnection, and a lock to protect access to them.
private volatile NetworkBoundSocketFactory mNetworkBoundSocketFactory = null;
private volatile OkHttpClient mOkHttpClient = null;
private Object mLock = new Object();
@@ -157,12 +158,7 @@
@Override
public Socket createSocket() throws IOException {
Socket socket = new Socket();
- // Query a property of the underlying socket to ensure the underlying
- // socket exists so a file descriptor is available to bind to a network.
- socket.getReuseAddress();
- if (!NetworkUtils.bindSocketToNetwork(socket.getFileDescriptor$().getInt$(), mNetId)) {
- throw new SocketException("Failed to bind socket to network.");
- }
+ bindSocket(socket);
return socket;
}
}
@@ -187,73 +183,63 @@
return mNetworkBoundSocketFactory;
}
- /** The default NetworkBoundURLFactory, used if setNetworkBoundURLFactory is never called. */
- private static final NetworkBoundURLFactory DEFAULT_URL_FACTORY = new NetworkBoundURLFactory() {
- public URL getBoundURL(final Network network, URL url) throws MalformedURLException {
- if (network.mOkHttpClient == null) {
- synchronized (network.mLock) {
- if (network.mOkHttpClient == null) {
- HostResolver hostResolver = new HostResolver() {
- @Override
- public InetAddress[] getAllByName(String host)
- throws UnknownHostException {
- return network.getAllByName(host);
- }
- };
- network.mOkHttpClient = new OkHttpClient()
- .setSocketFactory(network.getSocketFactory())
- .setHostResolver(hostResolver);
- }
+ private void maybeInitHttpClient() {
+ if (mOkHttpClient == null) {
+ synchronized (mLock) {
+ if (mOkHttpClient == null) {
+ HostResolver hostResolver = new HostResolver() {
+ @Override
+ public InetAddress[] getAllByName(String host) throws UnknownHostException {
+ return Network.this.getAllByName(host);
+ }
+ };
+ mOkHttpClient = new OkHttpClient()
+ .setSocketFactory(getSocketFactory())
+ .setHostResolver(hostResolver);
}
}
-
- String protocol = url.getProtocol();
- URLStreamHandler handler = network.mOkHttpClient.createURLStreamHandler(protocol);
- if (handler == null) {
- // OkHttpClient only supports HTTP and HTTPS and returns a null URLStreamHandler if
- // passed another protocol.
- throw new MalformedURLException("Invalid URL or unrecognized protocol " + protocol);
- }
- return new URL(url, "", handler);
}
- };
-
- private static AtomicReference<NetworkBoundURLFactory> sNetworkBoundURLFactory =
- new AtomicReference <NetworkBoundURLFactory>(DEFAULT_URL_FACTORY);
-
- /**
- * Returns a {@link URL} based on the given URL but bound to this {@code Network},
- * such that opening the URL will send all network traffic on this Network.
- *
- * Note that if this {@code Network} ever disconnects, any URL object generated by this method
- * in the past or future will cease to work.
- *
- * The returned URL may have a {@link URLStreamHandler} explicitly set, which may not be the
- * handler generated by the factory set with {@link java.net.URL#setURLStreamHandlerFactory}. To
- * affect the {@code URLStreamHandler}s of URLs returned by this method, call
- * {@link #setNetworkBoundURLFactory}.
- *
- * Because the returned URLs may have an explicit {@code URLStreamHandler} set, using them as a
- * context when constructing other URLs and explicitly specifying a {@code URLStreamHandler} may
- * result in URLs that are no longer bound to the same {@code Network}.
- *
- * The default implementation only supports {@code HTTP} and {@code HTTPS} URLs.
- *
- * @return a {@link URL} bound to this {@code Network}.
- */
- public URL getBoundURL(URL url) throws MalformedURLException {
- return sNetworkBoundURLFactory.get().getBoundURL(this, url);
}
/**
- * Sets the {@link NetworkBoundURLFactory} to be used by future {@link #getBoundURL} calls.
- * If {@code null}, clears any factory that was previously specified.
+ * Opens the specified {@link URL} on this {@code Network}, such that all traffic will be sent
+ * on this Network. The URL protocol must be {@code HTTP} or {@code HTTPS}.
+ *
+ * @return a {@code URLConnection} to the resource referred to by this URL.
+ * @throws MalformedURLException if the URL protocol is not HTTP or HTTPS.
+ * @throws IOException if an error occurs while opening the connection.
+ * @see java.net.URL#openConnection()
*/
- public static void setNetworkBoundURLFactory(NetworkBoundURLFactory factory) {
- if (factory == null) {
- factory = DEFAULT_URL_FACTORY;
+ public URLConnection openConnection(URL url) throws IOException {
+ maybeInitHttpClient();
+ String protocol = url.getProtocol();
+ URLStreamHandler handler = mOkHttpClient.createURLStreamHandler(protocol);
+ if (handler == null) {
+ // OkHttpClient only supports HTTP and HTTPS and returns a null URLStreamHandler if
+ // passed another protocol.
+ throw new MalformedURLException("Invalid URL or unrecognized protocol " + protocol);
}
- sNetworkBoundURLFactory.set(factory);
+ return new URL(url, "", handler).openConnection();
+ }
+
+ /**
+ * Binds the specified {@link Socket} to this {@code Network}. All data traffic on the socket
+ * will be sent on this {@code Network}, irrespective of any process-wide network binding set by
+ * {@link ConnectivityManager#setProcessDefaultNetwork}. The socket must not be connected.
+ */
+ public void bindSocket(Socket socket) throws IOException {
+ if (socket.isConnected()) {
+ throw new SocketException("Socket is connected");
+ }
+ // Query a property of the underlying socket to ensure the underlying
+ // socket exists so a file descriptor is available to bind to a network.
+ socket.getReuseAddress();
+ int err = NetworkUtils.bindSocketToNetwork(socket.getFileDescriptor$().getInt$(), netId);
+ if (err != 0) {
+ // bindSocketToNetwork returns negative errno.
+ throw new ErrnoException("Binding socket to network " + netId, -err)
+ .rethrowAsSocketException();
+ }
}
// implement the Parcelable interface
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 54d8676..d2a2997 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -128,8 +128,9 @@
/**
* Explicitly binds {@code socketfd} to the network designated by {@code netId}. This
* overrides any binding via {@link #bindProcessToNetwork}.
+ * @return 0 on success or negative errno on failure.
*/
- public native static boolean bindSocketToNetwork(int socketfd, int netId);
+ public native static int bindSocketToNetwork(int socketfd, int netId);
/**
* Protect {@code socketfd} from VPN connections. After protecting, data sent through
diff --git a/core/java/android/net/PacProxySelector.java b/core/java/android/net/PacProxySelector.java
index 8a2c2b6..8626d08 100644
--- a/core/java/android/net/PacProxySelector.java
+++ b/core/java/android/net/PacProxySelector.java
@@ -39,6 +39,9 @@
public class PacProxySelector extends ProxySelector {
private static final String TAG = "PacProxySelector";
public static final String PROXY_SERVICE = "com.android.net.IProxyService";
+ private static final String SOCKS = "SOCKS ";
+ private static final String PROXY = "PROXY ";
+
private IProxyService mProxyService;
private final List<Proxy> mDefaultList;
@@ -88,16 +91,16 @@
String trimmed = s.trim();
if (trimmed.equals("DIRECT")) {
ret.add(java.net.Proxy.NO_PROXY);
- } else if (trimmed.startsWith("PROXY ")) {
- String[] hostPort = trimmed.substring(6).split(":");
- String host = hostPort[0];
- int port;
- try {
- port = Integer.parseInt(hostPort[1]);
- } catch (Exception e) {
- port = 8080;
+ } else if (trimmed.startsWith(PROXY)) {
+ Proxy proxy = proxyFromHostPort(Type.HTTP, trimmed.substring(PROXY.length()));
+ if (proxy != null) {
+ ret.add(proxy);
}
- ret.add(new Proxy(Type.HTTP, InetSocketAddress.createUnresolved(host, port)));
+ } else if (trimmed.startsWith(SOCKS)) {
+ Proxy proxy = proxyFromHostPort(Type.SOCKS, trimmed.substring(SOCKS.length()));
+ if (proxy != null) {
+ ret.add(proxy);
+ }
}
}
if (ret.size() == 0) {
@@ -106,6 +109,18 @@
return ret;
}
+ private static Proxy proxyFromHostPort(Proxy.Type type, String hostPortString) {
+ try {
+ String[] hostPort = hostPortString.split(":");
+ String host = hostPort[0];
+ int port = Integer.parseInt(hostPort[1]);
+ return new Proxy(type, InetSocketAddress.createUnresolved(host, port));
+ } catch (NumberFormatException|ArrayIndexOutOfBoundsException e) {
+ Log.d(TAG, "Unable to parse proxy " + hostPortString + " " + e);
+ return null;
+ }
+ }
+
@Override
public void connectFailed(URI uri, SocketAddress address, IOException failure) {
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index 5815fa6..4039992 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -57,7 +57,6 @@
void setReaderMode (IBinder b, IAppCallback callback, int flags, in Bundle extras);
void setP2pModes(int initatorModes, int targetModes);
- void registerLockscreenDispatch(INfcLockscreenDispatch lockscreenDispatch, in int[] techList);
void addNfcUnlockHandler(INfcUnlockHandler unlockHandler, in int[] techList);
void removeNfcUnlockHandler(INfcUnlockHandler unlockHandler);
}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 6bd5a32..7cc8ca4 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -384,16 +384,6 @@
public Uri[] createBeamUris(NfcEvent event);
}
-
- /**
- * A callback to be invoked when an application has registered for receiving
- * tags at the lockscreen.
- */
- public interface NfcLockscreenDispatch {
- public boolean onTagDetected(Tag tag);
- }
-
-
/**
* A callback to be invoked when an application has registered as a
* handler to unlock the device given an NFC tag at the lockscreen.
@@ -1468,26 +1458,6 @@
}
}
- public boolean registerLockscreenDispatch(final NfcLockscreenDispatch lockscreenDispatch,
- String[] techList) {
- try {
- sService.registerLockscreenDispatch(new INfcLockscreenDispatch.Stub() {
- @Override
- public boolean onTagDetected(Tag tag) throws RemoteException {
- return lockscreenDispatch.onTagDetected(tag);
- }
- }, Tag.getTechCodesFromStrings(techList));
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- return false;
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Unable to register LockscreenDispatch", e);
- return false;
- }
-
- return true;
- }
-
/**
* Registers a new NFC unlock handler with the NFC service.
*
diff --git a/core/java/android/os/FileBridge.java b/core/java/android/os/FileBridge.java
index 1e1ad9e..afa5885 100644
--- a/core/java/android/os/FileBridge.java
+++ b/core/java/android/os/FileBridge.java
@@ -95,6 +95,10 @@
int len = Memory.peekInt(temp, 4, ByteOrder.BIG_ENDIAN);
while (len > 0) {
int n = IoBridge.read(mServer, temp, 0, Math.min(temp.length, len));
+ if (n == -1) {
+ throw new IOException(
+ "Unexpected EOF; still expected " + len + " bytes");
+ }
IoBridge.write(mTarget, temp, 0, n);
len -= n;
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 5189155..e215669 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -57,8 +57,7 @@
/**
* Key for user restrictions. Specifies if a user is disallowed from changing Wi-Fi
- * access points.
- * The default value is <code>false</code>.
+ * access points. The default value is <code>false</code>.
* <p/>
* Type: Boolean
* @see #setUserRestrictions(Bundle)
@@ -119,7 +118,7 @@
/**
* Key for user restrictions. Specifies if a user is disallowed from transferring files over
- * USB. The default value is <code>false</code>.
+ * USB. This can only be set by device owners. The default value is <code>false</code>.
* <p/>
* Type: Boolean
* @see #setUserRestrictions(Bundle)
@@ -139,8 +138,7 @@
/**
* Key for user restrictions. Specifies if a user is disallowed from removing itself and other
- * users.
- * The default value is <code>false</code>.
+ * users. The default value is <code>false</code>.
* <p/>
* Type: Boolean
* @see #setUserRestrictions(Bundle)
@@ -170,7 +168,8 @@
/**
* Key for user restrictions. Specifies if a user is disallowed from configuring Tethering
- * & portable hotspots. The default value is <code>false</code>.
+ * & portable hotspots. This can only be set by device owners. The default value is
+ * <code>false</code>.
* <p/>
* Type: Boolean
* @see #setUserRestrictions(Bundle)
@@ -180,8 +179,8 @@
/**
* Key for user restrictions. Specifies if a user is disallowed from factory resetting
- * from Settings.
- * The default value is <code>false</code>.
+ * from Settings. This can only be set by device owners. The default value is
+ * <code>false</code>.
* <p>
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
@@ -190,7 +189,7 @@
/**
* Key for user restrictions. Specifies if a user is disallowed from adding new users and
- * profiles. The default value is <code>false</code>.
+ * profiles. This can only be set by device owners. The default value is <code>false</code>.
* <p>
* Type: Boolean
* @see #setUserRestrictions(Bundle)
@@ -210,7 +209,7 @@
/**
* Key for user restrictions. Specifies if a user is disallowed from configuring cell
- * broadcasts. The default value is <code>false</code>.
+ * broadcasts. This can only be set by device owners. The default value is <code>false</code>.
* <p>
* Type: Boolean
* @see #setUserRestrictions(Bundle)
@@ -220,7 +219,7 @@
/**
* Key for user restrictions. Specifies if a user is disallowed from configuring mobile
- * networks. The default value is <code>false</code>.
+ * networks. This can only be set by device owners. The default value is <code>false</code>.
* <p>
* Type: Boolean
* @see #setUserRestrictions(Bundle)
@@ -249,7 +248,8 @@
/**
* Key for user restrictions. Specifies if a user is disallowed from mounting
- * physical external media. The default value is <code>false</code>.
+ * physical external media. This can only be set by device owners. The default value is
+ * <code>false</code>.
* <p/>
* Type: Boolean
* @see #setUserRestrictions(Bundle)
@@ -259,7 +259,7 @@
/**
* Key for user restrictions. Specifies if a user is disallowed from adjusting microphone
- * volume.
+ * volume. If set, the microphone will be muted. This can only be set by device owners.
* The default value is <code>false</code>.
* <p/>
* Type: Boolean
@@ -270,7 +270,7 @@
/**
* Key for user restrictions. Specifies if a user is disallowed from adjusting the master
- * volume.
+ * volume. If set, the master volume will be muted. This can only be set by device owners.
* The default value is <code>false</code>.
* <p/>
* Type: Boolean
@@ -292,8 +292,7 @@
/**
* Key for user restrictions. Specifies that the user is not allowed to send or receive
- * SMS messages.
- * The default value is <code>false</code>.
+ * SMS messages. This can only be set by device owners. The default value is <code>false</code>.
* <p/>
* Type: Boolean
* @see #setUserRestrictions(Bundle)
@@ -311,7 +310,7 @@
* <li>{@link LayoutParams#TYPE_SYSTEM_ERROR}</li>
* <li>{@link LayoutParams#TYPE_SYSTEM_OVERLAY}</li>
*
- * <p>The default value is <code>false</code>.
+ * <p>This can only be set by device owners. The default value is <code>false</code>.
* <p/>
* Type: Boolean
* @see #setUserRestrictions(Bundle)
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 8db99a5..942da5a 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -24,13 +24,17 @@
import android.content.Intent;
import android.content.pm.UserInfo;
import android.database.Cursor;
+import android.location.Country;
+import android.location.CountryDetector;
import android.net.Uri;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.ContactsContract.CommonDataKinds.Callable;
import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.DataUsageFeedback;
import android.telecomm.PhoneAccountHandle;
+import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
import com.android.internal.telephony.CallerInfo;
@@ -345,6 +349,13 @@
public static final String PHONE_ACCOUNT_ID = "subscription_id";
/**
+ * If a successful call is made that is longer than this duration, update the phone number
+ * in the ContactsProvider with the normalized version of the number, based on the user's
+ * current country code.
+ */
+ private static final int MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS = 1000 * 10;
+
+ /**
* Adds a call to the call log.
*
* @param ci the CallerInfo object to get the target contact from. Can be null
@@ -484,12 +495,13 @@
if (cursor != null) {
try {
if (cursor.getCount() > 0 && cursor.moveToFirst()) {
- final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon()
- .appendPath(cursor.getString(0))
- .appendQueryParameter(DataUsageFeedback.USAGE_TYPE,
- DataUsageFeedback.USAGE_TYPE_CALL)
- .build();
- resolver.update(feedbackUri, new ContentValues(), null, null);
+ final String dataId = cursor.getString(0);
+ updateDataUsageStatForData(resolver, dataId);
+ if (duration >= MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS
+ && callType == Calls.OUTGOING_TYPE
+ && TextUtils.isEmpty(ci.normalizedNumber)) {
+ updateNormalizedNumber(context, resolver, dataId, number);
+ }
}
} finally {
cursor.close();
@@ -562,5 +574,53 @@
+ " LIMIT -1 OFFSET 500)", null);
return result;
}
+
+ private static void updateDataUsageStatForData(ContentResolver resolver, String dataId) {
+ final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon()
+ .appendPath(dataId)
+ .appendQueryParameter(DataUsageFeedback.USAGE_TYPE,
+ DataUsageFeedback.USAGE_TYPE_CALL)
+ .build();
+ resolver.update(feedbackUri, new ContentValues(), null, null);
+ }
+
+ /**
+ * Update the normalized phone number for the given dataId in the ContactsProvider, based
+ * on the user's current country.
+ */
+ private static void updateNormalizedNumber(Context context, ContentResolver resolver,
+ String dataId, String number) {
+ if (TextUtils.isEmpty(number) || TextUtils.isEmpty(dataId)) {
+ return;
+ }
+
+ final String countryIso = getCurrentCountryIso(context);
+ if (TextUtils.isEmpty(countryIso)) {
+ return;
+ }
+
+ final String normalizedNumber = PhoneNumberUtils.formatNumberToE164(number,
+ getCurrentCountryIso(context));
+ if (TextUtils.isEmpty(normalizedNumber)) {
+ return;
+ }
+
+ final ContentValues values = new ContentValues();
+ values.put(Phone.NORMALIZED_NUMBER, normalizedNumber);
+ resolver.update(Data.CONTENT_URI, values, Data._ID + "=?", new String[] {dataId});
+ }
+
+ private static String getCurrentCountryIso(Context context) {
+ String countryIso = null;
+ final CountryDetector detector = (CountryDetector) context.getSystemService(
+ Context.COUNTRY_DETECTOR);
+ if (detector != null) {
+ final Country country = detector.detectCountry();
+ if (country != null) {
+ countryIso = country.getCountryIso();
+ }
+ }
+ return countryIso;
+ }
}
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 52f1dd9..2241716 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2674,6 +2674,9 @@
*/
public static final String[] CLONE_TO_MANAGED_PROFILE = {
DATE_FORMAT,
+ HAPTIC_FEEDBACK_ENABLED,
+ SOUND_EFFECTS_ENABLED,
+ TEXT_SHOW_PASSWORD,
TIME_12_24
};
@@ -4737,17 +4740,16 @@
/**
* List of TV inputs that are currently hidden. This is a string
- * containing the IDs of all hidden TV inputs. Each ID is separated by ':'.
- *
+ * containing the IDs of all hidden TV inputs. Each ID is encoded by
+ * {@link android.net.Uri#encode(String)} and separated by ':'.
* @hide
*/
public static final String TV_INPUT_HIDDEN_INPUTS = "tv_input_hidden_inputs";
/**
* List of custom TV input labels. This is a string containing <TV input id, custom name>
- * pairs. Each pair is separated by ':' and TV input id and custom name are separated by
- * ','.
- *
+ * pairs. TV input id and custom name are encoded by {@link android.net.Uri#encode(String)}
+ * and separated by ','. Each pair is separated by ':'.
* @hide
*/
public static final String TV_INPUT_CUSTOM_LABELS = "tv_input_custom_labels";
diff --git a/core/java/android/text/style/TtsSpan.java b/core/java/android/text/style/TtsSpan.java
index cb447fd..342a183 100644
--- a/core/java/android/text/style/TtsSpan.java
+++ b/core/java/android/text/style/TtsSpan.java
@@ -26,10 +26,14 @@
/**
* A span that supplies additional meta-data for the associated text intended
- * for text-to-speech engines. If the text is being processed by a
+ * for text-to-speech engines. If the text is being processed by a
* text-to-speech engine, the engine may use the data in this span in addition
* to or instead of its associated text.
*
+ * Each instance of a TtsSpan has a type, for example {@link #TYPE_DATE}
+ * or {@link #TYPE_MEASURE}. And a list of arguments, provided as
+ * key-value pairs in a bundle.
+ *
* The inner classes are there for convenience and provide builders for each
* TtsSpan type.
*/
@@ -39,7 +43,7 @@
/**
* This span type can be used to add morphosyntactic features to the text it
- * spans over, or synthesize a something else than the spanned text. Use
+ * spans over, or synthesize a something else than the spanned text. Use
* the argument {@link #ARG_TEXT} to set a different text.
* Accepts the arguments {@link #ARG_GENDER},
* {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
@@ -48,7 +52,7 @@
public static final String TYPE_TEXT = "android.type.text";
/**
- * The text associated with this span is a cardinal. Must include the
+ * The text associated with this span is a cardinal. Must include the
* number to be synthesized with {@link #ARG_NUMBER}.
* Also accepts the arguments {@link #ARG_GENDER},
* {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
@@ -108,12 +112,12 @@
public static final String TYPE_TIME = "android.type.time";
/**
- * The text associated with this span is a date. All arguments are optional,
- * but at least one has to be provided: {@link #ARG_WEEKDAY},
- * {@link #ARG_DAY}, {@link #ARG_MONTH} and {@link #ARG_YEAR}.
- * Also accepts the arguments {@link #ARG_GENDER},
- * {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
- * {@link #ARG_CASE}.
+ * The text associated with this span is a date. At least one of the
+ * arguments {@link #ARG_MONTH} and {@link #ARG_YEAR} has to be provided.
+ * The argument {@link #ARG_DAY} is optional if {@link #ARG_MONTH} is set.
+ * The argument {@link #ARG_WEEKDAY} is optional if {@link #ARG_DAY} is set.
+ * Also accepts the arguments {@link #ARG_GENDER}, {@link #ARG_ANIMACY},
+ * {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
*/
public static final String TYPE_DATE = "android.type.date";
@@ -121,13 +125,11 @@
* The text associated with this span is a telephone number. The argument
* {@link #ARG_NUMBER_PARTS} is required. {@link #ARG_COUNTRY_CODE} and
* {@link #ARG_EXTENSION} are optional.
- * Also accepts the arguments {@link #ARG_GENDER},
- * {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
- * {@link #ARG_CASE}.
+ * Also accepts the arguments {@link #ARG_GENDER}, {@link #ARG_ANIMACY},
+ * {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
*/
public static final String TYPE_TELEPHONE = "android.type.telephone";
-
/**
* The text associated with this span is a URI (can be used for URLs and
* email addresses). The full schema for URLs, which email addresses can
@@ -138,9 +140,8 @@
* {@link #ARG_PROTOCOL}, {@link #ARG_USERNAME}, {@link #ARG_PASSWORD},
* {@link #ARG_DOMAIN}, {@link #ARG_PORT}, {@link #ARG_PATH},
* {@link #ARG_QUERY_STRING} and {@link #ARG_FRAGMENT_ID}.
- * Also accepts the arguments {@link #ARG_GENDER},
- * {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
- * {@link #ARG_CASE}.
+ * Also accepts the arguments {@link #ARG_GENDER}, {@link #ARG_ANIMACY},
+ * {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
*/
public static final String TYPE_ELECTRONIC = "android.type.electronic";
@@ -149,18 +150,16 @@
* with the same arguments as {@link #TYPE_DECIMAL}.
* {@link #ARG_CURRENCY} is used to set the currency. {@link #ARG_QUANTITY}
* is optional.
- * Also accepts the arguments {@link #ARG_GENDER},
- * {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
- * {@link #ARG_CASE}.
+ * Also accepts the arguments {@link #ARG_GENDER}, {@link #ARG_ANIMACY},
+ * {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
*/
public static final String TYPE_MONEY = "android.type.money";
/**
* The text associated with this span is a series of digits that have to be
- * read sequentially. {@link #ARG_DIGITS} is required.
- * Also accepts the arguments {@link #ARG_GENDER},
- * {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
- * {@link #ARG_CASE}.
+ * read sequentially. The digits can be set with {@link #ARG_DIGITS}.
+ * Also accepts the arguments {@link #ARG_GENDER}, {@link #ARG_ANIMACY},
+ * {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
*/
public static final String TYPE_DIGITS = "android.type.digits";
@@ -169,13 +168,12 @@
* be read verbatim. The engine will attempt to ready out any character like
* punctuation but excluding whitespace. {@link #ARG_VERBATIM} is required.
* Also accepts the arguments {@link #ARG_GENDER},
- * {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
- * {@link #ARG_CASE}.
+ * {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
*/
public static final String TYPE_VERBATIM = "android.type.verbatim";
/**
- * String argument supplying gender information. Can be any of
+ * String argument supplying gender information. Can be any of
* {@link #GENDER_NEUTRAL}, {@link #GENDER_MALE} and
* {@link #GENDER_FEMALE}.
*/
@@ -186,7 +184,7 @@
public static final String GENDER_FEMALE = "android.female";
/**
- * String argument supplying animacy information. Can be
+ * String argument supplying animacy information. Can be
* {@link #ANIMACY_ANIMATE} or
* {@link #ANIMACY_INANIMATE}
*/
@@ -196,9 +194,8 @@
public static final String ANIMACY_INANIMATE = "android.inanimate";
/**
- * String argument supplying multiplicity information. Can be any of
- * {@link #MULTIPLICITY_SINGLE},
- * {@link #MULTIPLICITY_DUAL} and
+ * String argument supplying multiplicity information. Can be any of
+ * {@link #MULTIPLICITY_SINGLE}, {@link #MULTIPLICITY_DUAL} and
* {@link #MULTIPLICITY_PLURAL}
*/
public static final String ARG_MULTIPLICITY = "android.arg.multiplicity";
@@ -208,16 +205,14 @@
public static final String MULTIPLICITY_PLURAL = "android.plural";
/**
- * String argument supplying case information. Can be any of
- * {@link #CASE_NOMINATIVE}, {@link #CASE_ACCUSATIVE},
- * {@link #CASE_DATIVE}, {@link #CASE_ABLATIVE},
- * {@link #CASE_GENITIVE}, {@link #CASE_VOCATIVE},
- * {@link #CASE_LOCATIVE} and
- * {@link #CASE_INSTRUMENTAL}
+ * String argument supplying case information. Can be any of
+ * {@link #CASE_NOMINATIVE}, {@link #CASE_ACCUSATIVE}, {@link #CASE_DATIVE},
+ * {@link #CASE_ABLATIVE}, {@link #CASE_GENITIVE}, {@link #CASE_VOCATIVE},
+ * {@link #CASE_LOCATIVE} and {@link #CASE_INSTRUMENTAL}
*/
public static final String ARG_CASE = "android.arg.case";
- public static final String CASE_NOMINATIVE = "android.nomative";
+ public static final String CASE_NOMINATIVE = "android.nominative";
public static final String CASE_ACCUSATIVE = "android.accusative";
public static final String CASE_DATIVE = "android.dative";
public static final String CASE_ABLATIVE = "android.ablative";
@@ -227,14 +222,14 @@
public static final String CASE_INSTRUMENTAL = "android.instrumental";
/**
- * String supplying the text to be synthesized. The synthesizer is free
+ * String supplying the text to be synthesized. The synthesizer is free
* to decide how to interpret the text.
* Can be used with {@link #TYPE_TEXT}.
*/
public static final String ARG_TEXT = "android.arg.text";
/**
- * Argument used to specify a whole number. The value can be a string of
+ * Argument used to specify a whole number. The value can be a string of
* digits of any size optionally prefixed with a - or +.
* Can be used with {@link #TYPE_CARDINAL} and {@link #TYPE_ORDINAL}.
*/
@@ -293,7 +288,7 @@
* specified in English singular form. Prefixes may be used. Engines will do
* their best to pronounce them correctly in the language used. Engines are
* expected to at least support the most common ones like "meter", "second",
- * "degree celcius" and "degree fahrenheit" with some common prefixes like
+ * "degree celsius" and "degree fahrenheit" with some common prefixes like
* "milli" and "kilo".
* Can be used with {@link #TYPE_MEASURE}.
*/
@@ -589,8 +584,8 @@
/**
* Sets the gender information for this instance.
- * @param gender Can any of {@link TtsSpan#GENDER_NEUTRAL},
- * {@link TtsSpan#GENDER_MALE} and {@link TtsSpan#GENDER_FEMALE}.
+ * @param gender Can any of {@link #GENDER_NEUTRAL},
+ * {@link #GENDER_MALE} and {@link #GENDER_FEMALE}.
* @return This instance.
*/
public C setGender(String gender) {
@@ -599,8 +594,8 @@
/**
* Sets the animacy information for this instance.
- * @param animacy Can be any of {@link TtsSpan#ANIMACY_ANIMATE} and
- * {@link TtsSpan#ANIMACY_INANIMATE}.
+ * @param animacy Can be any of {@link #ANIMACY_ANIMATE} and
+ * {@link #ANIMACY_INANIMATE}.
* @return This instance.
*/
public C setAnimacy(String animacy) {
@@ -610,9 +605,8 @@
/**
* Sets the multiplicity information for this instance.
* @param multiplicity Can be any of
- * {@link TtsSpan#MULTIPLICITY_SINGLE},
- * {@link TtsSpan#MULTIPLICITY_DUAL} and
- * {@link TtsSpan#MULTIPLICITY_PLURAL}.
+ * {@link #MULTIPLICITY_SINGLE}, {@link #MULTIPLICITY_DUAL} and
+ * {@link #MULTIPLICITY_PLURAL}.
* @return This instance.
*/
public C setMultiplicity(String multiplicity) {
@@ -621,11 +615,11 @@
/**
* Sets the grammatical case information for this instance.
- * @param grammaticalCase Can be any of {@link TtsSpan#CASE_NOMINATIVE},
- * {@link TtsSpan#CASE_ACCUSATIVE}, {@link TtsSpan#CASE_DATIVE},
- * {@link TtsSpan#CASE_ABLATIVE}, {@link TtsSpan#CASE_GENITIVE},
- * {@link TtsSpan#CASE_VOCATIVE}, {@link TtsSpan#CASE_LOCATIVE} and
- * {@link TtsSpan#CASE_INSTRUMENTAL}.
+ * @param grammaticalCase Can be any of {@link #CASE_NOMINATIVE},
+ * {@link #CASE_ACCUSATIVE}, {@link #CASE_DATIVE},
+ * {@link #CASE_ABLATIVE}, {@link #CASE_GENITIVE},
+ * {@link #CASE_VOCATIVE}, {@link #CASE_LOCATIVE} and
+ * {@link #CASE_INSTRUMENTAL}.
* @return This instance.
*/
public C setCase(String grammaticalCase) {
@@ -634,20 +628,20 @@
}
/**
- * A builder for TtsSpans of type {@link TtsSpan #TYPE_TEXT}.
+ * A builder for TtsSpans of type {@link #TYPE_TEXT}.
*/
public static class TextBuilder extends SemioticClassBuilder<TextBuilder> {
/**
- * Creates a builder for a TtsSpan of type {@link TtsSpan#TYPE_TEXT}.
+ * Creates a builder for a TtsSpan of type {@link #TYPE_TEXT}.
*/
public TextBuilder() {
super(TtsSpan.TYPE_TEXT);
}
/**
- * Creates a TtsSpan of type {@link TtsSpan#TYPE_TEXT} and sets the
- * {@link TtsSpan#ARG_TEXT} argument.
+ * Creates a TtsSpan of type {@link #TYPE_TEXT} and sets the
+ * {@link #ARG_TEXT} argument.
* @param text The text to be synthesized.
* @see #setText(String)
*/
@@ -657,8 +651,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_TEXT} argument, the text to be
- * synthesized.
+ * Sets the {@link #ARG_TEXT} argument, the text to be synthesized.
* @param text The string that will be synthesized.
* @return This instance.
*/
@@ -668,22 +661,21 @@
}
/**
- * A builder for TtsSpans of type {@link TtsSpan #TYPE_CARDINAL}.
+ * A builder for TtsSpans of type {@link #TYPE_CARDINAL}.
*/
public static class CardinalBuilder
extends SemioticClassBuilder<CardinalBuilder> {
/**
- * Creates a builder for a TtsSpan of type
- * {@link TtsSpan#TYPE_CARDINAL}.
+ * Creates a builder for a TtsSpan of type {@link #TYPE_CARDINAL}.
*/
public CardinalBuilder() {
super(TtsSpan.TYPE_CARDINAL);
}
/**
- * Creates a TtsSpan of type {@link TtsSpan#TYPE_CARDINAL} and sets the
- * {@link TtsSpan#ARG_NUMBER} argument.
+ * Creates a TtsSpan of type {@link #TYPE_CARDINAL} and sets the
+ * {@link #ARG_NUMBER} argument.
* @param number The number to synthesize.
* @see #setNumber(long)
*/
@@ -693,8 +685,8 @@
}
/**
- * Creates a TtsSpan of type {@link TtsSpan#TYPE_CARDINAL} and sets the
- * {@link TtsSpan#ARG_NUMBER} argument.
+ * Creates a TtsSpan of type {@link #TYPE_CARDINAL} and sets the
+ * {@link #ARG_NUMBER} argument.
* @param number The number to synthesize.
* @see #setNumber(String)
*/
@@ -705,7 +697,7 @@
/**
* Convenience method that converts the number to a String and set it to
- * the value for {@link TtsSpan#ARG_NUMBER}.
+ * the value for {@link #ARG_NUMBER}.
* @param number The number that will be synthesized.
* @return This instance.
*/
@@ -714,7 +706,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_NUMBER} argument.
+ * Sets the {@link #ARG_NUMBER} argument.
* @param number A non-empty string of digits with an optional
* leading + or -.
* @return This instance.
@@ -725,21 +717,21 @@
}
/**
- * A builder for TtsSpans of type {@link TtsSpan#TYPE_ORDINAL}.
+ * A builder for TtsSpans of type {@link #TYPE_ORDINAL}.
*/
public static class OrdinalBuilder
extends SemioticClassBuilder<OrdinalBuilder> {
/**
- * Creates a builder for a TtsSpan of type {@link TtsSpan#TYPE_ORDINAL}.
+ * Creates a builder for a TtsSpan of type {@link #TYPE_ORDINAL}.
*/
public OrdinalBuilder() {
super(TtsSpan.TYPE_ORDINAL);
}
/**
- * Creates a TtsSpan of type {@link TtsSpan#TYPE_ORDINAL} and sets the
- * {@link TtsSpan#ARG_NUMBER} argument.
+ * Creates a TtsSpan of type {@link #TYPE_ORDINAL} and sets the
+ * {@link #ARG_NUMBER} argument.
* @param number The ordinal number to synthesize.
* @see #setNumber(long)
*/
@@ -749,8 +741,8 @@
}
/**
- * Creates a TtsSpan of type {@link TtsSpan#TYPE_ORDINAL} and sets the
- * {@link TtsSpan#ARG_NUMBER} argument.
+ * Creates a TtsSpan of type {@link #TYPE_ORDINAL} and sets the
+ * {@link #ARG_NUMBER} argument.
* @param number The number to synthesize.
* @see #setNumber(String)
*/
@@ -761,7 +753,7 @@
/**
* Convenience method that converts the number to a String and sets it
- * to the value for {@link TtsSpan#ARG_NUMBER}.
+ * to the value for {@link #ARG_NUMBER}.
* @param number The ordinal number that will be synthesized.
* @return This instance.
*/
@@ -770,7 +762,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_NUMBER} argument.
+ * Sets the {@link #ARG_NUMBER} argument.
* @param number A non-empty string of digits with an optional
* leading + or -.
* @return This instance.
@@ -781,22 +773,21 @@
}
/**
- * A builder for TtsSpans of type {@link TtsSpan#TYPE_DECIMAL}.
+ * A builder for TtsSpans of type {@link #TYPE_DECIMAL}.
*/
public static class DecimalBuilder
extends SemioticClassBuilder<DecimalBuilder> {
/**
- * Creates a builder for a TtsSpan of type {@link TtsSpan#TYPE_DECIMAL}.
+ * Creates a builder for a TtsSpan of type {@link #TYPE_DECIMAL}.
*/
public DecimalBuilder() {
super(TtsSpan.TYPE_DECIMAL);
}
/**
- * Creates a TtsSpan of type {@link TtsSpan#TYPE_DECIMAL} and sets the
- * {@link TtsSpan#ARG_INTEGER_PART} and
- * {@link TtsSpan#ARG_FRACTIONAL_PART} arguments.
+ * Creates a TtsSpan of type {@link #TYPE_DECIMAL} and sets the
+ * {@link #ARG_INTEGER_PART} and {@link #ARG_FRACTIONAL_PART} arguments.
* @see {@link #setArgumentsFromDouble(double, int, int)
*/
public DecimalBuilder(double number,
@@ -809,9 +800,8 @@
}
/**
- * Creates a TtsSpan of type {@link TtsSpan#TYPE_DECIMAL} and sets the
- * {@link TtsSpan#ARG_INTEGER_PART} and
- * {@link TtsSpan#ARG_FRACTIONAL_PART} arguments.
+ * Creates a TtsSpan of type {@link #TYPE_DECIMAL} and sets the
+ * {@link #ARG_INTEGER_PART} and {@link #ARG_FRACTIONAL_PART} arguments.
*/
public DecimalBuilder(String integerPart, String fractionalPart) {
this();
@@ -821,8 +811,8 @@
/**
* Convenience method takes a double and a maximum number of fractional
- * digits, it sets the {@link TtsSpan#ARG_INTEGER_PART} and
- * {@link TtsSpan#ARG_FRACTIONAL_PART} arguments.
+ * digits, it sets the {@link #ARG_INTEGER_PART} and
+ * {@link #ARG_FRACTIONAL_PART} arguments.
* @param number The number to be synthesized.
* @param minimumFractionDigits The minimum number of fraction digits
* that are pronounced.
@@ -856,7 +846,7 @@
/**
* Convenience method that converts the number to a String and sets it
- * to the value for {@link TtsSpan#ARG_INTEGER_PART}.
+ * to the value for {@link #ARG_INTEGER_PART}.
* @param integerPart The integer part of the decimal.
* @return This instance.
*/
@@ -865,7 +855,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_INTEGER_PART} argument.
+ * Sets the {@link #ARG_INTEGER_PART} argument.
* @param integerPart A non-empty string of digits with an optional
* leading + or -.
* @return This instance.
@@ -875,7 +865,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_FRACTIONAL_PART} argument.
+ * Sets the {@link #ARG_FRACTIONAL_PART} argument.
* @param fractionalPart A non-empty string of digits.
* @return This instance.
*/
@@ -886,23 +876,22 @@
}
/**
- * A builder for TtsSpans of type {@link TtsSpan#TYPE_FRACTION}.
+ * A builder for TtsSpans of type {@link #TYPE_FRACTION}.
*/
public static class FractionBuilder
extends SemioticClassBuilder<FractionBuilder> {
/**
- * Creates a builder for a TtsSpan of type
- * {@link TtsSpan#TYPE_FRACTION}.
+ * Creates a builder for a TtsSpan of type {@link #TYPE_FRACTION}.
*/
public FractionBuilder() {
super(TtsSpan.TYPE_FRACTION);
}
/**
- * Creates a TtsSpan of type {@link TtsSpan#TYPE_FRACTION} and sets the
- * {@link TtsSpan#ARG_INTEGER_PART}, {@link TtsSpan#ARG_NUMERATOR}, and
- * {@link TtsSpan#ARG_DENOMINATOR} arguments.
+ * Creates a TtsSpan of type {@link #TYPE_FRACTION} and sets the
+ * {@link #ARG_INTEGER_PART}, {@link #ARG_NUMERATOR}, and
+ * {@link #ARG_DENOMINATOR} arguments.
*/
public FractionBuilder(long integerPart,
long numerator,
@@ -913,10 +902,9 @@
setDenominator(denominator);
}
-
/**
* Convenience method that converts the integer to a String and sets the
- * argument {@link TtsSpan#ARG_NUMBER}.
+ * argument {@link #ARG_NUMBER}.
* @param integerPart The integer part.
* @return This instance.
*/
@@ -925,7 +913,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_INTEGER_PART} argument.
+ * Sets the {@link #ARG_INTEGER_PART} argument.
* @param integerPart A non-empty string of digits with an optional
* leading + or -.
* @return This instance.
@@ -936,7 +924,7 @@
/**
* Convenience method that converts the numerator to a String and sets
- * the argument {@link TtsSpan#ARG_NUMERATOR}.
+ * the argument {@link #ARG_NUMERATOR}.
* @param numerator The numerator.
* @return This instance.
*/
@@ -945,7 +933,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_NUMERATOR} argument.
+ * Sets the {@link #ARG_NUMERATOR} argument.
* @param numerator A non-empty string of digits with an optional
* leading + or -.
* @return This instance.
@@ -956,7 +944,7 @@
/**
* Convenience method that converts the denominator to a String and sets
- * the argument {@link TtsSpan#ARG_DENOMINATOR}.
+ * the argument {@link #ARG_DENOMINATOR}.
* @param denominator The denominator.
* @return This instance.
*/
@@ -965,7 +953,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_DENOMINATOR} argument.
+ * Sets the {@link #ARG_DENOMINATOR} argument.
* @param denominator A non-empty string of digits with an optional
* leading + or -.
* @return This instance.
@@ -976,13 +964,13 @@
}
/**
- * A builder for TtsSpans of type {@link TtsSpan #TYPE_MEASURE}.
+ * A builder for TtsSpans of type {@link #TYPE_MEASURE}.
*/
public static class MeasureBuilder
extends SemioticClassBuilder<MeasureBuilder> {
/**
- * Creates a builder for a TtsSpan of type {@link TtsSpan#TYPE_MEASURE}.
+ * Creates a builder for a TtsSpan of type {@link #TYPE_MEASURE}.
*/
public MeasureBuilder() {
super(TtsSpan.TYPE_MEASURE);
@@ -990,7 +978,7 @@
/**
* Convenience method that converts the number to a String and set it to
- * the value for {@link TtsSpan#ARG_NUMBER}.
+ * the value for {@link #ARG_NUMBER}.
* @param number The amount of the measure.
* @return This instance.
*/
@@ -999,7 +987,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_NUMBER} argument.
+ * Sets the {@link #ARG_NUMBER} argument.
* @param number A non-empty string of digits with an optional
* leading + or -.
* @return This instance.
@@ -1010,7 +998,7 @@
/**
* Convenience method that converts the integer part to a String and set
- * it to the value for {@link TtsSpan#ARG_INTEGER_PART}.
+ * it to the value for {@link #ARG_INTEGER_PART}.
* @param integerPart The integer part of a decimal or fraction.
* @return This instance.
*/
@@ -1019,7 +1007,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_INTEGER_PART} argument.
+ * Sets the {@link #ARG_INTEGER_PART} argument.
* @param integerPart The integer part of a decimal or fraction; a
* non-empty string of digits with an optional
* leading + or -.
@@ -1030,10 +1018,9 @@
}
/**
- * Sets the {@link TtsSpan#ARG_FRACTIONAL_PART} argument.
+ * Sets the {@link #ARG_FRACTIONAL_PART} argument.
* @param fractionalPart The fractional part of a decimal; a non-empty
- * string of digits with an optional
- * leading + or -.
+ * string of digits with an optional leading + or -.
* @return This instance.
*/
public MeasureBuilder setFractionalPart(String fractionalPart) {
@@ -1043,7 +1030,7 @@
/**
* Convenience method that converts the numerator to a String and set it
- * to the value for {@link TtsSpan#ARG_NUMERATOR}.
+ * to the value for {@link #ARG_NUMERATOR}.
* @param numerator The numerator of a fraction.
* @return This instance.
*/
@@ -1052,7 +1039,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_NUMERATOR} argument.
+ * Sets the {@link #ARG_NUMERATOR} argument.
* @param numerator The numerator of a fraction; a non-empty string of
* digits with an optional leading + or -.
* @return This instance.
@@ -1063,7 +1050,7 @@
/**
* Convenience method that converts the denominator to a String and set
- * it to the value for {@link TtsSpan#ARG_DENOMINATOR}.
+ * it to the value for {@link #ARG_DENOMINATOR}.
* @param denominator The denominator of a fraction.
* @return This instance.
*/
@@ -1072,7 +1059,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_DENOMINATOR} argument.
+ * Sets the {@link #ARG_DENOMINATOR} argument.
* @param denominator The denominator of a fraction; a non-empty string
* of digits with an optional leading + or -.
* @return This instance.
@@ -1082,7 +1069,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_UNIT} argument.
+ * Sets the {@link #ARG_UNIT} argument.
* @param unit The unit of the measure.
* @return This instance.
* @see {@link TtsSpan.ARG_UNIT}
@@ -1093,22 +1080,21 @@
}
/**
- * A builder for TtsSpans of type {@link TtsSpan #TYPE_TIME}.
+ * A builder for TtsSpans of type {@link #TYPE_TIME}.
*/
public static class TimeBuilder
extends SemioticClassBuilder<TimeBuilder> {
/**
- * Creates a builder for a TtsSpan of type {@link TtsSpan#TYPE_TIME}.
+ * Creates a builder for a TtsSpan of type {@link #TYPE_TIME}.
*/
public TimeBuilder() {
super(TtsSpan.TYPE_TIME);
}
/**
- * Creates a builder for a TtsSpan of type {@link TtsSpan#TYPE_TIME} and
- * sets the {@link TtsSpan#ARG_HOURS} and {@link TtsSpan#ARG_MINUTES}
- * arguments.
+ * Creates a builder for a TtsSpan of type {@link #TYPE_TIME} and
+ * sets the {@link #ARG_HOURS} and {@link #ARG_MINUTES} arguments.
*/
public TimeBuilder(int hours, int minutes) {
this();
@@ -1117,22 +1103,21 @@
}
/**
- * Sets the {@link TtsSpan#ARG_HOURS} argument.
- * @param hours The value to be set for hours. See
- * {@link TtsSpan#ARG_HOURS}.
+ * Sets the {@link #ARG_HOURS} argument.
+ * @param hours The value to be set for hours. See {@link #ARG_HOURS}.
* @return This instance.
- * @see {@link TtsSpan#ARG_HOURS}
+ * @see {@link #ARG_HOURS}
*/
public TimeBuilder setHours(int hours) {
return setIntArgument(TtsSpan.ARG_HOURS, hours);
}
/**
- * Sets the {@link TtsSpan#ARG_MINUTES} argument.
+ * Sets the {@link #ARG_MINUTES} argument.
* @param minutes The value to be set for minutes. See
- * {@link TtsSpan#ARG_MINUTES}.
+ * {@link #ARG_MINUTES}.
* @return This instance.
- * @see {@link TtsSpan#ARG_MINUTES}
+ * @see {@link #ARG_MINUTES}
*/
public TimeBuilder setMinutes(int minutes) {
return setIntArgument(TtsSpan.ARG_MINUTES, minutes);
@@ -1140,24 +1125,23 @@
}
/**
- * A builder for TtsSpans of type {@link TtsSpan #TYPE_DATE}.
+ * A builder for TtsSpans of type {@link #TYPE_DATE}.
*/
public static class DateBuilder
extends SemioticClassBuilder<DateBuilder> {
/**
- * Creates a builder for a TtsSpan of type {@link TtsSpan#TYPE_DATE}.
+ * Creates a builder for a TtsSpan of type {@link #TYPE_DATE}.
*/
public DateBuilder() {
super(TtsSpan.TYPE_DATE);
}
/**
- * Creates a builder for a TtsSpan of type {@link TtsSpan#TYPE_TIME} and
- * possibly sets the {@link TtsSpan#ARG_WEEKDAY},
- * {@link TtsSpan#ARG_DAY}, {@link TtsSpan#ARG_MONTH} and
- * {@link TtsSpan#ARG_YEAR} arguments. Pass null to any argument to
- * leave it unset.
+ * Creates a builder for a TtsSpan of type {@link #TYPE_TIME} and
+ * possibly sets the {@link #ARG_WEEKDAY}, {@link #ARG_DAY},
+ * {@link #ARG_MONTH} and {@link #ARG_YEAR} arguments. Pass null to any
+ * argument to leave it unset.
*/
public DateBuilder(Integer weekday,
Integer day,
@@ -1179,44 +1163,41 @@
}
/**
- * Sets the {@link TtsSpan#ARG_WEEKDAY} argument.
+ * Sets the {@link #ARG_WEEKDAY} argument.
* @param weekday The value to be set for weekday. See
- * {@link TtsSpan#ARG_WEEKDAY}.
+ * {@link #ARG_WEEKDAY}.
* @return This instance.
- * @see {@link TtsSpan#ARG_WEEKDAY}
+ * @see {@link #ARG_WEEKDAY}
*/
public DateBuilder setWeekday(int weekday) {
return setIntArgument(TtsSpan.ARG_WEEKDAY, weekday);
}
/**
- * Sets the {@link TtsSpan#ARG_DAY} argument.
- * @param day The value to be set for day. See
- * {@link TtsSpan#ARG_DAY}.
+ * Sets the {@link #ARG_DAY} argument.
+ * @param day The value to be set for day. See {@link #ARG_DAY}.
* @return This instance.
- * @see {@link TtsSpan#ARG_DAY}
+ * @see {@link #ARG_DAY}
*/
public DateBuilder setDay(int day) {
return setIntArgument(TtsSpan.ARG_DAY, day);
}
/**
- * Sets the {@link TtsSpan#ARG_MONTH} argument.
- * @param month The value to be set for month. See
- * {@link TtsSpan#ARG_MONTH}.
+ * Sets the {@link #ARG_MONTH} argument.
+ * @param month The value to be set for month. See {@link #ARG_MONTH}.
* @return This instance.
- * @see {@link TtsSpan#ARG_MONTH}
+ * @see {@link #ARG_MONTH}
*/
public DateBuilder setMonth(int month) {
return setIntArgument(TtsSpan.ARG_MONTH, month);
}
/**
- * Sets the {@link TtsSpan#ARG_YEAR} argument.
- * @param year The value to be set for year. See
- * {@link TtsSpan#ARG_YEAR}.
+ * Sets the {@link #ARG_YEAR} argument.
+ * @param year The value to be set for year. See {@link #ARG_YEAR}.
* @return This instance.
- * @see {@link TtsSpan#ARG_YEAR}
+ * @see {@link #ARG_YEAR}
*/
public DateBuilder setYear(int year) {
return setIntArgument(TtsSpan.ARG_YEAR, year);
@@ -1224,13 +1205,13 @@
}
/**
- * A builder for TtsSpans of type {@link TtsSpan #TYPE_MONEY}.
+ * A builder for TtsSpans of type {@link #TYPE_MONEY}.
*/
public static class MoneyBuilder
extends SemioticClassBuilder<MoneyBuilder> {
/**
- * Creates a TtsSpan of type {@link TtsSpan#TYPE_MONEY}.
+ * Creates a TtsSpan of type {@link #TYPE_MONEY}.
*/
public MoneyBuilder() {
super(TtsSpan.TYPE_MONEY);
@@ -1238,7 +1219,7 @@
/**
* Convenience method that converts the number to a String and set it to
- * the value for {@link TtsSpan#ARG_INTEGER_PART}.
+ * the value for {@link #ARG_INTEGER_PART}.
* @param integerPart The integer part of the amount.
* @return This instance.
*/
@@ -1247,7 +1228,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_INTEGER_PART} argument.
+ * Sets the {@link #ARG_INTEGER_PART} argument.
* @param integerPart A non-empty string of digits with an optional
* leading + or -.
* @return This instance.
@@ -1257,7 +1238,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_FRACTIONAL_PART} argument.
+ * Sets the {@link #ARG_FRACTIONAL_PART} argument.
* @param fractionalPart Can be a string of digits of any size.
* @return This instance.
*/
@@ -1266,7 +1247,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_CURRENCY} argument.
+ * Sets the {@link #ARG_CURRENCY} argument.
* @param currency Should be a ISO4217 currency code, e.g. "USD".
* @return This instance.
*/
@@ -1275,7 +1256,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_QUANTITY} argument.
+ * Sets the {@link #ARG_QUANTITY} argument.
* @param quantity
* @return This instance.
*/
@@ -1285,21 +1266,21 @@
}
/**
- * A builder for TtsSpans of type {@link TtsSpan #TYPE_TELEPHONE}.
+ * A builder for TtsSpans of type {@link #TYPE_TELEPHONE}.
*/
public static class TelephoneBuilder
extends SemioticClassBuilder<TelephoneBuilder> {
/**
- * Creates a TtsSpan of type {@link TtsSpan#TYPE_TELEPHONE}.
+ * Creates a TtsSpan of type {@link #TYPE_TELEPHONE}.
*/
public TelephoneBuilder() {
super(TtsSpan.TYPE_TELEPHONE);
}
/**
- * Creates a TtsSpan of type {@link TtsSpan#TYPE_TELEPHONE} and sets the
- * {@link TtsSpan#ARG_NUMBER_PARTS} argument.
+ * Creates a TtsSpan of type {@link #TYPE_TELEPHONE} and sets the
+ * {@link #ARG_NUMBER_PARTS} argument.
*/
public TelephoneBuilder(String numberParts) {
this();
@@ -1307,7 +1288,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_COUNTRY_CODE} argument.
+ * Sets the {@link #ARG_COUNTRY_CODE} argument.
* @param countryCode The country code can be a series of digits
* optionally prefixed with a "+".
* @return This instance.
@@ -1317,7 +1298,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_NUMBER_PARTS} argument.
+ * Sets the {@link #ARG_NUMBER_PARTS} argument.
* @param numberParts The main telephone number. Can be a series of
* digits and letters separated by spaces, "/", "-" or ".".
* @return This instance.
@@ -1327,7 +1308,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_EXTENSION} argument.
+ * Sets the {@link #ARG_EXTENSION} argument.
* @param extension The extension can be a series of digits.
* @return This instance.
*/
@@ -1337,20 +1318,20 @@
}
/**
- * A builder for TtsSpans of type {@link TtsSpan #TYPE_ELECTRONIC}.
+ * A builder for TtsSpans of type {@link #TYPE_ELECTRONIC}.
*/
public static class ElectronicBuilder
extends SemioticClassBuilder<ElectronicBuilder> {
/**
- * Creates a TtsSpan of type {@link TtsSpan#TYPE_ELECTRONIC}.
+ * Creates a TtsSpan of type {@link #TYPE_ELECTRONIC}.
*/
public ElectronicBuilder() {
super(TtsSpan.TYPE_ELECTRONIC);
}
/**
- * Sets the {@link TtsSpan#ARG_USERNAME} and {@link TtsSpan#ARG_DOMAIN}
+ * Sets the {@link #ARG_USERNAME} and {@link #ARG_DOMAIN}
* arguments, representing an email address.
* @param username The part before the @ in the email address.
* @param domain The part after the @ in the email address.
@@ -1362,7 +1343,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_PROTOCOL} argument.
+ * Sets the {@link #ARG_PROTOCOL} argument.
* @param protocol The protocol of the URI. Examples are "http" and
* "ftp".
* @return This instance.
@@ -1372,7 +1353,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_USERNAME} argument.
+ * Sets the {@link #ARG_USERNAME} argument.
* @return This instance.
*/
public ElectronicBuilder setUsername(String username) {
@@ -1380,7 +1361,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_PASSWORD} argument.
+ * Sets the {@link #ARG_PASSWORD} argument.
* @return This instance.
*/
public ElectronicBuilder setPassword(String password) {
@@ -1388,7 +1369,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_DOMAIN} argument.
+ * Sets the {@link #ARG_DOMAIN} argument.
* @param domain The domain, for example "source.android.com".
* @return This instance.
*/
@@ -1397,7 +1378,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_PORT} argument.
+ * Sets the {@link #ARG_PORT} argument.
* @return This instance.
*/
public ElectronicBuilder setPort(int port) {
@@ -1405,7 +1386,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_PATH} argument.
+ * Sets the {@link #ARG_PATH} argument.
* @param path For example "source/index.html".
* @return This instance.
*/
@@ -1414,7 +1395,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_QUERY_STRING} argument.
+ * Sets the {@link #ARG_QUERY_STRING} argument.
* @param queryString For example "arg=value&argtwo=value".
* @return This instance.
*/
@@ -1423,7 +1404,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_FRAGMENT_ID} argument.
+ * Sets the {@link #ARG_FRAGMENT_ID} argument.
* @return This instance.
*/
public ElectronicBuilder setFragmentId(String fragmentId) {
@@ -1432,22 +1413,21 @@
}
/**
- * A builder for TtsSpans of type {@link TtsSpan #TYPE_DIGITS}.
+ * A builder for TtsSpans of type {@link #TYPE_DIGITS}.
*/
public static class DigitsBuilder
extends SemioticClassBuilder<DigitsBuilder> {
/**
- * Creates a builder for a TtsSpan of type
- * {@link TtsSpan#TYPE_VERBATIM}.
+ * Creates a builder for a TtsSpan of type {@link #TYPE_DIGITS}.
*/
public DigitsBuilder() {
super(TtsSpan.TYPE_DIGITS);
}
/**
- * Creates a builder for a TtsSpan of type {@link TtsSpan#TYPE_DIGITS}
- * and sets the {@link TtsSpan#ARG_DIGITS} argument.
+ * Creates a builder for a TtsSpan of type {@link #TYPE_DIGITS}
+ * and sets the {@link #ARG_DIGITS} argument.
*/
public DigitsBuilder(String digits) {
this();
@@ -1455,7 +1435,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_DIGITS} argument.
+ * Sets the {@link #ARG_DIGITS} argument.
* @param digits A string of digits.
* @return This instance.
*/
@@ -1465,22 +1445,21 @@
}
/**
- * A builder for TtsSpans of type {@link TtsSpan #TYPE_VERBATIM}.
+ * A builder for TtsSpans of type {@link #TYPE_VERBATIM}.
*/
public static class VerbatimBuilder
extends SemioticClassBuilder<VerbatimBuilder> {
/**
- * Creates a builder for a TtsSpan of type
- * {@link TtsSpan#TYPE_VERBATIM}.
+ * Creates a builder for a TtsSpan of type {@link #TYPE_VERBATIM}.
*/
public VerbatimBuilder() {
super(TtsSpan.TYPE_VERBATIM);
}
/**
- * Creates a builder for a TtsSpan of type {@link TtsSpan#TYPE_VERBATIM}
- * and sets the {@link TtsSpan#ARG_VERBATIM} argument.
+ * Creates a builder for a TtsSpan of type {@link #TYPE_VERBATIM}
+ * and sets the {@link #ARG_VERBATIM} argument.
*/
public VerbatimBuilder(String verbatim) {
this();
@@ -1488,7 +1467,7 @@
}
/**
- * Sets the {@link TtsSpan#ARG_VERBATIM} argument.
+ * Sets the {@link #ARG_VERBATIM} argument.
* @param verbatim A string of characters that will be read verbatim,
* except whitespace.
* @return This instance.
diff --git a/core/java/android/transition/ChangeBounds.java b/core/java/android/transition/ChangeBounds.java
index 6246cbe..ebb1a5c 100644
--- a/core/java/android/transition/ChangeBounds.java
+++ b/core/java/android/transition/ChangeBounds.java
@@ -107,6 +107,8 @@
*
* @param reparent true if the transition should track the parent
* container of target views and animate parent changes.
+ * @deprecated Use {@link android.transition.ChangeTransform} to handle
+ * transitions between different parents.
*/
public void setReparent(boolean reparent) {
mReparent = reparent;
diff --git a/core/java/android/transition/ChangeImageTransform.java b/core/java/android/transition/ChangeImageTransform.java
index 4b230eb..d7a9120 100644
--- a/core/java/android/transition/ChangeImageTransform.java
+++ b/core/java/android/transition/ChangeImageTransform.java
@@ -16,7 +16,6 @@
package android.transition;
import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.TypeEvaluator;
import android.content.Context;
@@ -196,28 +195,6 @@
private ObjectAnimator createMatrixAnimator(final ImageView imageView, Matrix startMatrix,
final Matrix endMatrix) {
return ObjectAnimator.ofObject(imageView, ANIMATED_TRANSFORM_PROPERTY,
- new MatrixEvaluator(), startMatrix, endMatrix);
+ new TransitionUtils.MatrixEvaluator(), startMatrix, endMatrix);
}
-
- private static class MatrixEvaluator implements TypeEvaluator<Matrix> {
-
- float[] mTempStartValues = new float[9];
-
- float[] mTempEndValues = new float[9];
-
- Matrix mTempMatrix = new Matrix();
-
- @Override
- public Matrix evaluate(float fraction, Matrix startValue, Matrix endValue) {
- startValue.getValues(mTempStartValues);
- endValue.getValues(mTempEndValues);
- for (int i = 0; i < 9; i++) {
- float diff = mTempEndValues[i] - mTempStartValues[i];
- mTempEndValues[i] = mTempStartValues[i] + (fraction * diff);
- }
- mTempMatrix.setValues(mTempEndValues);
- return mTempMatrix;
- }
- }
-
}
diff --git a/core/java/android/transition/ChangeTransform.java b/core/java/android/transition/ChangeTransform.java
index e9be3b9..d579f54 100644
--- a/core/java/android/transition/ChangeTransform.java
+++ b/core/java/android/transition/ChangeTransform.java
@@ -16,72 +16,134 @@
package android.transition;
import android.animation.Animator;
-import android.animation.FloatArrayEvaluator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Matrix;
import android.util.AttributeSet;
-import android.util.FloatProperty;
import android.util.Property;
+import android.view.GhostView;
import android.view.View;
import android.view.ViewGroup;
+import com.android.internal.R;
/**
* This Transition captures scale and rotation for Views before and after the
* scene change and animates those changes during the transition.
*
- * <p>ChangeTransform does not work when the pivot changes between scenes, so either the
- * pivot must be set to prevent automatic pivot adjustment or the View's size must be unchanged.</p>
+ * A change in parent is handled as well by capturing the transforms from
+ * the parent before and after the scene change and animating those during the
+ * transition.
*/
public class ChangeTransform extends Transition {
private static final String TAG = "ChangeTransform";
- private static final String PROPNAME_SCALE_X = "android:changeTransform:scaleX";
- private static final String PROPNAME_SCALE_Y = "android:changeTransform:scaleY";
- private static final String PROPNAME_ROTATION_X = "android:changeTransform:rotationX";
- private static final String PROPNAME_ROTATION_Y = "android:changeTransform:rotationY";
- private static final String PROPNAME_ROTATION_Z = "android:changeTransform:rotationZ";
- private static final String PROPNAME_PIVOT_X = "android:changeTransform:pivotX";
- private static final String PROPNAME_PIVOT_Y = "android:changeTransform:pivotY";
+ private static final String PROPNAME_MATRIX = "android:changeTransform:matrix";
+ private static final String PROPNAME_TRANSFORMS = "android:changeTransform:transforms";
+ private static final String PROPNAME_PARENT = "android:changeTransform:parent";
+ private static final String PROPNAME_PARENT_MATRIX = "android:changeTransform:parentMatrix";
private static final String[] sTransitionProperties = {
- PROPNAME_SCALE_X,
- PROPNAME_SCALE_Y,
- PROPNAME_ROTATION_X,
- PROPNAME_ROTATION_Y,
- PROPNAME_ROTATION_Z,
+ PROPNAME_MATRIX,
+ PROPNAME_TRANSFORMS,
+ PROPNAME_PARENT_MATRIX,
};
- private static final FloatProperty<View>[] sChangedProperties = new FloatProperty[] {
- (FloatProperty) View.SCALE_X,
- (FloatProperty) View.SCALE_Y,
- (FloatProperty) View.ROTATION_X,
- (FloatProperty) View.ROTATION_Y,
- (FloatProperty) View.ROTATION,
- };
-
- private static Property<View, float[]> TRANSFORMS = new Property<View, float[]>(float[].class,
- "transforms") {
- @Override
- public float[] get(View object) {
- return null;
- }
-
- @Override
- public void set(View view, float[] values) {
- for (int i = 0; i < values.length; i++) {
- float value = values[i];
- if (!Float.isNaN(value)) {
- sChangedProperties[i].setValue(view, value);
+ private static final Property<View, Matrix> ANIMATION_MATRIX_PROPERTY =
+ new Property<View, Matrix>(Matrix.class, "animationMatrix") {
+ @Override
+ public Matrix get(View object) {
+ return null;
}
- }
- }
- };
+
+ @Override
+ public void set(View object, Matrix value) {
+ object.setAnimationMatrix(value);
+ }
+ };
+
+ private boolean mUseOverlay = true;
+ private boolean mReparent = true;
+ private Matrix mTempMatrix = new Matrix();
public ChangeTransform() {}
public ChangeTransform(Context context, AttributeSet attrs) {
super(context, attrs);
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ChangeTransform);
+ mUseOverlay = a.getBoolean(R.styleable.ChangeTransform_reparentWithOverlay, true);
+ mReparent = a.getBoolean(R.styleable.ChangeTransform_reparent, true);
+ a.recycle();
+ }
+
+ /**
+ * Returns whether changes to parent should use an overlay or not. When the parent
+ * change doesn't use an overlay, it affects the transforms of the child. The
+ * default value is <code>true</code>.
+ *
+ * <p>Note: when Overlays are not used when a parent changes, a view can be clipped when
+ * it moves outside the bounds of its parent. Setting
+ * {@link android.view.ViewGroup#setClipChildren(boolean)} and
+ * {@link android.view.ViewGroup#setClipToPadding(boolean)} can help. Also, when
+ * Overlays are not used and the parent is animating its location, the position of the
+ * child view will be relative to its parent's final position, so it may appear to "jump"
+ * at the beginning.</p>
+ *
+ * @return <code>true</code> when a changed parent should execute the transition
+ * inside the scene root's overlay or <code>false</code> if a parent change only
+ * affects the transform of the transitioning view.
+ */
+ public boolean getReparentWithOverlay() {
+ return mUseOverlay;
+ }
+
+ /**
+ * Sets whether changes to parent should use an overlay or not. When the parent
+ * change doesn't use an overlay, it affects the transforms of the child. The
+ * default value is <code>true</code>.
+ *
+ * <p>Note: when Overlays are not used when a parent changes, a view can be clipped when
+ * it moves outside the bounds of its parent. Setting
+ * {@link android.view.ViewGroup#setClipChildren(boolean)} and
+ * {@link android.view.ViewGroup#setClipToPadding(boolean)} can help. Also, when
+ * Overlays are not used and the parent is animating its location, the position of the
+ * child view will be relative to its parent's final position, so it may appear to "jump"
+ * at the beginning.</p>
+ *
+ * @return <code>true</code> when a changed parent should execute the transition
+ * inside the scene root's overlay or <code>false</code> if a parent change only
+ * affects the transform of the transitioning view.
+ */
+ public void setReparentWithOverlay(boolean reparentWithOverlay) {
+ mUseOverlay = reparentWithOverlay;
+ }
+
+ /**
+ * Returns whether parent changes will be tracked by the ChangeTransform. If parent
+ * changes are tracked, then the transform will adjust to the transforms of the
+ * different parents. If they aren't tracked, only the transforms of the transitioning
+ * view will be tracked. Default is true.
+ *
+ * @return whether parent changes will be tracked by the ChangeTransform.
+ */
+ public boolean getReparent() {
+ return mReparent;
+ }
+
+ /**
+ * Sets whether parent changes will be tracked by the ChangeTransform. If parent
+ * changes are tracked, then the transform will adjust to the transforms of the
+ * different parents. If they aren't tracked, only the transforms of the transitioning
+ * view will be tracked. Default is true.
+ *
+ * @param reparent Set to true to track parent changes or false to only track changes
+ * of the transitioning view without considering the parent change.
+ */
+ public void setReparent(boolean reparent) {
+ mReparent = reparent;
}
@Override
@@ -89,19 +151,29 @@
return sTransitionProperties;
}
- private void captureValues(TransitionValues values) {
- View view = values.view;
+ private void captureValues(TransitionValues transitionValues) {
+ View view = transitionValues.view;
if (view.getVisibility() == View.GONE) {
return;
}
-
- values.values.put(PROPNAME_SCALE_X, view.getScaleX());
- values.values.put(PROPNAME_SCALE_Y, view.getScaleY());
- values.values.put(PROPNAME_PIVOT_X, view.getPivotX());
- values.values.put(PROPNAME_PIVOT_Y, view.getPivotY());
- values.values.put(PROPNAME_ROTATION_X, view.getRotationX());
- values.values.put(PROPNAME_ROTATION_Y, view.getRotationY());
- values.values.put(PROPNAME_ROTATION_Z, view.getRotation());
+ transitionValues.values.put(PROPNAME_PARENT, view.getParent());
+ Transforms transforms = new Transforms(view);
+ transitionValues.values.put(PROPNAME_TRANSFORMS, transforms);
+ Matrix matrix = view.getMatrix();
+ if (matrix == null || matrix.isIdentity()) {
+ matrix = null;
+ } else {
+ matrix = new Matrix(matrix);
+ }
+ transitionValues.values.put(PROPNAME_MATRIX, matrix);
+ if (mReparent) {
+ Matrix parentMatrix = new Matrix();
+ ViewGroup parent = (ViewGroup) view.getParent();
+ parent.transformMatrixToGlobal(parentMatrix);
+ parentMatrix.preTranslate(-parent.getScrollX(), -parent.getScrollY());
+ transitionValues.values.put(PROPNAME_PARENT_MATRIX, parentMatrix);
+ }
+ return;
}
@Override
@@ -115,57 +187,252 @@
}
@Override
- public Animator createAnimator(final ViewGroup sceneRoot, TransitionValues startValues,
+ public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
TransitionValues endValues) {
- if (startValues == null || endValues == null
- || !startValues.values.containsKey(PROPNAME_SCALE_X)
- || !endValues.values.containsKey(PROPNAME_SCALE_X)
- || !isPivotSame(startValues, endValues)
- || !isChanged(startValues, endValues)) {
+ if (startValues == null || endValues == null ||
+ !startValues.values.containsKey(PROPNAME_PARENT) ||
+ !endValues.values.containsKey(PROPNAME_PARENT)) {
return null;
}
- float[] start = createValues(startValues);
- float[] end = createValues(endValues);
- for (int i = 0; i < start.length; i++) {
- if (start[i] == end[i]) {
- start[i] = Float.NaN;
- end[i] = Float.NaN;
- } else {
- sChangedProperties[i].setValue(endValues.view, start[i]);
+ ViewGroup startParent = (ViewGroup) startValues.values.get(PROPNAME_PARENT);
+ ViewGroup endParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT);
+ boolean handleParentChange = mReparent && !parentsMatch(startParent, endParent);
+
+ Matrix startMatrix = (Matrix) startValues.view.getTag(R.id.transitionTransform);
+ if (startMatrix != null) {
+ startValues.values.put(PROPNAME_MATRIX, startMatrix);
+ }
+
+ Matrix startParentMatrix = (Matrix) startValues.view.getTag(R.id.parentMatrix);
+ if (startParentMatrix != null) {
+ startValues.values.put(PROPNAME_PARENT_MATRIX, startParentMatrix);
+ }
+
+ // First handle the parent change:
+ if (handleParentChange) {
+ setMatricesForParent(startValues, endValues);
+ }
+
+ // Next handle the normal matrix transform:
+ ObjectAnimator transformAnimator = createTransformAnimator(startValues, endValues);
+
+ if (handleParentChange && transformAnimator != null && mUseOverlay) {
+ createGhostView(sceneRoot, startValues, endValues);
+ }
+
+ return transformAnimator;
+ }
+
+ private ObjectAnimator createTransformAnimator(TransitionValues startValues,
+ TransitionValues endValues) {
+ Matrix startMatrix = (Matrix) startValues.values.get(PROPNAME_MATRIX);
+ Matrix endMatrix = (Matrix) endValues.values.get(PROPNAME_MATRIX);
+
+ if (startMatrix == null) {
+ startMatrix = Matrix.IDENTITY_MATRIX;
+ }
+
+ if (endMatrix == null) {
+ endMatrix = Matrix.IDENTITY_MATRIX;
+ }
+
+ if (startMatrix.equals(endMatrix)) {
+ return null;
+ }
+
+ final Transforms transforms = (Transforms) endValues.values.get(PROPNAME_TRANSFORMS);
+
+ // clear the transform properties so that we can use the animation matrix instead
+ final View view = endValues.view;
+ setIdentityTransforms(view);
+
+ ObjectAnimator animator = ObjectAnimator.ofObject(view, ANIMATION_MATRIX_PROPERTY,
+ new TransitionUtils.MatrixEvaluator(), startMatrix, endMatrix);
+
+ AnimatorListenerAdapter listener = new AnimatorListenerAdapter() {
+ private boolean mIsCanceled;
+ private Matrix mTempMatrix;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mIsCanceled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!mIsCanceled) {
+ view.setTagInternal(R.id.transitionTransform, null);
+ view.setTagInternal(R.id.parentMatrix, null);
+ }
+ ANIMATION_MATRIX_PROPERTY.set(view, null);
+ transforms.restore(view);
+ }
+
+ @Override
+ public void onAnimationPause(Animator animation) {
+ ValueAnimator animator = (ValueAnimator) animation;
+ Matrix currentMatrix = (Matrix) animator.getAnimatedValue();
+ if (mTempMatrix == null) {
+ mTempMatrix = new Matrix(currentMatrix);
+ } else {
+ mTempMatrix.set(currentMatrix);
+ }
+ view.setTagInternal(R.id.transitionTransform, mTempMatrix);
+ transforms.restore(view);
+ }
+
+ @Override
+ public void onAnimationResume(Animator animation) {
+ setIdentityTransforms(view);
+ }
+ };
+
+ animator.addListener(listener);
+ animator.addPauseListener(listener);
+ return animator;
+ }
+
+ private boolean parentsMatch(ViewGroup startParent, ViewGroup endParent) {
+ boolean parentsMatch = false;
+ if (!isValidTarget(startParent) || !isValidTarget(endParent)) {
+ parentsMatch = startParent == endParent;
+ } else {
+ TransitionValues endValues = getMatchedTransitionValues(startParent, true);
+ if (endValues != null) {
+ parentsMatch = endParent == endValues.view;
}
}
- FloatArrayEvaluator evaluator = new FloatArrayEvaluator(new float[start.length]);
- return ObjectAnimator.ofObject(endValues.view, TRANSFORMS, evaluator, start, end);
+ return parentsMatch;
}
- private static float[] createValues(TransitionValues transitionValues) {
- float[] values = new float[sChangedProperties.length];
- for (int i = 0; i < values.length; i++) {
- values[i] = (Float) transitionValues.values.get(sTransitionProperties[i]);
+ private void createGhostView(final ViewGroup sceneRoot, TransitionValues startValues,
+ TransitionValues endValues) {
+ View view = endValues.view;
+
+ Matrix endMatrix = (Matrix) endValues.values.get(PROPNAME_PARENT_MATRIX);
+ Matrix localEndMatrix = new Matrix(endMatrix);
+ sceneRoot.transformMatrixToLocal(localEndMatrix);
+
+ GhostView ghostView = GhostView.addGhost(view, sceneRoot, localEndMatrix);
+
+ Transition outerTransition = this;
+ while (outerTransition.mParent != null) {
+ outerTransition = outerTransition.mParent;
}
- return values;
+ GhostListener listener = new GhostListener(view, ghostView, endMatrix);
+ outerTransition.addListener(listener);
+
+ if (startValues.view != endValues.view) {
+ startValues.view.setTransitionAlpha(0);
+ }
+ view.setTransitionAlpha(1);
}
- private static boolean isPivotSame(TransitionValues startValues, TransitionValues endValues) {
- float startPivotX = (Float) startValues.values.get(PROPNAME_PIVOT_X);
- float startPivotY = (Float) startValues.values.get(PROPNAME_PIVOT_Y);
- float endPivotX = (Float) endValues.values.get(PROPNAME_PIVOT_X);
- float endPivotY = (Float) endValues.values.get(PROPNAME_PIVOT_Y);
+ private void setMatricesForParent(TransitionValues startValues, TransitionValues endValues) {
+ Matrix endParentMatrix = (Matrix) endValues.values.get(PROPNAME_PARENT_MATRIX);
+ endValues.view.setTagInternal(R.id.parentMatrix, endParentMatrix);
- // We don't support pivot changes, because they could be automatically set
- // and we can't end the state in an automatic state.
- return startPivotX == endPivotX && startPivotY == endPivotY;
+ Matrix toLocal = mTempMatrix;
+ toLocal.reset();
+ endParentMatrix.invert(toLocal);
+
+ Matrix startLocal = (Matrix) startValues.values.get(PROPNAME_MATRIX);
+ if (startLocal == null) {
+ startLocal = new Matrix();
+ startValues.values.put(PROPNAME_MATRIX, startLocal);
+ }
+
+ Matrix startParentMatrix = (Matrix) startValues.values.get(PROPNAME_PARENT_MATRIX);
+ startLocal.postConcat(startParentMatrix);
+ startLocal.postConcat(toLocal);
}
- private static boolean isChanged(TransitionValues startValues, TransitionValues endValues) {
- for (int i = 0; i < sChangedProperties.length; i++) {
- Object start = startValues.values.get(sTransitionProperties[i]);
- Object end = endValues.values.get(sTransitionProperties[i]);
- if (!start.equals(end)) {
- return true;
+ private static void setIdentityTransforms(View view) {
+ setTransforms(view, 0, 0, 0, 1, 1, 0, 0, 0);
+ }
+
+ private static void setTransforms(View view, float translationX, float translationY,
+ float translationZ, float scaleX, float scaleY, float rotationX,
+ float rotationY, float rotationZ) {
+ view.setTranslationX(translationX);
+ view.setTranslationY(translationY);
+ view.setTranslationZ(translationZ);
+ view.setScaleX(scaleX);
+ view.setScaleY(scaleY);
+ view.setRotationX(rotationX);
+ view.setRotationY(rotationY);
+ view.setRotation(rotationZ);
+ }
+
+ private static class Transforms {
+ public final float translationX;
+ public final float translationY;
+ public final float translationZ;
+ public final float scaleX;
+ public final float scaleY;
+ public final float rotationX;
+ public final float rotationY;
+ public final float rotationZ;
+
+ public Transforms(View view) {
+ translationX = view.getTranslationX();
+ translationY = view.getTranslationY();
+ translationZ = view.getTranslationZ();
+ scaleX = view.getScaleX();
+ scaleY = view.getScaleY();
+ rotationX = view.getRotationX();
+ rotationY = view.getRotationY();
+ rotationZ = view.getRotation();
+ }
+
+ public void restore(View view) {
+ setTransforms(view, translationX, translationY, translationZ, scaleX, scaleY,
+ rotationX, rotationY, rotationZ);
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (!(that instanceof Transforms)) {
+ return false;
}
+ Transforms thatTransform = (Transforms) that;
+ return thatTransform.translationX == translationX &&
+ thatTransform.translationY == translationY &&
+ thatTransform.translationZ == translationZ &&
+ thatTransform.scaleX == scaleX &&
+ thatTransform.scaleY == scaleY &&
+ thatTransform.rotationX == rotationX &&
+ thatTransform.rotationY == rotationY &&
+ thatTransform.rotationZ == rotationZ;
}
- return false;
+ }
+
+ private static class GhostListener extends Transition.TransitionListenerAdapter {
+ private View mView;
+ private GhostView mGhostView;
+ private Matrix mEndMatrix;
+
+ public GhostListener(View view, GhostView ghostView, Matrix endMatrix) {
+ mView = view;
+ mGhostView = ghostView;
+ mEndMatrix = endMatrix;
+ }
+
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ transition.removeListener(this);
+ GhostView.removeGhost(mView);
+ }
+
+ @Override
+ public void onTransitionPause(Transition transition) {
+ mGhostView.setVisibility(View.INVISIBLE);
+ }
+
+ @Override
+ public void onTransitionResume(Transition transition) {
+ mGhostView.setVisibility(View.VISIBLE);
+ }
}
}
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 0d32d40..59ba71f 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -112,8 +112,8 @@
*
* Further information on XML resource descriptions for transitions can be found for
* {@link android.R.styleable#Transition}, {@link android.R.styleable#TransitionSet},
- * {@link android.R.styleable#TransitionTarget}, {@link android.R.styleable#Fade}, and
- * {@link android.R.styleable#Slide}.
+ * {@link android.R.styleable#TransitionTarget}, {@link android.R.styleable#Fade},
+ * {@link android.R.styleable#Slide}, and {@link android.R.styleable#ChangeTransform}.
*
*/
public abstract class Transition implements Cloneable {
@@ -1755,24 +1755,40 @@
// if oldValues null, then transition didn't care to stash values,
// and won't get canceled
if (oldValues != null && newValues != null) {
- for (String key : oldValues.values.keySet()) {
- Object oldValue = oldValues.values.get(key);
- Object newValue = newValues.values.get(key);
- if (oldValue != null && newValue != null &&
- !oldValue.equals(newValue)) {
- valuesChanged = true;
- if (DBG) {
- Log.d(LOG_TAG, "Transition.playTransition: " +
- "oldValue != newValue for " + key +
- ": old, new = " + oldValue + ", " + newValue);
+ String[] properties = getTransitionProperties();
+ if (properties != null) {
+ int count = properties.length;
+ for (int i = 0; i < count; i++) {
+ if (isValueChanged(oldValues, newValues, properties[i])) {
+ valuesChanged = true;
+ break;
}
- break;
+ }
+ } else {
+ for (String key : oldValues.values.keySet()) {
+ if (isValueChanged(oldValues, newValues, key)) {
+ valuesChanged = true;
+ break;
+ }
}
}
}
return valuesChanged;
}
+ private static boolean isValueChanged(TransitionValues oldValues, TransitionValues newValues,
+ String key) {
+ Object oldValue = oldValues.values.get(key);
+ Object newValue = newValues.values.get(key);
+ boolean changed = (oldValue != null && newValue != null && !oldValue.equals(newValue));
+ if (DBG && changed) {
+ Log.d(LOG_TAG, "Transition.playTransition: " +
+ "oldValue != newValue for " + key +
+ ": old, new = " + oldValue + ", " + newValue);
+ }
+ return changed;
+ }
+
/**
* This is a utility method used by subclasses to handle standard parts of
* setting up and running an Animator: it sets the {@link #getDuration()
diff --git a/core/java/android/transition/TransitionUtils.java b/core/java/android/transition/TransitionUtils.java
index 931d46a..b0c9e9a 100644
--- a/core/java/android/transition/TransitionUtils.java
+++ b/core/java/android/transition/TransitionUtils.java
@@ -18,6 +18,8 @@
import android.animation.Animator;
import android.animation.AnimatorSet;
+import android.animation.TypeEvaluator;
+import android.graphics.Matrix;
/**
* Static utility methods for Transitions.
@@ -37,4 +39,25 @@
return animatorSet;
}
}
+
+ public static class MatrixEvaluator implements TypeEvaluator<Matrix> {
+
+ float[] mTempStartValues = new float[9];
+
+ float[] mTempEndValues = new float[9];
+
+ Matrix mTempMatrix = new Matrix();
+
+ @Override
+ public Matrix evaluate(float fraction, Matrix startValue, Matrix endValue) {
+ startValue.getValues(mTempStartValues);
+ endValue.getValues(mTempEndValues);
+ for (int i = 0; i < 9; i++) {
+ float diff = mTempEndValues[i] - mTempStartValues[i];
+ mTempEndValues[i] = mTempStartValues[i] + (fraction * diff);
+ }
+ mTempMatrix.setValues(mTempEndValues);
+ return mTempMatrix;
+ }
+ }
}
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 79dbb49..81c69d1 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -63,8 +63,6 @@
private static final String[] sTransitionProperties = {
PROPNAME_VISIBILITY,
- PROPNAME_PARENT,
- PROPNAME_SCREEN_LOCATION,
};
private static class VisibilityInfo {
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 8c9b819..de90899 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -349,6 +349,8 @@
*/
abstract HardwareLayer createTextureLayer();
+ abstract void buildLayer(RenderNode node);
+
abstract boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap);
/**
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 681717c..964b054 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -657,11 +657,15 @@
/** Key code constant: TV data service key.
* Displays data services like weather, sports. */
public static final int KEYCODE_TV_DATA_SERVICE = 230;
+ /** Key code constant: Voice Assist key.
+ * Launches the global voice assist activity. Not delivered to applications. */
+ public static final int KEYCODE_VOICE_ASSIST = 231;
- private static final int LAST_KEYCODE = KEYCODE_TV_DATA_SERVICE;
+ private static final int LAST_KEYCODE = KEYCODE_VOICE_ASSIST;
// NOTE: If you add a new keycode here you must also add it to:
// isSystem()
+ // isWakeKey()
// frameworks/native/include/android/keycodes.h
// frameworks/native/include/input/InputEventLabels.h
// frameworks/base/core/res/res/values/attrs.xml
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index c7f16e0..9433237 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -19,6 +19,7 @@
import android.animation.Animator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
+import android.animation.Animator.AnimatorListener;
import android.graphics.Canvas;
import android.graphics.CanvasProperty;
import android.graphics.Paint;
@@ -93,6 +94,14 @@
private long mUnscaledDuration = 300;
private long mUnscaledStartDelay = 0;
+ // If this is true, we will run any start delays on the UI thread. This is
+ // the safe default, and is necessary to ensure start listeners fire at
+ // the correct time. Animators created by RippleDrawable (the
+ // CanvasProperty<> ones) do not have this expectation, and as such will
+ // set this to false so that the renderthread handles the startdelay instead
+ private final boolean mUiThreadHandlesDelay;
+ private long mStartDelay = 0;
+ private long mStartTime;
public static int mapViewPropertyToRenderProperty(int viewProperty) {
return sViewPropertyAnimatorMap.get(viewProperty);
@@ -101,6 +110,7 @@
public RenderNodeAnimator(int property, float finalValue) {
mRenderProperty = property;
mFinalValue = finalValue;
+ mUiThreadHandlesDelay = true;
init(nCreateAnimator(new WeakReference<RenderNodeAnimator>(this),
property, finalValue));
}
@@ -109,6 +119,7 @@
init(nCreateCanvasPropertyFloatAnimator(
new WeakReference<RenderNodeAnimator>(this),
property.getNativeContainer(), finalValue));
+ mUiThreadHandlesDelay = false;
}
/**
@@ -123,11 +134,13 @@
init(nCreateCanvasPropertyPaintAnimator(
new WeakReference<RenderNodeAnimator>(this),
property.getNativeContainer(), paintField, finalValue));
+ mUiThreadHandlesDelay = false;
}
public RenderNodeAnimator(int x, int y, float startRadius, float endRadius) {
init(nCreateRevealAnimator(new WeakReference<RenderNodeAnimator>(this),
x, y, startRadius, endRadius));
+ mUiThreadHandlesDelay = true;
}
private void init(long ptr) {
@@ -169,6 +182,16 @@
mStarted = true;
applyInterpolator();
+
+ if (mStartDelay <= 0 || !mUiThreadHandlesDelay) {
+ nSetStartDelay(mNativePtr.get(), mStartDelay);
+ doStart();
+ } else {
+ getHelper().addDelayedAnimation(this);
+ }
+ }
+
+ private void doStart() {
nStart(mNativePtr.get());
// Alpha is a special snowflake that has the canonical value stored
@@ -180,7 +203,7 @@
mViewTarget.mTransformationInfo.mAlpha = mFinalValue;
}
- final ArrayList<AnimatorListener> listeners = getListeners();
+ final ArrayList<AnimatorListener> listeners = cloneListeners();
final int numListeners = listeners == null ? 0 : listeners.size();
for (int i = 0; i < numListeners; i++) {
listeners.get(i).onAnimationStart(this);
@@ -195,9 +218,10 @@
@Override
public void cancel() {
if (!mFinished) {
+ getHelper().removeDelayedAnimation(this);
nEnd(mNativePtr.get());
- final ArrayList<AnimatorListener> listeners = getListeners();
+ final ArrayList<AnimatorListener> listeners = cloneListeners();
final int numListeners = listeners == null ? 0 : listeners.size();
for (int i = 0; i < numListeners; i++) {
listeners.get(i).onAnimationCancel(this);
@@ -258,7 +282,7 @@
throw new IllegalArgumentException("startDelay must be positive; " + startDelay);
}
mUnscaledStartDelay = startDelay;
- nSetStartDelay(mNativePtr.get(), (long) (startDelay * ValueAnimator.getDurationScale()));
+ mStartDelay = (long) (ValueAnimator.getDurationScale() * startDelay);
}
@Override
@@ -303,20 +327,105 @@
return mInterpolator;
}
- private void onFinished() {
+ protected void onFinished() {
mFinished = true;
- final ArrayList<AnimatorListener> listeners = getListeners();
+ final ArrayList<AnimatorListener> listeners = cloneListeners();
final int numListeners = listeners == null ? 0 : listeners.size();
for (int i = 0; i < numListeners; i++) {
listeners.get(i).onAnimationEnd(this);
}
}
+ @SuppressWarnings("unchecked")
+ private ArrayList<AnimatorListener> cloneListeners() {
+ ArrayList<AnimatorListener> listeners = getListeners();
+ if (listeners != null) {
+ listeners = (ArrayList<AnimatorListener>) listeners.clone();
+ }
+ return listeners;
+ }
+
long getNativeAnimator() {
return mNativePtr.get();
}
+ /**
+ * @return true if the animator was started, false if still delayed
+ */
+ private boolean processDelayed(long frameTimeMs) {
+ if (mStartTime == 0) {
+ mStartTime = frameTimeMs;
+ } else if ((frameTimeMs - mStartTime) >= mStartDelay) {
+ doStart();
+ return true;
+ }
+ return false;
+ }
+
+ private static DelayedAnimationHelper getHelper() {
+ DelayedAnimationHelper helper = sAnimationHelper.get();
+ if (helper == null) {
+ helper = new DelayedAnimationHelper();
+ sAnimationHelper.set(helper);
+ }
+ return helper;
+ }
+
+ private static ThreadLocal<DelayedAnimationHelper> sAnimationHelper =
+ new ThreadLocal<DelayedAnimationHelper>();
+
+ private static class DelayedAnimationHelper implements Runnable {
+
+ private ArrayList<RenderNodeAnimator> mDelayedAnims = new ArrayList<RenderNodeAnimator>();
+ private final Choreographer mChoreographer;
+ private boolean mCallbackScheduled;
+
+ public DelayedAnimationHelper() {
+ mChoreographer = Choreographer.getInstance();
+ }
+
+ public void addDelayedAnimation(RenderNodeAnimator animator) {
+ mDelayedAnims.add(animator);
+ scheduleCallback();
+ }
+
+ public void removeDelayedAnimation(RenderNodeAnimator animator) {
+ mDelayedAnims.remove(animator);
+ }
+
+ private void scheduleCallback() {
+ if (!mCallbackScheduled) {
+ mCallbackScheduled = true;
+ mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, this, null);
+ }
+ }
+
+ @Override
+ public void run() {
+ long frameTimeMs = mChoreographer.getFrameTime();
+ mCallbackScheduled = false;
+
+ int end = 0;
+ for (int i = 0; i < mDelayedAnims.size(); i++) {
+ RenderNodeAnimator animator = mDelayedAnims.get(i);
+ if (!animator.processDelayed(frameTimeMs)) {
+ if (end != i) {
+ mDelayedAnims.set(end, animator);
+ }
+ end++;
+ }
+ }
+ while (mDelayedAnims.size() > end) {
+ mDelayedAnims.remove(mDelayedAnims.size() - 1);
+ }
+
+ if (mDelayedAnims.size() > 0) {
+ scheduleCallback();
+ }
+ }
+ }
+
// Called by native
private static void callOnFinished(WeakReference<RenderNodeAnimator> weakThis) {
RenderNodeAnimator animator = weakThis.get();
@@ -325,6 +434,11 @@
}
}
+ @Override
+ public Animator clone() {
+ throw new IllegalStateException("Cannot clone this animator");
+ }
+
private static native long nCreateAnimator(WeakReference<RenderNodeAnimator> weakThis,
int property, float finalValue);
private static native long nCreateCanvasPropertyFloatAnimator(WeakReference<RenderNodeAnimator> weakThis,
diff --git a/core/java/android/view/RenderNodeAnimatorCompat.java b/core/java/android/view/RenderNodeAnimatorCompat.java
deleted file mode 100644
index 8103f47..0000000
--- a/core/java/android/view/RenderNodeAnimatorCompat.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.animation.ValueAnimator;
-
-import java.util.ArrayList;
-
-/**
- * This class provides compatibility for things like start listeners &
- * start delays for use by ViewPropertyAnimator and ObjectAnimator
- * @hide
- */
-public class RenderNodeAnimatorCompat extends RenderNodeAnimator {
-
- private long mUnscaledStartDelay = 0;
- private long mStartDelay = 0;
- private long mStartTime;
- private boolean mCanceled;
- private boolean mStarted;
-
- public RenderNodeAnimatorCompat(int property, float finalValue) {
- super(property, finalValue);
- }
-
- @Override
- public void setStartDelay(long startDelay) {
- mUnscaledStartDelay = startDelay;
- mStartDelay = (long) (ValueAnimator.getDurationScale() * startDelay);
- }
-
- @Override
- public long getStartDelay() {
- return mUnscaledStartDelay;
- }
-
- @Override
- public void start() {
- mStarted = true;
- if (mStartDelay <= 0) {
- doStart();
- } else {
- getHelper().addDelayedAnimation(this);
- }
- }
-
- @Override
- public boolean isStarted() {
- return mStarted;
- }
-
- private void doStart() {
- if (!mCanceled) {
- super.start();
- }
- }
-
- @Override
- public void cancel() {
- mCanceled = true;
- super.cancel();
- }
-
- /**
- * @return true if the animator was started, false if still delayed
- */
- private boolean processDelayed(long frameTimeMs) {
- if (mCanceled) return true;
-
- if (mStartTime == 0) {
- mStartTime = frameTimeMs;
- } else if ((frameTimeMs - mStartTime) >= mStartDelay) {
- doStart();
- return true;
- }
- return false;
- }
-
- private static AnimationHelper getHelper() {
- AnimationHelper helper = sAnimationHelper.get();
- if (helper == null) {
- helper = new AnimationHelper();
- sAnimationHelper.set(helper);
- }
- return helper;
- }
-
- private static ThreadLocal<AnimationHelper> sAnimationHelper =
- new ThreadLocal<AnimationHelper>();
-
- private static class AnimationHelper implements Runnable {
-
- private ArrayList<RenderNodeAnimatorCompat> mDelayedAnims = new ArrayList<RenderNodeAnimatorCompat>();
- private final Choreographer mChoreographer;
- private boolean mCallbackScheduled;
-
- public AnimationHelper() {
- mChoreographer = Choreographer.getInstance();
- }
-
- public void addDelayedAnimation(RenderNodeAnimatorCompat animator) {
- mDelayedAnims.add(animator);
- scheduleCallback();
- }
-
- private void scheduleCallback() {
- if (!mCallbackScheduled) {
- mCallbackScheduled = true;
- mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, this, null);
- }
- }
-
- @Override
- public void run() {
- long frameTimeMs = mChoreographer.getFrameTime();
- mCallbackScheduled = false;
-
- int end = 0;
- for (int i = 0; i < mDelayedAnims.size(); i++) {
- RenderNodeAnimatorCompat animator = mDelayedAnims.get(i);
- if (!animator.processDelayed(frameTimeMs)) {
- if (end != i) {
- mDelayedAnims.set(end, animator);
- }
- end++;
- }
- }
- while (mDelayedAnims.size() > end) {
- mDelayedAnims.remove(mDelayedAnims.size() - 1);
- }
-
- if (mDelayedAnims.size() > 0) {
- scheduleCallback();
- }
- }
- }
-}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index f9333d5..50341fc 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -332,6 +332,11 @@
}
@Override
+ void buildLayer(RenderNode node) {
+ nBuildLayer(mNativeProxy, node.getNativeDisplayList());
+ }
+
+ @Override
boolean copyLayerInto(final HardwareLayer layer, final Bitmap bitmap) {
return nCopyLayerInto(mNativeProxy,
layer.getDeferredLayerUpdater(), bitmap.mNativeBitmap);
@@ -468,6 +473,7 @@
private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height);
private static native long nCreateTextureLayer(long nativeProxy);
+ private static native void nBuildLayer(long nativeProxy, long node);
private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmap);
private static native void nPushLayerUpdate(long nativeProxy, long layer);
private static native void nCancelLayerUpdate(long nativeProxy, long layer);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 3adc41a..6f58582 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4047,6 +4047,10 @@
mBackgroundTintMode = Drawable.parseTintMode(a.getInt(
R.styleable.View_backgroundTintMode, -1), mBackgroundTintMode);
break;
+ case R.styleable.View_outlineProvider:
+ setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
+ PROVIDER_BACKGROUND));
+ break;
}
}
@@ -10789,6 +10793,15 @@
}
}
+ /** @hide */
+ public void setAnimationMatrix(Matrix matrix) {
+ invalidateViewProperty(true, false);
+ mRenderNode.setAnimationMatrix(matrix);
+ invalidateViewProperty(false, true);
+
+ invalidateParentIfNeededAndWasQuickRejected();
+ }
+
/**
* Returns the current StateListAnimator if exists.
*
@@ -10824,14 +10837,6 @@
}
/**
- * Deprecated, pending removal
- *
- * @hide
- */
- @Deprecated
- public void setOutline(@Nullable Outline outline) {}
-
- /**
* Returns whether the Outline should be used to clip the contents of the View.
* <p>
* Note that this flag will only be respected if the View's Outline returns true from
@@ -10860,6 +10865,28 @@
}
}
+ // correspond to the enum values of View_outlineProvider
+ private static final int PROVIDER_BACKGROUND = 0;
+ private static final int PROVIDER_NONE = 1;
+ private static final int PROVIDER_BOUNDS = 2;
+ private static final int PROVIDER_PADDED_BOUNDS = 3;
+ private void setOutlineProviderFromAttribute(int providerInt) {
+ switch (providerInt) {
+ case PROVIDER_BACKGROUND:
+ setOutlineProvider(ViewOutlineProvider.BACKGROUND);
+ break;
+ case PROVIDER_NONE:
+ setOutlineProvider(null);
+ break;
+ case PROVIDER_BOUNDS:
+ setOutlineProvider(ViewOutlineProvider.BOUNDS);
+ break;
+ case PROVIDER_PADDED_BOUNDS:
+ setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
+ break;
+ }
+ }
+
/**
* Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
* the shape of the shadow it casts, and enables outline clipping.
@@ -13072,6 +13099,10 @@
removeSendViewScrolledAccessibilityEventCallback();
stopNestedScroll();
+ // Anything that started animating right before detach should already
+ // be in its final state when re-attached.
+ jumpDrawablesToCurrentState();
+
destroyDrawingCache();
cleanupDraw();
@@ -13640,11 +13671,10 @@
switch (mLayerType) {
case LAYER_TYPE_HARDWARE:
- // The only part of a hardware layer we can build in response to
- // this call is to ensure the display list is up to date.
- // The actual rendering of the display list into the layer must
- // be done at playback time
updateDisplayListIfDirty();
+ if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
+ attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
+ }
break;
case LAYER_TYPE_SOFTWARE:
buildDrawingCache(true);
diff --git a/core/java/android/view/ViewAnimationUtils.java b/core/java/android/view/ViewAnimationUtils.java
index ea3efb1..7ced088 100644
--- a/core/java/android/view/ViewAnimationUtils.java
+++ b/core/java/android/view/ViewAnimationUtils.java
@@ -26,10 +26,13 @@
public final class ViewAnimationUtils {
private ViewAnimationUtils() {}
/**
- * Returns a ValueAnimator which can animate a clipping circle.
+ * Returns an Animator which can animate a clipping circle.
*
* Any shadow cast by the View will respect the circular clip from this animator.
*
+ * Note that the animation returned here is a one-shot animation. It cannot
+ * be re-used, and once started it cannot be paused or resumed.
+ *
* @param view The View will be clipped to the animating circle.
* @param centerX The x coordinate of the center of the animating circle.
* @param centerY The y coordinate of the center of the animating circle.
diff --git a/core/java/android/view/ViewOutlineProvider.java b/core/java/android/view/ViewOutlineProvider.java
index 170c5d8..a1a02f6 100644
--- a/core/java/android/view/ViewOutlineProvider.java
+++ b/core/java/android/view/ViewOutlineProvider.java
@@ -44,6 +44,35 @@
};
/**
+ * Maintains the outline of the View to match its rectangular bounds,
+ * at <code>1.0f</code> alpha.
+ *
+ * This can be used to enable Views that are opaque but lacking a background cast a shadow.
+ */
+ public static final ViewOutlineProvider BOUNDS = new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRect(0, 0, view.getWidth(), view.getHeight());
+ }
+ };
+
+ /**
+ * Maintains the outline of the View to match its rectangular padded bounds,
+ * at <code>1.0f</code> alpha.
+ *
+ * This can be used to enable Views that are opaque but lacking a background cast a shadow.
+ */
+ public static final ViewOutlineProvider PADDED_BOUNDS = new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRect(view.getPaddingLeft(),
+ view.getPaddingTop(),
+ view.getWidth() - view.getPaddingRight(),
+ view.getHeight() - view.getPaddingBottom());
+ }
+ };
+
+ /**
* Called to get the provider to populate the Outline.
*
* This method will be called by a View when its owned Drawables are invalidated, when the
diff --git a/core/java/android/view/ViewPropertyAnimatorRT.java b/core/java/android/view/ViewPropertyAnimatorRT.java
index 20f5182..de96887 100644
--- a/core/java/android/view/ViewPropertyAnimatorRT.java
+++ b/core/java/android/view/ViewPropertyAnimatorRT.java
@@ -81,7 +81,7 @@
int property = RenderNodeAnimator.mapViewPropertyToRenderProperty(holder.mNameConstant);
final float finalValue = holder.mFromValue + holder.mDeltaValue;
- RenderNodeAnimator animator = new RenderNodeAnimatorCompat(property, finalValue);
+ RenderNodeAnimator animator = new RenderNodeAnimator(property, finalValue);
animator.setStartDelay(startDelay);
animator.setDuration(duration);
animator.setInterpolator(interpolator);
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index e7b3152..2c7ea3e 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1662,6 +1662,27 @@
public void setTransitionBackgroundFadeDuration(long fadeDurationMillis) { }
/**
+ * Returns <code>true</code> when shared elements should use an Overlay during
+ * shared element transitions or <code>false</code> when they should animate as
+ * part of the normal View hierarchy. The default value is true.
+ *
+ * @return <code>true</code> when shared elements should use an Overlay during
+ * shared element transitions or <code>false</code> when they should animate as
+ * part of the normal View hierarchy.
+ */
+ public boolean getSharedElementsUseOverlay() { return true; }
+
+ /**
+ * Sets whether or not shared elements should use an Overlay during shared element transitions.
+ * The default value is true.
+ *
+ * @param sharedElementsUseOverlay <code>true</code> indicates that shared elements should
+ * be transitioned with an Overlay or <code>false</code>
+ * to transition within the normal View hierarchy.
+ */
+ public void setSharedElementsUseOverlay(boolean sharedElementsUseOverlay) { }
+
+ /**
* @return the color of the status bar.
*/
public abstract int getStatusBarColor();
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 8cae27b..4d2f57a 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -429,25 +429,10 @@
}
/**
- * The default implementation is responsible for handling
- * {@link CursorAnchorInfoRequest#TYPE_CURSOR_RECT}. In fact, for derived classes, calling
- * {@code super.requestCursorAnchorInfo(request)} is the only way to handle
- * {@link CursorAnchorInfoRequest#TYPE_CURSOR_RECT}.
+ * The default implementation does nothing.
*/
- public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) {
- // This implementation supports TYPE_CURSOR_RECT only.
- if (request == null ||
- request.getRequestType() != CursorAnchorInfoRequest.TYPE_CURSOR_RECT) {
- return CursorAnchorInfoRequest.RESULT_NOT_HANDLED;
- }
- if (mIMM == null) {
- // In this case, TYPE_CURSOR_RECT is not handled.
- // TODO: Return some notification code for the input method that indicates
- // Cursor rect information is temporarily unavailable.
- return CursorAnchorInfoRequest.RESULT_NOT_HANDLED;
- }
- mIMM.setCursorRectMonitorMode(request.getRequestFlags());
- return CursorAnchorInfoRequest.RESULT_SCHEDULED;
+ public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+ return false;
}
/**
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.java b/core/java/android/view/inputmethod/CursorAnchorInfoRequest.java
deleted file mode 100644
index e4c94f2..0000000
--- a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.view.inputmethod;
-
-import android.inputmethodservice.InputMethodService;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.view.View;
-
-/**
- * Used to enable or disable event notification for
- * {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)}. This class is also used to
- * enable {@link InputMethodService#onUpdateCursor(android.graphics.Rect)} for existing editors
- * that have not supported {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)}.
- */
-public final class CursorAnchorInfoRequest implements Parcelable {
- private final int mRequestType;
- private final int mRequestFlags;
-
- /**
- * Not handled by the editor.
- */
- public static final int RESULT_NOT_HANDLED = 0x00;
- /**
- * Request is scheduled in the editor task queue.
- */
- public static final int RESULT_SCHEDULED = 0x01;
-
- /**
- * The request is for {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)}.
- * This mechanism is powerful enough to retrieve fine-grained positional information of
- * characters in the editor.
- */
- public static final int TYPE_CURSOR_ANCHOR_INFO = 0x01;
- /**
- * The editor is requested to call
- * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)}
- * whenever cursor/anchor position is changed. To disable monitoring, call
- * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} again with
- * {@link #TYPE_CURSOR_ANCHOR_INFO} and this flag off.
- * <p>
- * This flag can be used together with {@link #FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE}.
- * </p>
- */
- public static final int FLAG_CURSOR_ANCHOR_INFO_MONITOR = 0x01;
- /**
- * The editor is requested to call
- * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} at
- * once, as soon as possible, regardless of cursor/anchor position changes. This flag can be
- * used together with {@link #FLAG_CURSOR_ANCHOR_INFO_MONITOR}.
- */
- public static final int FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE = 0x02;
-
- /**
- * The request is for {@link InputMethodService#onUpdateCursor(android.graphics.Rect)}. This
- * mechanism has been available since API Level 3 (CUPCAKE) but only the cursor rectangle can
- * be retrieved with this mechanism.
- */
- public static final int TYPE_CURSOR_RECT = 0x02;
- /**
- * The editor is requested to call
- * {@link InputMethodManager#updateCursor(android.view.View, int, int, int, int)}
- * whenever the cursor position is changed. To disable monitoring, call
- * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} again with
- * {@link #TYPE_CURSOR_RECT} and this flag off.
- * <p>
- * This flag can be used together with {@link #FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES}.
- * </p>
- */
- public static final int FLAG_CURSOR_RECT_MONITOR = 0x01;
- /**
- * {@link InputMethodManager#updateCursor(android.view.View, int, int, int, int)} should be
- * called back in screen coordinates. To receive cursor position in local coordinates, call
- * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} again with
- * {@link #TYPE_CURSOR_RECT} and this flag off.
- */
- public static final int FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES = 0x02;
- /**
- * {@link InputMethodManager#updateCursor(android.view.View, int, int, int, int)} should be
- * called back in screen coordinates after coordinate conversion with {@link View#getMatrix()}.
- * To disable coordinate conversion with {@link View#getMatrix()} again, call
- * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} with
- * {@link #TYPE_CURSOR_RECT} and this flag off.
- *
- * <p>
- * The flag is ignored if {@link #FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES} is off.
- * </p>
- */
- public static final int FLAG_CURSOR_RECT_WITH_VIEW_MATRIX = 0x04;
-
- /**
- * Constructs the object with request type and type-specific flags.
- *
- * @param requestType the type of this request. Currently {@link #TYPE_CURSOR_ANCHOR_INFO} or
- * {@link #TYPE_CURSOR_RECT} is supported.
- * @param requestFlags the flags for the given request type.
- */
- public CursorAnchorInfoRequest(int requestType, int requestFlags) {
- mRequestType = requestType;
- mRequestFlags = requestFlags;
- }
-
- /**
- * Used to make this class parcelable.
- *
- * @param source the parcel from which the object is unmarshalled.
- */
- public CursorAnchorInfoRequest(Parcel source) {
- mRequestType = source.readInt();
- mRequestFlags = source.readInt();
- }
-
- /**
- * @return the type of this request.
- */
- public int getRequestType() {
- return mRequestType;
- }
-
- /**
- * @return the flags that are specific to the type of this request.
- */
- public int getRequestFlags() {
- return mRequestFlags;
- }
-
- /**
- * Used to package this object into a {@link Parcel}.
- *
- * @param dest The {@link Parcel} to be written.
- * @param flags The flags used for parceling.
- */
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mRequestType);
- dest.writeInt(mRequestFlags);
- }
-
- @Override
- public int hashCode(){
- return mRequestType * 31 + mRequestFlags;
- }
-
- @Override
- public boolean equals(Object obj){
- if (obj == null) {
- return false;
- }
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof CursorAnchorInfoRequest)) {
- return false;
- }
- final CursorAnchorInfoRequest that = (CursorAnchorInfoRequest) obj;
- if (hashCode() != that.hashCode()) {
- return false;
- }
- return mRequestType != that.mRequestType && mRequestFlags == that.mRequestFlags;
- }
-
- @Override
- public String toString() {
- return "CursorAnchorInfoRequest{mRequestType=" + mRequestType
- + " mRequestFlags=" + mRequestFlags
- + "}";
- }
-
- /**
- * Used to make this class parcelable.
- */
- public static final Parcelable.Creator<CursorAnchorInfoRequest> CREATOR =
- new Parcelable.Creator<CursorAnchorInfoRequest>() {
- @Override
- public CursorAnchorInfoRequest createFromParcel(Parcel source) {
- return new CursorAnchorInfoRequest(source);
- }
-
- @Override
- public CursorAnchorInfoRequest[] newArray(int size) {
- return new CursorAnchorInfoRequest[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
-}
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index dff91dc..ca094c1 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -725,13 +725,34 @@
public boolean performPrivateCommand(String action, Bundle data);
/**
- * Called by the IME to ask the editor for calling back
+ * The editor is requested to call
+ * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} at
+ * once, as soon as possible, regardless of cursor/anchor position changes. This flag can be
+ * used together with {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR}.
+ */
+ public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE = 1 << 0;
+
+ /**
+ * The editor is requested to call
+ * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)}
+ * whenever cursor/anchor position is changed. To disable monitoring, call
+ * {@link InputConnection#requestUpdateCursorAnchorInfo(int)} again with this flag off.
+ * <p>
+ * This flag can be used together with {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE}.
+ * </p>
+ */
+ public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR = 1 << 1;
+
+ /**
+ * Called by the input method to ask the editor for calling back
* {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} to
* notify cursor/anchor locations.
*
- * @param request the details of the request.
- * @return a result code that depends on {@link CursorAnchorInfoRequest#getRequestType()}. See
- * {@link CursorAnchorInfoRequest} for details.
+ * @param cursorUpdateMode {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE} and/or
+ * {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR}
+ * @return {@code true} if the request is scheduled. {@code false} to indicate that when the
+ * application will not call
+ * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)}.
*/
- public int requestCursorAnchorInfo(CursorAnchorInfoRequest request);
+ public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode);
}
diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java
index c831d7c..d95df25 100644
--- a/core/java/android/view/inputmethod/InputConnectionWrapper.java
+++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java
@@ -126,7 +126,7 @@
return mTarget.performPrivateCommand(action, data);
}
- public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) {
- return mTarget.requestCursorAnchorInfo(request);
+ public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+ return mTarget.requestUpdateCursorAnchorInfo(cursorUpdateMode);
}
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index eec3570..0a472c7 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -313,9 +313,8 @@
CompletionInfo[] mCompletions;
// Cursor position on the screen.
- Rect mNextCursorRect = new Rect();
+ Rect mTmpCursorRect = new Rect();
Rect mCursorRect = new Rect();
- RectF mTempRectF = new RectF();
int mCursorSelStart;
int mCursorSelEnd;
int mCursorCandStart;
@@ -372,28 +371,12 @@
InputChannel mCurChannel;
ImeInputEventSender mCurSender;
- private static final int CURSOR_RECT_MONITOR_MODE_NONE = 0x0;
-
- private static final int CURSOR_RECT_MONITOR_FLAG_MASK =
- CursorAnchorInfoRequest.FLAG_CURSOR_RECT_MONITOR |
- CursorAnchorInfoRequest.FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES |
- CursorAnchorInfoRequest.FLAG_CURSOR_RECT_WITH_VIEW_MATRIX;
-
- private static final int CURSOR_ANCHOR_INFO_MONITOR_MODE_NONE = 0x0;
-
- private static final int CURSOR_ANCHOR_INFO_MONITOR_FLAG_MASK =
- CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_MONITOR |
- CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE;
-
- /**
- * The monitor mode for {@link #updateCursor(View, int, int, int, int)}.
- */
- private int mCursorRectMonitorMode = CURSOR_RECT_MONITOR_MODE_NONE;
+ private static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE = 0x0;
/**
* The monitor mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}.
*/
- private int mCursorAnchorInfoMonitorMode = CURSOR_ANCHOR_INFO_MONITOR_MODE_NONE;
+ private int mRequestUpdateCursorAnchorInfoMonitorMode = REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
final Pool<PendingEvent> mPendingEventPool = new SimplePool<PendingEvent>(20);
final SparseArray<PendingEvent> mPendingEvents = new SparseArray<PendingEvent>(20);
@@ -446,8 +429,8 @@
return;
}
- mCursorAnchorInfoMonitorMode = CURSOR_ANCHOR_INFO_MONITOR_MODE_NONE;
- mCursorRectMonitorMode = CURSOR_RECT_MONITOR_MODE_NONE;
+ mRequestUpdateCursorAnchorInfoMonitorMode =
+ REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
setInputChannelLocked(res.channel);
mCurMethod = res.method;
@@ -1540,59 +1523,49 @@
}
/**
- * Returns true if the current input method wants to watch the location
+ * Return true if the current input method wants to watch the location
* of the input editor's cursor in its window.
- */
- public boolean isWatchingCursor(View view) {
- if (!isActive(view)) {
- return false;
- }
- synchronized (mH) {
- return (mCursorRectMonitorMode & CursorAnchorInfoRequest.FLAG_CURSOR_RECT_MONITOR) != 0;
- }
- }
-
- /**
- * Updates the result of {@link #isWatchingCursor(View)}.
*
- * @hide
+ * @deprecated Use {@link InputConnection#requestUpdateCursorAnchorInfo(int)} instead.
*/
- public void setCursorRectMonitorMode(int flags) {
- synchronized (mH) {
- mCursorRectMonitorMode = (CURSOR_RECT_MONITOR_FLAG_MASK & flags);
- }
+ @Deprecated
+ public boolean isWatchingCursor(View view) {
+ return false;
}
/**
- * Returns true if the current input method wants to be notified when cursor/anchor location
+ * Return true if the current input method wants to be notified when cursor/anchor location
* is changed.
*
* @hide
*/
public boolean isCursorAnchorInfoEnabled() {
synchronized (mH) {
- final boolean isImmediate = (mCursorAnchorInfoMonitorMode &
- CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0;
- final boolean isMonitoring = (mCursorAnchorInfoMonitorMode &
- CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_MONITOR) != 0;
+ final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
+ InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0;
+ final boolean isMonitoring = (mRequestUpdateCursorAnchorInfoMonitorMode &
+ InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR) != 0;
return isImmediate || isMonitoring;
}
}
/**
- * Updates the result of {@link #isWatchingCursor(View)}.
+ * Set the requested mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}.
*
* @hide
*/
- public void setCursorAnchorInfoMonitorMode(int flags) {
+ public void setUpdateCursorAnchorInfoMode(int flags) {
synchronized (mH) {
- mCursorAnchorInfoMonitorMode = (CURSOR_ANCHOR_INFO_MONITOR_FLAG_MASK & flags);
+ mRequestUpdateCursorAnchorInfoMonitorMode = flags;
}
}
/**
* Report the current cursor location in its window.
+ *
+ * @deprecated Use {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)} instead.
*/
+ @Deprecated
public void updateCursor(View view, int left, int top, int right, int bottom) {
checkFocus();
synchronized (mH) {
@@ -1601,33 +1574,15 @@
|| mCurrentTextBoxAttribute == null || mCurMethod == null) {
return;
}
- if (DEBUG) Log.d(TAG, "updateCursor");
- final boolean usesScreenCoordinates = (mCursorRectMonitorMode &
- CursorAnchorInfoRequest.FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES) != 0;
- if (usesScreenCoordinates) {
- view.getLocationOnScreen(mViewTopLeft);
- final Matrix viewMatrix = view.getMatrix();
- final boolean usesViewMatrix = (viewMatrix != null) && ((mCursorRectMonitorMode &
- CursorAnchorInfoRequest.FLAG_CURSOR_RECT_WITH_VIEW_MATRIX) != 0);
- if (usesViewMatrix) {
- mTempRectF.set(left, top, right, bottom);
- mViewToScreenMatrix.set(viewMatrix);
- mViewToScreenMatrix.postTranslate(mViewTopLeft[0], mViewTopLeft[1]);
- mViewToScreenMatrix.mapRect(mTempRectF);
- mNextCursorRect.set((int)mTempRectF.left, (int)mTempRectF.top,
- (int)mTempRectF.right, (int)mTempRectF.bottom);
- } else {
- mNextCursorRect.set(left + mViewTopLeft[0], top + mViewTopLeft[1],
- right + mViewTopLeft[0], bottom + mViewTopLeft[1]);
- }
- } else {
- mNextCursorRect.set(left, top, right, bottom);
- }
- if (!Objects.equals(mCursorRect, mNextCursorRect)) {
- if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mNextCursorRect);
+
+ mTmpCursorRect.set(left, top, right, bottom);
+ if (!mCursorRect.equals(mTmpCursorRect)) {
+ if (DEBUG) Log.d(TAG, "updateCursor");
+
try {
- mCurMethod.updateCursor(mNextCursorRect);
- mCursorRect.set(mNextCursorRect);
+ if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod);
+ mCurMethod.updateCursor(mTmpCursorRect);
+ mCursorRect.set(mTmpCursorRect);
} catch (RemoteException e) {
Log.w(TAG, "IME died: " + mCurId, e);
}
@@ -1652,8 +1607,8 @@
}
// If immediate bit is set, we will call updateCursorAnchorInfo() even when the data has
// not been changed from the previous call.
- final boolean isImmediate = (mCursorAnchorInfoMonitorMode &
- CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0;
+ final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
+ InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0;
if (!isImmediate && Objects.equals(mCursorAnchorInfo, cursorAnchorInfo)) {
// TODO: Consider always emitting this message once we have addressed redundant
// calls of this method from android.widget.Editor.
@@ -1668,8 +1623,8 @@
mCurMethod.updateCursorAnchorInfo(cursorAnchorInfo);
mCursorAnchorInfo = cursorAnchorInfo;
// Clear immediate bit (if any).
- mCursorAnchorInfoMonitorMode &=
- ~CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE;
+ mRequestUpdateCursorAnchorInfoMonitorMode &=
+ ~InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE;
} catch (RemoteException e) {
Log.w(TAG, "IME died: " + mCurId, e);
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 60ef693..eb93745 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -65,7 +65,6 @@
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
-import android.view.inputmethod.CursorAnchorInfoRequest;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
@@ -5718,8 +5717,8 @@
}
@Override
- public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) {
- return getTarget().requestCursorAnchorInfo(request);
+ public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+ return getTarget().requestUpdateCursorAnchorInfo(cursorUpdateMode);
}
}
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index f4a478a..49d47fe 100644
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -386,7 +386,9 @@
mCurrentDate.set(Calendar.YEAR, year);
mCurrentDate.set(Calendar.MONTH, month);
mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
- mDateChangedListener.onDateChanged(mDelegator, year, month, dayOfMonth);
+ if (mDateChangedListener != null) {
+ mDateChangedListener.onDateChanged(mDelegator, year, month, dayOfMonth);
+ }
updateDisplay(false);
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 3f5f045..29c8298 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1298,25 +1298,6 @@
reported = reportExtractedText();
}
}
-
- if (imm.isWatchingCursor(mTextView) && highlight != null) {
- highlight.computeBounds(ims.mTmpRectF, true);
- ims.mTmpOffset[0] = ims.mTmpOffset[1] = 0;
-
- canvas.getMatrix().mapPoints(ims.mTmpOffset);
- ims.mTmpRectF.offset(ims.mTmpOffset[0], ims.mTmpOffset[1]);
-
- ims.mTmpRectF.offset(0, cursorOffsetVertical);
-
- ims.mCursorRectInWindow.set((int)(ims.mTmpRectF.left + 0.5),
- (int)(ims.mTmpRectF.top + 0.5),
- (int)(ims.mTmpRectF.right + 0.5),
- (int)(ims.mTmpRectF.bottom + 0.5));
-
- imm.updateCursor(mTextView,
- ims.mCursorRectInWindow.left, ims.mCursorRectInWindow.top,
- ims.mCursorRectInWindow.right, ims.mCursorRectInWindow.bottom);
- }
}
}
@@ -4136,7 +4117,6 @@
static class InputMethodState {
Rect mCursorRectInWindow = new Rect();
- RectF mTmpRectF = new RectF();
float[] mTmpOffset = new float[2];
ExtractedTextRequest mExtractedTextRequest;
final ExtractedText mExtractedText = new ExtractedText();
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index a0d9475..27763eb 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.content.res.ColorStateList;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
@@ -38,6 +39,7 @@
import com.android.internal.R;
import com.android.internal.widget.ExploreByTouchHelper;
+import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Formatter;
import java.util.List;
@@ -72,6 +74,9 @@
// used for scaling to the device density
private static float mScale = 0;
+ /** Single-letter (when available) formatter for the day of week label. */
+ private SimpleDateFormat mDayFormatter = new SimpleDateFormat("EEEEE", Locale.getDefault());
+
// affects the padding on the sides of this view
private int mPadding = 0;
@@ -181,6 +186,13 @@
initView();
}
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ mDayFormatter = new SimpleDateFormat("EEEEE", newConfig.locale);
+ }
+
void setTextColor(ColorStateList colors) {
final Resources res = getContext().getResources();
@@ -426,16 +438,16 @@
}
private void drawWeekDayLabels(Canvas canvas) {
- int y = mMonthHeaderSize - (mMonthDayLabelTextSize / 2);
- int dayWidthHalf = (mWidth - mPadding * 2) / (mNumDays * 2);
+ final int y = mMonthHeaderSize - (mMonthDayLabelTextSize / 2);
+ final int dayWidthHalf = (mWidth - mPadding * 2) / (mNumDays * 2);
for (int i = 0; i < mNumDays; i++) {
- int calendarDay = (i + mWeekStart) % mNumDays;
- int x = (2 * i + 1) * dayWidthHalf + mPadding;
+ final int calendarDay = (i + mWeekStart) % mNumDays;
mDayLabelCalendar.set(Calendar.DAY_OF_WEEK, calendarDay);
- canvas.drawText("" + mDayLabelCalendar.getDisplayName(Calendar.DAY_OF_WEEK,
- Calendar.SHORT, Locale.getDefault()).toUpperCase(Locale.getDefault()).charAt(0),
- x, y, mMonthDayLabelPaint);
+
+ final String dayLabel = mDayFormatter.format(mDayLabelCalendar.getTime());
+ final int x = (2 * i + 1) * dayWidthHalf + mPadding;
+ canvas.drawText(dayLabel, x, y, mMonthDayLabelPaint);
}
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a82fa65..096fe88 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -2867,8 +2867,15 @@
}
/**
- * Gives the text a shadow of the specified radius and color, the specified
- * distance from its normal position.
+ * Gives the text a shadow of the specified blur radius and color, the specified
+ * distance from its drawn position.
+ * <p>
+ * The text shadow produced does not interact with the properties on view
+ * that are responsible for real time shadows,
+ * {@link View#getElevation() elevation} and
+ * {@link View#getTranslationZ() translationZ}.
+ *
+ * @see Paint#setShadowLayer(float, float, float, int)
*
* @attr ref android.R.styleable#TextView_shadowColor
* @attr ref android.R.styleable#TextView_shadowDx
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 376e5b4..1b89179 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -73,16 +73,6 @@
private boolean mHourWithTwoDigit;
private char mHourFormat;
- /**
- * A no-op callback used in the constructor to avoid null checks later in
- * the code.
- */
- private static final TimePicker.OnTimeChangedListener NO_OP_CHANGE_LISTENER =
- new TimePicker.OnTimeChangedListener() {
- public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
- }
- };
-
public TimePickerClockDelegate(TimePicker delegator, Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(delegator, context);
@@ -216,8 +206,6 @@
updateMinuteControl();
updateAmPmControl();
- setOnTimeChangedListener(NO_OP_CHANGE_LISTENER);
-
// set to current time
setCurrentHour(mTempCalendar.get(Calendar.HOUR_OF_DAY));
setCurrentMinute(mTempCalendar.get(Calendar.MINUTE));
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index 8ee0a1b..cb0c3d0 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -230,16 +230,29 @@
mTargetState = STATE_IDLE;
}
+ /**
+ * Sets video path.
+ *
+ * @param path the path of the video.
+ */
public void setVideoPath(String path) {
setVideoURI(Uri.parse(path));
}
+ /**
+ * Sets video URI.
+ *
+ * @param uri the URI of the video.
+ */
public void setVideoURI(Uri uri) {
setVideoURI(uri, null);
}
/**
- * @hide
+ * Sets video URI using specific headers.
+ *
+ * @param uri the URI of the video.
+ * @param headers the headers for the URI request.
*/
public void setVideoURI(Uri uri, Map<String, String> headers) {
mUri = uri;
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 636c712..61b4567 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -22,6 +22,7 @@
import android.app.usage.UsageStatsManager;
import android.os.AsyncTask;
import android.provider.Settings;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Slog;
import android.widget.AbsListView;
@@ -278,12 +279,15 @@
});
}
- final TextView titleView = (TextView) findViewById(R.id.title);
- if (titleView != null) {
- if (title == null) {
- title = getTitleForAction(intent.getAction(), defaultTitleRes);
+ if (title == null) {
+ title = getTitleForAction(intent.getAction(), defaultTitleRes);
+ }
+ if (!TextUtils.isEmpty(title)) {
+ final TextView titleView = (TextView) findViewById(R.id.title);
+ if (titleView != null) {
+ titleView.setText(title);
}
- titleView.setText(title);
+ setTitle(title);
}
final ImageView iconView = (ImageView) findViewById(R.id.icon);
diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java
index b5ff0cc..b58e1db 100644
--- a/core/java/com/android/internal/app/WindowDecorActionBar.java
+++ b/core/java/com/android/internal/app/WindowDecorActionBar.java
@@ -925,6 +925,15 @@
public void onContentScrollStopped() {
}
+ @Override
+ public boolean collapseActionView() {
+ if (mDecorToolbar != null && mDecorToolbar.hasExpandedActionView()) {
+ mDecorToolbar.collapseActionView();
+ return true;
+ }
+ return false;
+ }
+
/**
* @hide
*/
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index d76d0d4..179d5e8 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -19,15 +19,25 @@
import static android.content.pm.PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS;
import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
import static android.content.pm.PackageManager.NO_NATIVE_LIBRARIES;
+import static android.system.OsConstants.S_IRGRP;
+import static android.system.OsConstants.S_IROTH;
+import static android.system.OsConstants.S_IRWXU;
+import static android.system.OsConstants.S_IXGRP;
+import static android.system.OsConstants.S_IXOTH;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.Package;
import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
+import android.os.Build;
+import android.os.SELinux;
+import android.system.ErrnoException;
+import android.system.Os;
import android.util.Slog;
import dalvik.system.CloseGuard;
+import dalvik.system.VMRuntime;
import java.io.Closeable;
import java.io.File;
@@ -44,6 +54,10 @@
private static final boolean DEBUG_NATIVE = false;
+ // Special value for {@code PackageParser.Package#cpuAbiOverride} to indicate
+ // that the cpuAbiOverride must be clear.
+ public static final String CLEAR_ABI_OVERRIDE = "-";
+
/**
* A handle to an opened package, consisting of one or more APKs. Used as
* input to the various NativeLibraryHelper methods. Allows us to scan and
@@ -126,27 +140,17 @@
private static native long nativeSumNativeBinaries(long handle, String cpuAbi);
- /**
- * Sums the size of native binaries in an APK for a given ABI.
- *
- * @return size of all native binary files in bytes
- */
- public static long sumNativeBinariesLI(Handle handle, String[] abis) {
+ private native static int nativeCopyNativeBinaries(long handle,
+ String sharedLibraryPath, String abiToCopy);
+
+ private static long sumNativeBinaries(Handle handle, String abi) {
long sum = 0;
for (long apkHandle : handle.apkHandles) {
- // NOTE: For a given APK handle, we parse the central directory precisely
- // once, but prefix matching of entries requires a CD traversal, which can
- // take a while (even if it needs no additional I/O).
- for (String abi : abis) {
- sum += nativeSumNativeBinaries(apkHandle, abi);
- }
+ sum += nativeSumNativeBinaries(apkHandle, abi);
}
return sum;
}
- private native static int nativeCopyNativeBinaries(long handle,
- String sharedLibraryPath, String abiToCopy);
-
/**
* Copies native binaries to a shared library directory.
*
@@ -244,9 +248,171 @@
}
}
+ private static void createNativeLibrarySubdir(File path) throws IOException {
+ if (!path.isDirectory()) {
+ path.delete();
+
+ if (!path.mkdir()) {
+ throw new IOException("Cannot create " + path.getPath());
+ }
+
+ try {
+ Os.chmod(path.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+ } catch (ErrnoException e) {
+ throw new IOException("Cannot chmod native library directory "
+ + path.getPath(), e);
+ }
+ } else if (!SELinux.restorecon(path)) {
+ throw new IOException("Cannot set SELinux context for " + path.getPath());
+ }
+ }
+
+ private static long sumNativeBinaries(Handle handle, String[] abiList) {
+ int abi = findSupportedAbi(handle, abiList);
+ if (abi >= 0) {
+ return sumNativeBinaries(handle, abiList[abi]);
+ } else {
+ return 0;
+ }
+ }
+
+ public static int copyNativeBinariesIfNeededLI(Handle handle, File libraryRoot,
+ String[] abiList, boolean useIsaSubdir) throws IOException {
+ createNativeLibrarySubdir(libraryRoot);
+
+ /*
+ * If this is an internal application or our nativeLibraryPath points to
+ * the app-lib directory, unpack the libraries if necessary.
+ */
+ int abi = findSupportedAbi(handle, abiList);
+ if (abi >= 0) {
+ /*
+ * If we have a matching instruction set, construct a subdir under the native
+ * library root that corresponds to this instruction set.
+ */
+ final String instructionSet = VMRuntime.getInstructionSet(abiList[abi]);
+ final File subDir;
+ if (useIsaSubdir) {
+ final File isaSubdir = new File(libraryRoot, instructionSet);
+ createNativeLibrarySubdir(isaSubdir);
+ subDir = isaSubdir;
+ } else {
+ subDir = libraryRoot;
+ }
+
+ int copyRet = copyNativeBinariesIfNeededLI(handle, subDir, abiList[abi]);
+ if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
+ return copyRet;
+ }
+ }
+
+ return abi;
+ }
+
+ public static int copyNativeBinariesIfNeededLI(Handle handle, File libraryRoot,
+ String abiOverride, boolean multiArch) {
+ try {
+ if (multiArch) {
+ // Warn if we've set an abiOverride for multi-lib packages..
+ // By definition, we need to copy both 32 and 64 bit libraries for
+ // such packages.
+ if (abiOverride != null && !CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
+ Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
+ }
+
+ int copyRet = PackageManager.NO_NATIVE_LIBRARIES;
+ if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
+ copyRet = copyNativeBinariesIfNeededLI(handle, libraryRoot,
+ Build.SUPPORTED_32_BIT_ABIS, true /* use isa specific subdirs */);
+ if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES &&
+ copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) {
+ Slog.w(TAG, "Failure copying 32 bit native libraries; copyRet=" +copyRet);
+ return copyRet;
+ }
+ }
+
+ if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
+ copyRet = copyNativeBinariesIfNeededLI(handle, libraryRoot,
+ Build.SUPPORTED_64_BIT_ABIS, true /* use isa specific subdirs */);
+ if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES &&
+ copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) {
+ Slog.w(TAG, "Failure copying 64 bit native libraries; copyRet=" +copyRet);
+ return copyRet;
+ }
+ }
+ } else {
+ String cpuAbiOverride = null;
+ if (CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
+ cpuAbiOverride = null;
+ } else if (abiOverride != null) {
+ cpuAbiOverride = abiOverride;
+ }
+
+ String[] abiList = (cpuAbiOverride != null) ?
+ new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
+ if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
+ hasRenderscriptBitcode(handle)) {
+ abiList = Build.SUPPORTED_32_BIT_ABIS;
+ }
+
+ int copyRet = copyNativeBinariesIfNeededLI(handle, libraryRoot, abiList,
+ true /* use isa specific subdirs */);
+ if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
+ Slog.w(TAG, "Failure copying native libraries [errorCode=" + copyRet + "]");
+ return copyRet;
+ }
+ }
+
+ return PackageManager.INSTALL_SUCCEEDED;
+ } catch (IOException e) {
+ Slog.e(TAG, "Copying native libraries failed", e);
+ return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+ }
+ }
+
+ public static long sumNativeBinaries(Handle handle, String abiOverride, boolean multiArch)
+ throws IOException {
+ long sum = 0;
+ if (multiArch) {
+ // Warn if we've set an abiOverride for multi-lib packages..
+ // By definition, we need to copy both 32 and 64 bit libraries for
+ // such packages.
+ if (abiOverride != null && !CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
+ Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
+ }
+
+ if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
+ sum += sumNativeBinaries(handle, Build.SUPPORTED_32_BIT_ABIS);
+ }
+
+ if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
+ sum += sumNativeBinaries(handle, Build.SUPPORTED_64_BIT_ABIS);
+ }
+ } else {
+ String cpuAbiOverride = null;
+ if (CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
+ cpuAbiOverride = null;
+ } else if (abiOverride != null) {
+ cpuAbiOverride = abiOverride;
+ }
+
+ String[] abiList = (cpuAbiOverride != null) ?
+ new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
+ if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
+ hasRenderscriptBitcode(handle)) {
+ abiList = Build.SUPPORTED_32_BIT_ABIS;
+ }
+
+ sum += sumNativeBinaries(handle, abiList);
+ }
+ return sum;
+ }
+
// We don't care about the other return values for now.
private static final int BITCODE_PRESENT = 1;
+ private static native int hasRenderscriptBitcode(long apkHandle);
+
public static boolean hasRenderscriptBitcode(Handle handle) throws IOException {
for (long apkHandle : handle.apkHandles) {
final int res = hasRenderscriptBitcode(apkHandle);
@@ -258,6 +424,4 @@
}
return false;
}
-
- private static native int hasRenderscriptBitcode(long apkHandle);
}
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index fd96f64..a529cc3 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -17,13 +17,17 @@
package com.android.internal.content;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Environment;
+import android.os.Environment.UserEnvironment;
import android.os.FileUtils;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.os.storage.IMountService;
import android.os.storage.StorageManager;
import android.os.storage.StorageResultCode;
@@ -215,7 +219,7 @@
/**
* Extract public files for the single given APK.
*/
- public static int extractPublicFiles(String apkPath, File publicZipFile)
+ public static long extractPublicFiles(File apkFile, File publicZipFile)
throws IOException {
final FileOutputStream fstr;
final ZipOutputStream publicZipOutStream;
@@ -226,12 +230,13 @@
} else {
fstr = new FileOutputStream(publicZipFile);
publicZipOutStream = new ZipOutputStream(fstr);
+ Log.d(TAG, "Extracting " + apkFile + " to " + publicZipFile);
}
- int size = 0;
+ long size = 0L;
try {
- final ZipFile privateZip = new ZipFile(apkPath);
+ final ZipFile privateZip = new ZipFile(apkFile.getAbsolutePath());
try {
// Copy manifest, resources.arsc and res directory to public zip
for (final ZipEntry zipEntry : Collections.list(privateZip.entries())) {
@@ -308,8 +313,15 @@
* Given a requested {@link PackageInfo#installLocation} and calculated
* install size, pick the actual location to install the app.
*/
- public static int resolveInstallLocation(Context context, int installLocation, long sizeBytes,
- int installFlags) {
+ public static int resolveInstallLocation(Context context, String packageName,
+ int installLocation, long sizeBytes, int installFlags) {
+ ApplicationInfo existingInfo = null;
+ try {
+ existingInfo = context.getPackageManager().getApplicationInfo(packageName,
+ PackageManager.GET_UNINSTALLED_PACKAGES);
+ } catch (NameNotFoundException ignored) {
+ }
+
final int prefer;
final boolean checkBoth;
if ((installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
@@ -325,7 +337,16 @@
prefer = RECOMMEND_INSTALL_EXTERNAL;
checkBoth = true;
} else if (installLocation == PackageInfo.INSTALL_LOCATION_AUTO) {
- prefer = RECOMMEND_INSTALL_INTERNAL;
+ // When app is already installed, prefer same medium
+ if (existingInfo != null) {
+ if ((existingInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
+ prefer = RECOMMEND_INSTALL_EXTERNAL;
+ } else {
+ prefer = RECOMMEND_INSTALL_INTERNAL;
+ }
+ } else {
+ prefer = RECOMMEND_INSTALL_INTERNAL;
+ }
checkBoth = true;
} else {
prefer = RECOMMEND_INSTALL_INTERNAL;
@@ -337,14 +358,15 @@
boolean fitsOnInternal = false;
if (checkBoth || prefer == RECOMMEND_INSTALL_INTERNAL) {
- fitsOnInternal = (sizeBytes
- <= storage.getStorageBytesUntilLow(Environment.getDataDirectory()));
+ final File target = Environment.getDataDirectory();
+ fitsOnInternal = (sizeBytes <= storage.getStorageBytesUntilLow(target));
}
boolean fitsOnExternal = false;
if (!emulated && (checkBoth || prefer == RECOMMEND_INSTALL_EXTERNAL)) {
- fitsOnExternal = (sizeBytes
- <= storage.getStorageBytesUntilLow(Environment.getExternalStorageDirectory()));
+ final File target = new UserEnvironment(UserHandle.USER_OWNER)
+ .getExternalStorageDirectory();
+ fitsOnExternal = (sizeBytes <= storage.getStorageBytesUntilLow(target));
}
if (prefer == RECOMMEND_INSTALL_INTERNAL) {
@@ -377,4 +399,12 @@
return PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
}
}
+
+ public static String replaceEnd(String str, String before, String after) {
+ if (!str.endsWith(before)) {
+ throw new IllegalArgumentException(
+ "Expected " + str + " to end with " + before);
+ }
+ return str.substring(0, str.length() - before.length()) + after;
+ }
}
diff --git a/core/java/com/android/internal/net/LegacyVpnInfo.java b/core/java/com/android/internal/net/LegacyVpnInfo.java
index d6f6d0b..f812ad6 100644
--- a/core/java/com/android/internal/net/LegacyVpnInfo.java
+++ b/core/java/com/android/internal/net/LegacyVpnInfo.java
@@ -40,7 +40,6 @@
public String key;
public int state = -1;
- public PendingIntent intent;
@Override
public int describeContents() {
@@ -51,7 +50,6 @@
public void writeToParcel(Parcel out, int flags) {
out.writeString(key);
out.writeInt(state);
- out.writeParcelable(intent, flags);
}
public static final Parcelable.Creator<LegacyVpnInfo> CREATOR =
@@ -61,7 +59,6 @@
LegacyVpnInfo info = new LegacyVpnInfo();
info.key = in.readString();
info.state = in.readInt();
- info.intent = in.readParcelable(null);
return info;
}
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index 0099269..aa66d7d 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -20,17 +20,19 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
import android.content.res.Resources;
+import android.net.LinkAddress;
+import android.net.RouteInfo;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.UserHandle;
-import android.net.RouteInfo;
-import android.net.LinkAddress;
import java.net.Inet4Address;
import java.net.InetAddress;
-import java.util.List;
import java.util.ArrayList;
+import java.util.List;
/**
* A simple container used to carry information in VpnBuilder, VpnDialogs,
@@ -55,12 +57,19 @@
return intent;
}
- public static PendingIntent getIntentForStatusPanel(Context context) {
- Intent intent = new Intent();
- intent.setClassName(DIALOGS_PACKAGE, DIALOGS_PACKAGE + ".ManageDialog");
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY |
- Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- return PendingIntent.getActivityAsUser(context, 0, intent, 0, null, UserHandle.CURRENT);
+ public static CharSequence getVpnLabel(Context context, String packageName)
+ throws NameNotFoundException {
+ PackageManager pm = context.getPackageManager();
+ Intent intent = new Intent(SERVICE_INTERFACE);
+ intent.setPackage(packageName);
+ List<ResolveInfo> services = pm.queryIntentServices(intent, 0 /* flags */);
+ if (services != null && services.size() == 1) {
+ // This app contains exactly one VPN service. Call loadLabel, which will attempt to
+ // load the service's label, and fall back to the app label if none is present.
+ return services.get(0).loadLabel(pm);
+ } else {
+ return pm.getApplicationInfo(packageName, 0).loadLabel(pm);
+ }
}
public String user;
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 897381d..b1f5d90 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -25,7 +25,6 @@
import android.view.KeyEvent;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
-import android.view.inputmethod.CursorAnchorInfoRequest;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
@@ -55,7 +54,7 @@
private static final int DO_REPORT_FULLSCREEN_MODE = 100;
private static final int DO_PERFORM_PRIVATE_COMMAND = 120;
private static final int DO_CLEAR_META_KEY_STATES = 130;
- private static final int DO_REQUEST_CURSOR_ANCHOR_INFO = 140;
+ private static final int DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO = 140;
private WeakReference<InputConnection> mInputConnection;
@@ -177,9 +176,10 @@
dispatchMessage(obtainMessageOO(DO_PERFORM_PRIVATE_COMMAND, action, data));
}
- public void requestCursorAnchorInfo(CursorAnchorInfoRequest request, int seq,
+ public void requestUpdateCursorAnchorInfo(int cursorUpdateMode, int seq,
IInputContextCallback callback) {
- dispatchMessage(obtainMessageOSC(DO_REQUEST_CURSOR_ANCHOR_INFO, request, seq, callback));
+ dispatchMessage(obtainMessageISC(DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO, cursorUpdateMode,
+ seq, callback));
}
void dispatchMessage(Message msg) {
@@ -427,18 +427,17 @@
(Bundle)args.arg2);
return;
}
- case DO_REQUEST_CURSOR_ANCHOR_INFO: {
+ case DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO: {
SomeArgs args = (SomeArgs)msg.obj;
try {
InputConnection ic = mInputConnection.get();
if (ic == null || !isActive()) {
Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection");
- args.callback.setRequestCursorAnchorInfoResult(0, args.seq);
+ args.callback.setRequestUpdateCursorAnchorInfoResult(false, args.seq);
return;
}
- args.callback.setRequestCursorAnchorInfoResult(
- ic.requestCursorAnchorInfo((CursorAnchorInfoRequest)args.arg1),
- args.seq);
+ args.callback.setRequestUpdateCursorAnchorInfoResult(
+ ic.requestUpdateCursorAnchorInfo(msg.arg1), args.seq);
} catch (RemoteException e) {
Log.w(TAG, "Got RemoteException calling requestCursorAnchorInfo", e);
}
diff --git a/core/java/com/android/internal/view/IInputContext.aidl b/core/java/com/android/internal/view/IInputContext.aidl
index c06596a..fd2b513 100644
--- a/core/java/com/android/internal/view/IInputContext.aidl
+++ b/core/java/com/android/internal/view/IInputContext.aidl
@@ -20,7 +20,6 @@
import android.view.KeyEvent;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
-import android.view.inputmethod.CursorAnchorInfoRequest;
import android.view.inputmethod.ExtractedTextRequest;
import com.android.internal.view.IInputContextCallback;
@@ -74,6 +73,6 @@
void getSelectedText(int flags, int seq, IInputContextCallback callback);
- void requestCursorAnchorInfo(in CursorAnchorInfoRequest request, int seq,
+ void requestUpdateCursorAnchorInfo(in int cursorUpdateMode, int seq,
IInputContextCallback callback);
}
diff --git a/core/java/com/android/internal/view/IInputContextCallback.aidl b/core/java/com/android/internal/view/IInputContextCallback.aidl
index ab2fbdc..54ea306 100644
--- a/core/java/com/android/internal/view/IInputContextCallback.aidl
+++ b/core/java/com/android/internal/view/IInputContextCallback.aidl
@@ -27,5 +27,5 @@
void setCursorCapsMode(int capsMode, int seq);
void setExtractedText(in ExtractedText extractedText, int seq);
void setSelectedText(CharSequence selectedText, int seq);
- void setRequestCursorAnchorInfoResult(int result, int seq);
+ void setRequestUpdateCursorAnchorInfoResult(boolean result, int seq);
}
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index 8535a98..a8526c8 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -23,7 +23,6 @@
import android.view.KeyEvent;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
-import android.view.inputmethod.CursorAnchorInfoRequest;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
@@ -41,7 +40,7 @@
public CharSequence mSelectedText;
public ExtractedText mExtractedText;
public int mCursorCapsMode;
- public int mCursorAnchorInfoRequestResult;
+ public boolean mRequestUpdateCursorAnchorInfoResult;
// A 'pool' of one InputContextCallback. Each ICW request will attempt to gain
// exclusive access to this object.
@@ -155,10 +154,10 @@
}
}
- public void setRequestCursorAnchorInfoResult(int result, int seq) {
+ public void setRequestUpdateCursorAnchorInfoResult(boolean result, int seq) {
synchronized (this) {
if (seq == mSeq) {
- mCursorAnchorInfoRequestResult = result;
+ mRequestUpdateCursorAnchorInfoResult = result;
mHaveValue = true;
notifyAll();
} else {
@@ -429,21 +428,21 @@
}
}
- public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) {
- int value = CursorAnchorInfoRequest.RESULT_NOT_HANDLED;
+ public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+ boolean result = false;
try {
InputContextCallback callback = InputContextCallback.getInstance();
- mIInputContext.requestCursorAnchorInfo(request, callback.mSeq, callback);
+ mIInputContext.requestUpdateCursorAnchorInfo(cursorUpdateMode, callback.mSeq, callback);
synchronized (callback) {
callback.waitForResultLocked();
if (callback.mHaveValue) {
- value = callback.mCursorAnchorInfoRequestResult;
+ result = callback.mRequestUpdateCursorAnchorInfoResult;
}
}
callback.dispose();
} catch (RemoteException e) {
- return CursorAnchorInfoRequest.RESULT_NOT_HANDLED;
+ return false;
}
- return value;
+ return result;
}
}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index 891baea..7eec392 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -265,13 +265,15 @@
final int width = getWidth();
final int height = getHeight();
final int midy = screenPos[1] + height / 2;
- final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
-
+ int referenceX = screenPos[0] + width / 2;
+ if (v.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) {
+ final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
+ referenceX = screenWidth - referenceX; // mirror
+ }
Toast cheatSheet = Toast.makeText(context, mItemData.getTitle(), Toast.LENGTH_SHORT);
if (midy < displayFrame.height()) {
// Show along the top; follow action buttons
- cheatSheet.setGravity(Gravity.TOP | Gravity.END,
- screenWidth - screenPos[0] - width / 2, height);
+ cheatSheet.setGravity(Gravity.TOP | Gravity.END, referenceX, height);
} else {
// Show along the bottom center
cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height);
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index 254f602..9b261ac 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -268,16 +268,24 @@
if (mActionBarView == null) return;
- final LayoutParams lp = (LayoutParams) mActionBarView.getLayoutParams();
- final int actionBarViewHeight = isCollapsed(mActionBarView) ? 0 :
- mActionBarView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
+ int nonTabMaxHeight = 0;
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+ if (child == mTabContainer) {
+ continue;
+ }
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ nonTabMaxHeight = isCollapsed(child) ? 0 :
+ child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
+ }
if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
final int mode = MeasureSpec.getMode(heightMeasureSpec);
if (mode == MeasureSpec.AT_MOST) {
final int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(),
- Math.min(actionBarViewHeight + mTabContainer.getMeasuredHeight(),
+ Math.min(nonTabMaxHeight + mTabContainer.getMeasuredHeight(),
maxHeight));
}
}
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
index 5709f659..cca48d3 100644
--- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -184,8 +184,6 @@
Build.VERSION_CODES.KITKAT;
mFlingEstimator = new OverScroller(context);
-
- setFocusableInTouchMode(true);
}
@Override
@@ -661,27 +659,6 @@
}
@Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- if (super.dispatchKeyEvent(event)) {
- return true;
- }
-
- if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
- final int action = event.getAction();
-
- // Collapse any expanded action views.
- if (mDecorToolbar != null && mDecorToolbar.hasExpandedActionView()) {
- if (action == KeyEvent.ACTION_UP) {
- mDecorToolbar.collapseActionView();
- }
- return true;
- }
- }
-
- return false;
- }
-
- @Override
public void setWindowCallback(Window.Callback cb) {
pullChildren();
mDecorToolbar.setWindowCallback(cb);
diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java
index bfe0090..2967938 100644
--- a/core/java/com/android/internal/widget/EditableInputConnection.java
+++ b/core/java/com/android/internal/widget/EditableInputConnection.java
@@ -25,9 +25,9 @@
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
-import android.view.inputmethod.CursorAnchorInfoRequest;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
+import android.view.inputmethod.InputConnection;
import android.widget.TextView;
public class EditableInputConnection extends BaseInputConnection {
@@ -188,24 +188,17 @@
}
@Override
- public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) {
- if (DEBUG) Log.v(TAG, "requestCursorAnchorInfo " + request);
+ public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+ if (DEBUG) Log.v(TAG, "requestUpdateCursorAnchorInfo " + cursorUpdateMode);
- // This implementation supports TYPE_CURSOR_ANCHOR_INFO only. Other events will be
- // delegated to the super class.
- if (request == null ||
- request.getRequestType() != CursorAnchorInfoRequest.TYPE_CURSOR_ANCHOR_INFO) {
- return super.requestCursorAnchorInfo(request);
- }
if (mIMM == null) {
// In this case, TYPE_CURSOR_ANCHOR_INFO is not handled.
- // TODO: Return some notification code for the input method that indicates
+ // TODO: Return some notification code rather than false to indicate method that
// CursorAnchorInfo is temporarily unavailable.
- return CursorAnchorInfoRequest.RESULT_NOT_HANDLED;
+ return false;
}
- final int flags = request.getRequestFlags();
- mIMM.setCursorAnchorInfoMonitorMode(flags);
- if ((flags & CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0) {
+ mIMM.setUpdateCursorAnchorInfoMode(cursorUpdateMode);
+ if ((cursorUpdateMode & InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0) {
if (mTextView == null) {
// In this case, FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE is silently ignored.
// TODO: Return some notification code for the input method that indicates
@@ -220,6 +213,6 @@
mTextView.requestLayout();
}
}
- return CursorAnchorInfoRequest.RESULT_SCHEDULED;
+ return true;
}
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index ece3e9d..6dec036 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -479,6 +479,7 @@
saveLockPattern(null);
setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
setLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
+ onAfterChangingPassword();
}
/**
@@ -565,6 +566,7 @@
dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0,
0, 0, 0, 0, 0, userId);
}
+ onAfterChangingPassword();
} catch (RemoteException re) {
Log.e(TAG, "Couldn't save lock pattern " + re);
}
@@ -844,6 +846,7 @@
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0,
userHandle);
}
+ onAfterChangingPassword();
} catch (RemoteException re) {
// Cant do much
Log.e(TAG, "Unable to save lock password " + re);
@@ -1093,6 +1096,25 @@
*/
public void setVisiblePatternEnabled(boolean enabled) {
setBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, enabled);
+
+ // Update for crypto if owner
+ int userId = getCurrentOrCallingUserId();
+ if (userId != UserHandle.USER_OWNER) {
+ return;
+ }
+
+ IBinder service = ServiceManager.getService("mount");
+ if (service == null) {
+ Log.e(TAG, "Could not find the mount service to update the user info");
+ return;
+ }
+
+ IMountService mountService = IMountService.Stub.asInterface(service);
+ try {
+ mountService.setField("PatternVisible", enabled ? "1" : "0");
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error changing pattern visible state", e);
+ }
}
/**
@@ -1542,4 +1564,8 @@
public void requireCredentialEntry(int userId) {
getTrustManager().reportRequireCredentialEntry(userId);
}
+
+ private void onAfterChangingPassword() {
+ getTrustManager().reportEnabledTrustAgentsChanged(getCurrentOrCallingUserId());
+ }
}
diff --git a/services/backup/java/com/android/server/backup/SystemBackupAgent.java b/core/java/com/android/server/backup/SystemBackupAgent.java
similarity index 100%
rename from services/backup/java/com/android/server/backup/SystemBackupAgent.java
rename to core/java/com/android/server/backup/SystemBackupAgent.java
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 2ce1b15..62ea351 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -18,6 +18,7 @@
#include <android_runtime/AndroidRuntime.h>
#include <androidfw/Asset.h>
#include <androidfw/ResourceTypes.h>
+#include <cutils/compiler.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/mman.h>
@@ -87,27 +88,39 @@
return options != NULL && env->GetBooleanField(options, gOptions_justBoundsFieldID);
}
-static void scaleNinePatchChunk(android::Res_png_9patch* chunk, float scale) {
+static void scaleDivRange(int32_t* divs, int count, float scale, int maxValue) {
+ for (int i = 0; i < count; i++) {
+ divs[i] = int32_t(divs[i] * scale + 0.5f);
+ if (i > 0 && divs[i] == divs[i - 1]) {
+ divs[i]++; // avoid collisions
+ }
+ }
+
+ if (CC_UNLIKELY(divs[count - 1] > maxValue)) {
+ // if the collision avoidance above put some divs outside the bounds of the bitmap,
+ // slide outer stretchable divs inward to stay within bounds
+ int highestAvailable = maxValue;
+ for (int i = count - 1; i >= 0; i--) {
+ divs[i] = highestAvailable;
+ if (i > 0 && divs[i] <= divs[i-1]){
+ // keep shifting
+ highestAvailable = divs[i] - 1;
+ } else {
+ break;
+ }
+ }
+ }
+}
+
+static void scaleNinePatchChunk(android::Res_png_9patch* chunk, float scale,
+ int scaledWidth, int scaledHeight) {
chunk->paddingLeft = int(chunk->paddingLeft * scale + 0.5f);
chunk->paddingTop = int(chunk->paddingTop * scale + 0.5f);
chunk->paddingRight = int(chunk->paddingRight * scale + 0.5f);
chunk->paddingBottom = int(chunk->paddingBottom * scale + 0.5f);
- int32_t* xDivs = chunk->getXDivs();
- for (int i = 0; i < chunk->numXDivs; i++) {
- xDivs[i] = int32_t(xDivs[i] * scale + 0.5f);
- if (i > 0 && xDivs[i] == xDivs[i - 1]) {
- xDivs[i]++;
- }
- }
-
- int32_t* yDivs = chunk->getYDivs();
- for (int i = 0; i < chunk->numYDivs; i++) {
- yDivs[i] = int32_t(yDivs[i] * scale + 0.5f);
- if (i > 0 && yDivs[i] == yDivs[i - 1]) {
- yDivs[i]++;
- }
- }
+ scaleDivRange(chunk->getXDivs(), chunk->numXDivs, scale, scaledWidth);
+ scaleDivRange(chunk->getYDivs(), chunk->numYDivs, scale, scaledHeight);
}
static SkColorType colorTypeForScaledOutput(SkColorType colorType) {
@@ -330,7 +343,7 @@
jbyteArray ninePatchChunk = NULL;
if (peeker.mPatch != NULL) {
if (willScale) {
- scaleNinePatchChunk(peeker.mPatch, scale);
+ scaleNinePatchChunk(peeker.mPatch, scale, scaledWidth, scaledHeight);
}
size_t ninePatchArraySize = peeker.mPatch->serializedSize();
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index fbb243a..e02aa5e 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -54,26 +54,19 @@
{
SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
SkSafeUnref(shader);
- SkShader* shaderWithLM = reinterpret_cast<SkShader*>(shaderWithLMHandle);
- SkSafeUnref(shaderWithLM);
}
-static jlong Shader_setLocalMatrix(JNIEnv* env, jobject o, jlong shaderHandle,
- jlong oldLocalMatrixShaderHandle, jlong matrixHandle)
+static void Shader_setLocalMatrix(JNIEnv* env, jobject o, jlong shaderHandle, jlong matrixHandle)
{
- // The old shader with local matrix is no longer needed, so unref it.
- SkSafeUnref(reinterpret_cast<SkShader*>(oldLocalMatrixShaderHandle));
-
SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
if (shader) {
- if (NULL == matrix) {
- matrix = &SkMatrix::I();
+ if (matrix) {
+ shader->setLocalMatrix(*matrix);
+ } else {
+ shader->resetLocalMatrix();
}
- SkShader* newShader = SkShader::CreateLocalMatrixShader(shader, *matrix);
- shader = newShader;
}
- return reinterpret_cast<jlong>(shader);
}
///////////////////////////////////////////////////////////////////////////////////////////////
@@ -243,8 +236,8 @@
};
static JNINativeMethod gShaderMethods[] = {
- { "nativeDestructor", "(JJ)V", (void*)Shader_destructor },
- { "nativeSetLocalMatrix", "(JJJ)J", (void*)Shader_setLocalMatrix }
+ { "nativeDestructor", "(J)V", (void*)Shader_destructor },
+ { "nativeSetLocalMatrix", "(JJ)V", (void*)Shader_setLocalMatrix }
};
static JNINativeMethod gBitmapShaderMethods[] = {
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 5bd38f3..8b9f574 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -236,10 +236,10 @@
return (jboolean) !setNetworkForResolv(netId);
}
-static jboolean android_net_utils_bindSocketToNetwork(JNIEnv *env, jobject thiz, jint socket,
+static jint android_net_utils_bindSocketToNetwork(JNIEnv *env, jobject thiz, jint socket,
jint netId)
{
- return (jboolean) !setNetworkForSocket(netId, socket);
+ return setNetworkForSocket(netId, socket);
}
static jboolean android_net_utils_protectFromVpn(JNIEnv *env, jobject thiz, jint socket)
@@ -263,7 +263,7 @@
{ "bindProcessToNetwork", "(I)Z", (void*) android_net_utils_bindProcessToNetwork },
{ "getNetworkBoundToProcess", "()I", (void*) android_net_utils_getNetworkBoundToProcess },
{ "bindProcessToNetworkForHostResolution", "(I)Z", (void*) android_net_utils_bindProcessToNetworkForHostResolution },
- { "bindSocketToNetwork", "(II)Z", (void*) android_net_utils_bindSocketToNetwork },
+ { "bindSocketToNetwork", "(II)I", (void*) android_net_utils_bindSocketToNetwork },
{ "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn },
};
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index d183d8e..4e3419a 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -264,6 +264,13 @@
return reinterpret_cast<jlong>(layer);
}
+static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
+ jlong proxyPtr, jlong nodePtr) {
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+ RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
+ proxy->buildLayer(node);
+}
+
static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
@@ -367,6 +374,7 @@
{ "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
{ "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
{ "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
+ { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer },
{ "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
{ "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
{ "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
diff --git a/core/res/res/anim/progress_indeterminate_horizontal_rect1.xml b/core/res/res/anim/progress_indeterminate_horizontal_rect1.xml
new file mode 100644
index 0000000..980c8e4
--- /dev/null
+++ b/core/res/res/anim/progress_indeterminate_horizontal_rect1.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <objectAnimator
+ android:duration="2000"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:repeatCount="infinite"
+ android:pathData="M -522.59998 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.1294 0 l 0.33832 0 l 0.5545 0 l 0.77088 0 l 0.98065 0 l 1.19641 0 l 1.41351 0 l 1.63153 0 l 1.85053 0 l 2.07052 0 l 2.29081 0 l 2.5115 0 l 2.73261 0 l 2.95355 0 l 3.17404 0 l 3.39423 0 l 3.61355 0 l 3.83164 0 l 4.04849 0 l 4.26367 0 l 5.74725 0 l 6.10266 0 l 6.45981 0 l 6.81781 0 l 7.17655 0 l 7.53366 0 l 7.88861 0 l 8.23975 0 l 8.58447 0 l 8.92157 0 l 9.24811 0 l 9.56137 0 l 9.85907 0 l 10.13778 0 l 10.39557 0 l 10.62876 0 l 10.83572 0 l 11.01492 0 l 11.16397 0 l 11.28324 0 l 11.3714 0 l 11.43011 0 l 11.45966 0 l 11.4611 0 l 11.43691 0 l 11.38878 0 l 11.31834 0 l 11.2276 0 l 11.11856 0 l 10.99338 0 l 10.85347 0 l 10.69954 0 l 10.53393 0 l 10.37447 0 l 10.37077 0 l 10.43095 0 l 10.52757 0 l 10.6715 0 l 10.8764 0 l 11.15665 0 l 11.52708 0 l 11.9948 0 l 12.55024 0 l 13.14534 0 l 13.68079 0 l 14.02233 0 l 14.06503 0 l 13.79804 0 l 13.295 0 l 12.65849 0 l 11.9693 0 l 11.2773 0 l 10.60766 0 l 9.97053 0 l 9.36723 0 l 8.79752 0 l 8.25793 0 l 7.74495 0 l 7.25633 0 l 6.78856 0 l 6.33934 0 l 5.9071 0 l 5.48941 0 l 5.08502 0 l 4.69292 0 l 4.33431 0 l 4.00734 0 l 3.68829 0 l 3.37685 0 l 3.07246 0 l 2.7744 0 l 2.48253 0 l 2.20102 0 l 1.91748 0 l 1.63726 0 l 1.36773 0 "
+ android:interpolator="@interpolator/progress_indeterminate_horizontal_rect1_grp_position" />
+ <objectAnimator
+ android:duration="2000"
+ android:propertyXName="scaleX"
+ android:propertyYName="scaleY"
+ android:repeatCount="infinite"
+ android:pathData="M 0.1 1 l 0.0 0 l 0.00882427215576 0 l 0.00982859611511 0 l 0.0108650398254 0 l 0.011930847168 0 l 0.0130220413208 0 l 0.0141334056854 0 l 0.0152582168579 0 l 0.0163880157471 0 l 0.0175127220154 0 l 0.0186203575134 0 l 0.0196973228455 0 l 0.0207285499573 0 l 0.0216978645325 0 l 0.0225887107849 0 l 0.0233847427368 0 l 0.0240707015991 0 l 0.0246334838867 0 l 0.0250626373291 0 l 0.0253514099121 0 l 0.0254969406128 0 l 0.0255004882813 0 l 0.0253670883179 0 l 0.0251052856445 0 l 0.0247262573242 0 l 0.0242431640625 0 l 0.0236701583862 0 l 0.0230218887329 0 l 0.0223124694824 0 l 0.021555557251 0 l 0.0207632446289 0 l 0.0199468231201 0 l 0.0191157531738 0 l 0.0182782745361 0 l 0.0173241424561 0 l 0.0152210998535 0 l 0.0126258087158 0 l 0.00973388671875 0 l 0.00647575378418 0 l 0.00276618957519 0 l -0.00149223327636 0 l -0.00639404296875 0 l -0.0119906616211 0 l -0.0182067108154 0 l -0.0247090148926 0 l -0.0308044433594 0 l -0.0355574798584 0 l -0.0382397460938 0 l -0.0387688446045 0 l -0.0376621246338 0 l -0.0356225204468 0 l -0.03321434021 0 l -0.0307815170288 0 l -0.0284958267212 0 l -0.0264254379272 0 l -0.024584236145 0 l -0.0229611587524 0 l -0.0215351867676 0 l -0.0202828598023 0 l -0.0191815567017 0 l -0.018210849762 0 l -0.0173528671265 0 l -0.0165923118591 0 l -0.0159160423279 0 l -0.0153129196167 0 l -0.0147735023499 0 l -0.0141336250305 0 l -0.0133926582336 0 l -0.01270362854 0 l -0.0120610809326 0 l -0.0114603328705 0 l -0.0108972930908 0 l -0.0103683567047 0 l -0.00987038612366 0 l -0.00940062522888 0 l -0.00895661354065 0 l -0.00853617668152 0 "
+ android:interpolator="@interpolator/progress_indeterminate_horizontal_rect1_grp_scale" />
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/progress_indeterminate_horizontal_rect1_scale.xml b/core/res/res/anim/progress_indeterminate_horizontal_rect1_scale.xml
deleted file mode 100644
index 7c782a6..0000000
--- a/core/res/res/anim/progress_indeterminate_horizontal_rect1_scale.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-
- <objectAnimator
- android:duration="2016"
- android:pathData="M 0.1 1 l 0 0 l 0.00882427215576 0 l 0.00982859611511 0
-l 0.01086503982544 0 l 0.01193084716797 0 l 0.0130220413208 0 l 0.01413340568542 0
-l 0.01525821685791 0 l 0.01638801574707 0 l 0.01751272201538 0 l 0.01862035751343 0
-l 0.01969732284546 0 l 0.02072854995728 0 l 0.02169786453247 0 l 0.02258871078491 0
-l 0.02338474273682 0 l 0.02407070159912 0 l 0.02463348388672 0 l 0.0250626373291 0
-l 0.02535140991211 0 l 0.02549694061279 0 l 0.02550048828125 0 l 0.02536708831787 0
-l 0.02510528564453 0 l 0.02472625732422 0 l 0.0242431640625 0 l 0.02367015838623 0
-l 0.02302188873291 0 l 0.02231246948242 0 l 0.02155555725098 0 l 0.02076324462891 0
-l 0.01994682312012 0 l 0.01911575317383 0 l 0.01827827453613 0 l 0.01732414245605 0
-l 0.01522109985352 0 l 0.01262580871582 0 l 0.00973388671875 0 l 0.00647575378418 0
-l 0.0027661895752 0 l -0.00149223327637 0 l -0.00639404296875 0 l -0.01199066162109 0
-l -0.01820671081543 0 l -0.02470901489258 0 l -0.03080444335937 0 l -0.0355574798584 0
-l -0.03823974609375 0 l -0.03876884460449 0 l -0.03766212463379 0 l -0.03562252044678 0
-l -0.03321434020996 0 l -0.03078151702881 0 l -0.02849582672119 0 l -0.02642543792725 0
-l -0.02458423614502 0 l -0.02296115875244 0 l -0.02153518676758 0 l -0.02028285980225 0
-l -0.01918155670166 0 l -0.01821084976196 0 l -0.01735286712646 0 l -0.01659231185913 0
-l -0.01591604232788 0 l -0.0153129196167 0 l -0.01477350234985 0 l -0.01413362503052 0
-l -0.01339265823364 0 l -0.01270362854004 0 l -0.01206108093262 0 l -0.01146033287048 0
-l -0.01089729309082 0 l -0.01036835670471 0 l -0.00987038612366 0 l -0.00940062522888 0
-l -0.00895661354065 0 l -0.00853617668152 0"
- android:propertyXName="scaleX"
- android:repeatCount="infinite" />
-
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/progress_indeterminate_horizontal_rect1_translate.xml b/core/res/res/anim/progress_indeterminate_horizontal_rect1_translate.xml
deleted file mode 100644
index c26bb5d..0000000
--- a/core/res/res/anim/progress_indeterminate_horizontal_rect1_translate.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-
- <objectAnimator
- android:duration="2016"
- android:pathData="M -522.599975585938 0 l 0 0 l 0.12939453125 0
-l 0.33831787109375 0 l 0.55450439453125 0 l 0.7708740234375 0 l 0.98065185546875 0
-l 1.1964111328125 0 l 1.41351318359375 0 l 1.63153076171875 0 l 1.85052490234375 0
-l 2.07052612304688 0 l 2.29080200195312 0 l 2.51150512695312 0 l 2.73260498046875 0
-l 2.95355224609375 0 l 3.17404174804688 0 l 3.39422607421875 0 l 3.61355590820312 0
-l 3.83163452148438 0 l 4.04849243164062 0 l 4.263671875 0 l 5.74725341796875 0
-l 6.1026611328125 0 l 6.45980834960938 0 l 6.81781005859375 0 l 7.17654418945312 0
-l 7.53366088867188 0 l 7.88861083984375 0 l 8.23974609375 0 l 8.58447265625 0
-l 8.92156982421875 0 l 9.24810791015625 0 l 9.56137084960938 0 l 9.85906982421875 0
-l 10.1377868652344 0 l 10.3955688476562 0 l 10.6287536621094 0 l 10.8357238769531 0
-l 11.0149230957031 0 l 11.1639709472656 0 l 11.2832336425781 0 l 11.3713989257812 0
-l 11.4301147460938 0 l 11.4596557617188 0 l 11.4611053466797 0 l 11.4369049072266 0
-l 11.3887786865234 0 l 11.3183441162109 0 l 11.2276000976562 0 l 11.1185607910156 0
-l 10.9933776855469 0 l 10.8534698486328 0 l 10.6995391845703 0 l 10.533935546875 0
-l 10.3744659423828 0 l 10.3707733154297 0 l 10.4309463500977 0 l 10.5275726318359 0
-l 10.671501159668 0 l 10.8763961791992 0 l 11.1566543579102 0 l 11.5270767211914 0
-l 11.9947967529297 0 l 12.5502433776855 0 l 13.1453399658203 0 l 13.680793762207 0
-l 14.0223298072815 0 l 14.0650296211243 0 l 13.798041343689 0 l 13.2949924468994 0
-l 12.6584892272949 0 l 11.9693031311035 0 l 11.2772979736328 0 l 10.607666015625 0
-l 9.97052764892578 0 l 9.36723327636719 0 l 8.79751586914062 0 l 8.25792694091797 0
-l 7.74495697021484 0 l 7.25632476806641 0 l 6.78855895996094 0 l 6.33934020996094 0
-l 5.9071044921875 0 l 5.48941040039062 0 l 5.08502197265625 0 l 4.69291687011719 0
-l 4.33430480957031 0 l 4.00733947753906 0 l 3.68829345703125 0 l 3.37684631347656 0
-l 3.07246398925781 0 l 2.77439880371094 0 l 2.48252868652344 0 l 2.20101928710938 0
-l 1.91748046875 0 l 1.63726806640625 0 l 1.36772155761719 0"
- android:propertyXName="translateX"
- android:repeatCount="infinite" />
-
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/progress_indeterminate_horizontal_rect2.xml b/core/res/res/anim/progress_indeterminate_horizontal_rect2.xml
new file mode 100644
index 0000000..8f0b2e8
--- /dev/null
+++ b/core/res/res/anim/progress_indeterminate_horizontal_rect2.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <objectAnimator
+ android:duration="2000"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:repeatCount="infinite"
+ android:pathData="M -197.60001 0 l 1.42626 0 l 1.80754 0 l 2.18779 0 l 2.5611 0 l 2.9181 0 l 3.25482 0 l 3.5716 0 l 3.86255 0 l 4.12494 0 l 4.35758 0 l 4.56035 0 l 4.73427 0 l 4.88091 0 l 5.00271 0 l 5.10274 0 l 5.18401 0 l 5.24911 0 l 5.30098 0 l 5.34226 0 l 5.37535 0 l 5.40181 0 l 5.42322 0 l 5.44123 0 l 5.45705 0 l 5.47099 0 l 5.48396 0 l 5.4967 0 l 5.5095 0 l 5.52215 0 l 5.53528 0 l 5.54913 0 l 5.56306 0 l 5.57743 0 l 5.59244 0 l 5.60744 0 l 5.62244 0 l 5.63767 0 l 5.65263 0 l 5.6669 0 l 5.6807 0 l 5.69401 0 l 5.70899 0 l 5.7517 0 l 5.80327 0 l 5.8571 0 l 5.914 0 l 5.9745 0 l 6.03849 0 l 6.10729 0 l 6.18126 0 l 6.26117 0 l 6.3484 0 l 6.44406 0 l 6.54867 0 l 6.66372 0 l 6.79021 0 l 6.92859 0 l 7.07807 0 l 7.23712 0 l 7.40254 0 l 7.56885 0 l 7.72841 0 l 7.87199 0 l 7.98993 0 l 8.07417 0 l 8.12013 0 l 8.12656 0 l 8.09511 0 l 8.03091 0 l 7.93996 0 l 7.82788 0 l 7.69977 0 l 7.56065 0 l 7.41323 0 l 7.26063 0 l 7.10471 0 l 6.94624 0 l 6.78694 0 l 6.63904 0 l 6.50302 0 l 6.36688 0 l 6.23044 0 l 6.09357 0 l 5.95706 0 l 5.82065 0 l 5.68396 0 l 5.54773 0 l 5.41144 0 l 5.27533 0 l 5.13922 0 l 5.00348 0 l 4.86804 0 l 4.73251 0 l 4.59732 0 l 4.46259 0 l 4.32812 0 l 4.19373 0 l 4.05993 0 l 3.92673 0 l 3.79376 0 l 3.6612 0 l 3.52936 0 l 3.39819 0 l 3.26749 0 l 3.13726 0 l 3.00797 0 l 2.87939 0 l 2.75159 0 l 2.62445 0 l 2.49811 0 l 2.37268 0 l 2.24817 0 l 2.12457 0 l 2.00174 0 l 1.87997 0 l 1.76185 0 l 1.64154 0 l 1.51962 0 l 1.40018 0 l 1.28421 0 "
+ android:interpolator="@interpolator/progress_indeterminate_horizontal_rect2_grp_position" />
+ <objectAnimator
+ android:duration="2000"
+ android:propertyXName="scaleX"
+ android:propertyYName="scaleY"
+ android:repeatCount="infinite"
+ android:pathData="M 0.1 1 l 0.00930031776428 0 l 0.0112302875519 0 l 0.0131314373016 0 l 0.014971075058 0 l 0.0167151069641 0 l 0.0183303451538 0 l 0.0197867202759 0 l 0.0210597610474 0 l 0.0221322822571 0 l 0.0229952049255 0 l 0.0236479568482 0 l 0.0240972709656 0 l 0.0243561935425 0 l 0.0244421386719 0 l 0.0243751525879 0 l 0.0241764450073 0 l 0.0238669586182 0 l 0.0234665298462 0 l 0.0229933547974 0 l 0.0224634552002 0 l 0.0218908691406 0 l 0.0212874603272 0 l 0.0206631851196 0 l 0.0200262451172 0 l 0.019383354187 0 l 0.0187397766113 0 l 0.018099899292 0 l 0.0174669647217 0 l 0.0168434906006 0 l 0.0162316131592 0 l 0.0156324005127 0 l 0.0150471496582 0 l 0.0144763183594 0 l 0.0139205169678 0 l 0.0133796691894 0 l 0.0128540802002 0 l 0.0123434448242 0 l 0.0118475341797 0 l 0.0113663482666 0 l 0.0108992004395 0 l 0.0104459381103 0 l 0.00998542785645 0 l 0.00933837890625 0 l 0.0086334991455 0 l 0.00791206359864 0 l 0.00717010498047 0 l 0.00640274047851 0 l 0.00560478210449 0 l 0.00477012634278 0 l 0.00389221191406 0 l 0.00296325683594 0 l 0.00197517395019 0 l 0.00091903686524 0 l -0.00021408081055 0 l -0.00143287658691 0 l -0.00274444580079 0 l -0.00415267944336 0 l -0.00565589904785 0 l -0.00724327087402 0 l -0.00889205932617 0 l -0.0105648040771 0 l -0.0122087860107 0 l -0.0137604522705 0 l -0.0151544952393 0 l -0.0163356018066 0 l -0.0172690582275 0 l -0.017946395874 0 l -0.0183829498291 0 l -0.0186113739014 0 l -0.018671798706 0 l -0.0186050415039 0 l -0.0184476470947 0 l -0.018229598999 0 l -0.017974319458 0 l -0.0176993560791 0 l -0.0174169921875 0 l -0.0171360397339 0 l -0.0168621444702 0 l -0.0165135955811 0 l -0.0160948562622 0 l -0.0156935882568 0 l -0.0153102493286 0 l -0.0149446105957 0 l -0.0145963287353 0 l -0.0142646408081 0 l -0.0139489364624 0 l -0.0136483383179 0 l -0.0133620071411 0 l -0.0130891799927 0 l -0.0128289794922 0 l -0.0125807571411 0 l -0.0123436355591 0 l -0.0121170043945 0 l -0.0119002914429 0 l -0.0116927337646 0 l -0.0114939498901 0 l -0.0113032531738 0 l -0.0111202430725 0 l -0.010944442749 0 l -0.0107754516601 0 l -0.0106128692627 0 l -0.0104563140869 0 l -0.0103054428101 0 l -0.0101600074768 0 l -0.0100196266174 0 l -0.0098840713501 0 l -0.00975311279297 0 l -0.00962644577026 0 l -0.00950393676758 0 l -0.00938529968262 0 l -0.00927038192749 0 l -0.00915899276733 0 l -0.00905097961426 0 l -0.00894614219665 0 l -0.0088443851471 0 l -0.00874552726745 0 l -0.00864946365357 0 l -0.00855606079101 0 l -0.00846519470215 0 l -0.00837676048279 0 "
+ android:interpolator="@interpolator/progress_indeterminate_horizontal_rect2_grp_scale" />
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/progress_indeterminate_horizontal_rect2_scale.xml b/core/res/res/anim/progress_indeterminate_horizontal_rect2_scale.xml
deleted file mode 100644
index ef1677d..0000000
--- a/core/res/res/anim/progress_indeterminate_horizontal_rect2_scale.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-
- <objectAnimator
- android:duration="2016"
- android:pathData="M 0.1 1 l 0.00930031776428 0 l 0.01123028755188 0
-l 0.01313143730164 0 l 0.01497107505798 0 l 0.01671510696411 0 l 0.01833034515381 0
-l 0.01978672027588 0 l 0.02105976104736 0 l 0.02213228225708 0 l 0.02299520492554 0
-l 0.02364795684814 0 l 0.02409727096558 0 l 0.02435619354248 0 l 0.02444213867188 0
-l 0.02437515258789 0 l 0.02417644500732 0 l 0.02386695861816 0 l 0.02346652984619 0
-l 0.02299335479736 0 l 0.0224634552002 0 l 0.02189086914062 0 l 0.02128746032715 0
-l 0.02066318511963 0 l 0.02002624511719 0 l 0.01938335418701 0 l 0.01873977661133 0
-l 0.01809989929199 0 l 0.01746696472168 0 l 0.01684349060059 0 l 0.01623161315918 0
-l 0.0156324005127 0 l 0.0150471496582 0 l 0.01447631835938 0 l 0.01392051696777 0
-l 0.01337966918945 0 l 0.0128540802002 0 l 0.01234344482422 0 l 0.01184753417969 0
-l 0.0113663482666 0 l 0.01089920043945 0 l 0.01044593811035 0 l 0.00998542785645 0
-l 0.00933837890625 0 l 0.00863349914551 0 l 0.00791206359863 0 l 0.00717010498047 0
-l 0.00640274047852 0 l 0.00560478210449 0 l 0.00477012634277 0 l 0.00389221191406 0
-l 0.00296325683594 0 l 0.0019751739502 0 l 0.00091903686523 0 l -0.00021408081055 0
-l -0.00143287658691 0 l -0.00274444580078 0 l -0.00415267944336 0 l -0.00565589904785 0
-l -0.00724327087402 0 l -0.00889205932617 0 l -0.01056480407715 0 l -0.01220878601074 0
-l -0.01376045227051 0 l -0.01515449523926 0 l -0.01633560180664 0 l -0.01726905822754 0
-l -0.01794639587402 0 l -0.0183829498291 0 l -0.01861137390137 0 l -0.01867179870605 0
-l -0.01860504150391 0 l -0.01844764709473 0 l -0.01822959899902 0 l -0.01797431945801 0
-l -0.0176993560791 0 l -0.0174169921875 0 l -0.01713603973389 0 l -0.01686214447021 0
-l -0.01651359558105 0 l -0.01609485626221 0 l -0.01569358825684 0 l -0.01531024932861 0
-l -0.0149446105957 0 l -0.01459632873535 0 l -0.01426464080811 0 l -0.0139489364624 0
-l -0.01364833831787 0 l -0.01336200714111 0 l -0.01308917999268 0 l -0.01282897949219 0
-l -0.01258075714111 0 l -0.01234363555908 0 l -0.01211700439453 0 l -0.01190029144287 0
-l -0.01169273376465 0 l -0.01149394989014 0 l -0.01130325317383 0 l -0.01112024307251 0
-l -0.01094444274902 0 l -0.01077545166016 0 l -0.0106128692627 0 l -0.01045631408691 0
-l -0.01030544281006 0 l -0.01016000747681 0 l -0.01001962661743 0 l -0.0098840713501 0
-l -0.00975311279297 0 l -0.00962644577026 0 l -0.00950393676758 0 l -0.00938529968262 0
-l -0.00927038192749 0 l -0.00915899276733 0 l -0.00905097961426 0 l -0.00894614219666 0
-l -0.00884438514709 0 l -0.00874552726746 0 l -0.00864946365356 0 l -0.00855606079102 0
-l -0.00846519470215 0 l -0.00837676048279 0 "
- android:propertyXName="scaleX"
- android:repeatCount="infinite" />
-
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/progress_indeterminate_horizontal_rect2_translate.xml b/core/res/res/anim/progress_indeterminate_horizontal_rect2_translate.xml
deleted file mode 100644
index f4cf83d..0000000
--- a/core/res/res/anim/progress_indeterminate_horizontal_rect2_translate.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-
- <objectAnimator
- android:duration="2016"
- android:pathData="M -197.600006103516 0 l 1.42625427246094 0
-l 1.80754089355469 0 l 2.18778991699219 0 l 2.56109619140625 0 l 2.91810607910156 0
-l 3.25482177734375 0 l 3.57159423828125 0 l 3.862548828125 0 l 4.12493896484375 0
-l 4.35758972167969 0 l 4.56034851074219 0 l 4.73426818847656 0 l 4.88090515136719 0
-l 5.00271606445312 0 l 5.10273742675781 0 l 5.18400573730469 0 l 5.24911499023438 0
-l 5.30097961425781 0 l 5.34226226806641 0 l 5.37535095214844 0 l 5.40180206298828 0
-l 5.42322540283203 0 l 5.44123077392578 0 l 5.45704650878906 0 l 5.47099304199219 0
-l 5.48395538330078 0 l 5.4967041015625 0 l 5.50949859619141 0 l 5.52214813232422 0
-l 5.53528594970703 0 l 5.54912567138672 0 l 5.56306457519531 0 l 5.57742691040039 0
-l 5.59244155883789 0 l 5.60744094848633 0 l 5.62243270874023 0 l 5.6376781463623 0
-l 5.65262794494629 0 l 5.66689777374268 0 l 5.68069934844971 0 l 5.69401162862778 0
-l 5.70898681879044 0 l 5.75169992446899 0 l 5.80327129364014 0 l 5.85710144042969 0
-l 5.91399765014648 0 l 5.97450065612793 0 l 6.03849411010742 0 l 6.10729217529297 0
-l 6.18125534057617 0 l 6.26116561889648 0 l 6.34840393066406 0 l 6.44406127929688 0
-l 6.54866790771484 0 l 6.66371917724609 0 l 6.79020690917969 0 l 6.92859649658203 0
-l 7.07807159423828 0 l 7.23712158203125 0 l 7.40253448486328 0 l 7.56884765625 0
-l 7.72840881347656 0 l 7.87199401855469 0 l 7.98992919921875 0 l 8.07417297363281 0
-l 8.12013244628906 0 l 8.12655639648438 0 l 8.09510803222656 0 l 8.03091430664062 0
-l 7.93995666503906 0 l 7.827880859375 0 l 7.69976806640625 0 l 7.56065368652344 0
-l 7.41322326660156 0 l 7.26063537597656 0 l 7.10470581054688 0 l 6.94624328613281 0
-l 6.78694152832031 0 l 6.6390380859375 0 l 6.50302124023438 0 l 6.36688232421875 0
-l 6.23043823242188 0 l 6.09356689453125 0 l 5.95706176757812 0 l 5.82064819335938 0
-l 5.6839599609375 0 l 5.5477294921875 0 l 5.41143798828125 0 l 5.27532958984375 0
-l 5.13922119140625 0 l 5.00347900390625 0 l 4.8680419921875 0 l 4.73251342773438 0
-l 4.59732055664062 0 l 4.46258544921875 0 l 4.328125 0 l 4.1937255859375 0
-l 4.0599365234375 0 l 3.92672729492188 0 l 3.79376220703125 0 l 3.66119384765625 0
-l 3.52935791015625 0 l 3.398193359375 0 l 3.26748657226562 0 l 3.13726806640625 0
-l 3.00796508789062 0 l 2.87939453125 0 l 2.7515869140625 0 l 2.62445068359375 0
-l 2.49810791015625 0 l 2.3726806640625 0 l 2.2481689453125 0 l 2.12457275390625 0
-l 2.00173950195312 0 l 1.87997436523438 0 l 1.7618408203125 0 l 1.64154052734375 0
-l 1.51962280273438 0 l 1.40017700195312 0 l 1.28421020507812 0 "
- android:propertyXName="translateX"
- android:repeatCount="infinite" />
-
-</set>
\ No newline at end of file
diff --git a/packages/PrintSpooler/res/drawable/ic_savetopdf.xml b/core/res/res/color/switch_thumb_material_dark.xml
similarity index 72%
rename from packages/PrintSpooler/res/drawable/ic_savetopdf.xml
rename to core/res/res/color/switch_thumb_material_dark.xml
index 60ed33a..8fede70 100644
--- a/packages/PrintSpooler/res/drawable/ic_savetopdf.xml
+++ b/core/res/res/color/switch_thumb_material_dark.xml
@@ -14,6 +14,7 @@
limitations under the License.
-->
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_savetopdf"
- android:tint="@color/promoted_action_background_color" />
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false" android:color="@color/switch_thumb_disabled_material_dark"/>
+ <item android:color="@color/switch_thumb_normal_material_dark"/>
+</selector>
diff --git a/packages/PrintSpooler/res/drawable/ic_savetopdf.xml b/core/res/res/color/switch_thumb_material_light.xml
similarity index 71%
copy from packages/PrintSpooler/res/drawable/ic_savetopdf.xml
copy to core/res/res/color/switch_thumb_material_light.xml
index 60ed33a..1a34b74 100644
--- a/packages/PrintSpooler/res/drawable/ic_savetopdf.xml
+++ b/core/res/res/color/switch_thumb_material_light.xml
@@ -14,6 +14,7 @@
limitations under the License.
-->
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_savetopdf"
- android:tint="@color/promoted_action_background_color" />
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false" android:color="@color/switch_thumb_disabled_material_light"/>
+ <item android:color="@color/switch_thumb_normal_material_light"/>
+</selector>
diff --git a/core/res/res/drawable-hdpi/spinner_textfield_activated_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/spinner_textfield_activated_mtrl_alpha.9.png
index 8af9ceb4..5e67395 100644
--- a/core/res/res/drawable-hdpi/spinner_textfield_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/spinner_textfield_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_textfield_default_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/spinner_textfield_default_mtrl_alpha.9.png
index 81c78c6..9c2ee13 100644
--- a/core/res/res/drawable-hdpi/spinner_textfield_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/spinner_textfield_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_activated_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/textfield_search_activated_mtrl_alpha.9.png
index 7bcebcd..ce577e5 100644
--- a/core/res/res/drawable-hdpi/textfield_search_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_default_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/textfield_search_default_mtrl_alpha.9.png
index eb1d945..7c305ab 100644
--- a/core/res/res/drawable-hdpi/textfield_search_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/title_bar_shadow.9.png b/core/res/res/drawable-hdpi/title_bar_shadow.9.png
deleted file mode 100644
index e6dab63..0000000
--- a/core/res/res/drawable-hdpi/title_bar_shadow.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_textfield_activated_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/spinner_textfield_activated_mtrl_alpha.9.png
index 22992c0..cb8f78a 100644
--- a/core/res/res/drawable-mdpi/spinner_textfield_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/spinner_textfield_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_textfield_default_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/spinner_textfield_default_mtrl_alpha.9.png
index f44a2c2..64d4c81 100644
--- a/core/res/res/drawable-mdpi/spinner_textfield_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/spinner_textfield_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_activated_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/textfield_search_activated_mtrl_alpha.9.png
index ef4ebc0..d7faacf 100644
--- a/core/res/res/drawable-mdpi/textfield_search_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_default_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/textfield_search_default_mtrl_alpha.9.png
index 9ddbcf5..0a36039 100644
--- a/core/res/res/drawable-mdpi/textfield_search_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/title_bar_shadow.9.png b/core/res/res/drawable-mdpi/title_bar_shadow.9.png
deleted file mode 100644
index dbcefee..0000000
--- a/core/res/res/drawable-mdpi/title_bar_shadow.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_textfield_activated_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/spinner_textfield_activated_mtrl_alpha.9.png
index 2d79d59..8e7862f 100644
--- a/core/res/res/drawable-xhdpi/spinner_textfield_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_textfield_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_textfield_default_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/spinner_textfield_default_mtrl_alpha.9.png
index 36f9753..95cb83f 100644
--- a/core/res/res/drawable-xhdpi/spinner_textfield_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_textfield_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_activated_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/textfield_search_activated_mtrl_alpha.9.png
index 1a2546f..33c1035 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_default_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/textfield_search_default_mtrl_alpha.9.png
index 500ec33..0226f84 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/title_bar_shadow.9.png b/core/res/res/drawable-xhdpi/title_bar_shadow.9.png
deleted file mode 100644
index 45b5456..0000000
--- a/core/res/res/drawable-xhdpi/title_bar_shadow.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_textfield_activated_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/spinner_textfield_activated_mtrl_alpha.9.png
index 9c0b19e..eb495c6 100644
--- a/core/res/res/drawable-xxhdpi/spinner_textfield_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_textfield_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_textfield_default_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/spinner_textfield_default_mtrl_alpha.9.png
index 0edb4b8..c2268af 100644
--- a/core/res/res/drawable-xxhdpi/spinner_textfield_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_textfield_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_activated_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/textfield_search_activated_mtrl_alpha.9.png
index cd5b00f..b6efff3 100644
--- a/core/res/res/drawable-xxhdpi/textfield_search_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_search_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_default_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/textfield_search_default_mtrl_alpha.9.png
index 5ee867c..2b253fb 100644
--- a/core/res/res/drawable-xxhdpi/textfield_search_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_search_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/spinner_textfield_activated_mtrl_alpha.9.png b/core/res/res/drawable-xxxhdpi/spinner_textfield_activated_mtrl_alpha.9.png
index 78c5ebd..fbcd7d4 100644
--- a/core/res/res/drawable-xxxhdpi/spinner_textfield_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxxhdpi/spinner_textfield_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/spinner_textfield_default_mtrl_alpha.9.png b/core/res/res/drawable-xxxhdpi/spinner_textfield_default_mtrl_alpha.9.png
index 36974b7..ebc9bf7 100644
--- a/core/res/res/drawable-xxxhdpi/spinner_textfield_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxxhdpi/spinner_textfield_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable/btn_borderless_material.xml b/core/res/res/drawable/btn_borderless_material.xml
index 47cc455..016f0ff 100644
--- a/core/res/res/drawable/btn_borderless_material.xml
+++ b/core/res/res/drawable/btn_borderless_material.xml
@@ -15,10 +15,7 @@
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android"
- android:insetLeft="@dimen/control_inset_material"
- android:insetTop="@dimen/control_inset_material"
- android:insetBottom="@dimen/control_inset_material"
- android:insetRight="@dimen/control_inset_material">
+ android:inset="@dimen/control_inset_material">
<ripple android:color="?attr/colorControlHighlight">
<item android:id="@id/mask"
android:drawable="@drawable/btn_default_mtrl_shape" />
diff --git a/core/res/res/drawable/btn_default_material.xml b/core/res/res/drawable/btn_default_material.xml
index b04d4fb..d00a348 100644
--- a/core/res/res/drawable/btn_default_material.xml
+++ b/core/res/res/drawable/btn_default_material.xml
@@ -15,10 +15,7 @@
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android"
- android:insetLeft="@dimen/control_inset_material"
- android:insetTop="@dimen/control_inset_material"
- android:insetBottom="@dimen/control_inset_material"
- android:insetRight="@dimen/control_inset_material">
+ android:inset="@dimen/control_inset_material">
<ripple android:color="?attr/colorControlHighlight">
<item android:drawable="@drawable/btn_default_mtrl_shape" />
</ripple>
diff --git a/core/res/res/drawable/btn_toggle_material.xml b/core/res/res/drawable/btn_toggle_material.xml
index a9951e7..9726782 100644
--- a/core/res/res/drawable/btn_toggle_material.xml
+++ b/core/res/res/drawable/btn_toggle_material.xml
@@ -15,10 +15,7 @@
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android"
- android:insetLeft="@dimen/control_inset_material"
- android:insetTop="@dimen/control_inset_material"
- android:insetBottom="@dimen/control_inset_material"
- android:insetRight="@dimen/control_inset_material">
+ android:inset="@dimen/control_inset_material">
<layer-list android:paddingMode="stack">
<item>
<ripple android:color="?attr/colorControlHighlight">
diff --git a/core/res/res/drawable/edit_text_material.xml b/core/res/res/drawable/edit_text_material.xml
index eaf5e45..bbc7301 100644
--- a/core/res/res/drawable/edit_text_material.xml
+++ b/core/res/res/drawable/edit_text_material.xml
@@ -15,10 +15,7 @@
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android"
- android:insetLeft="@dimen/control_inset_material"
- android:insetTop="@dimen/control_inset_material"
- android:insetBottom="@dimen/control_inset_material"
- android:insetRight="@dimen/control_inset_material">
+ android:inset="@dimen/control_inset_material">
<ripple android:color="?attr/colorControlActivated">
<item>
<selector>
diff --git a/core/res/res/drawable/notification_icon_legacy_bg_inset.xml b/core/res/res/drawable/notification_icon_legacy_bg_inset.xml
deleted file mode 100644
index 96c5573..0000000
--- a/core/res/res/drawable/notification_icon_legacy_bg_inset.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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
- -->
-
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
- android:drawable="@drawable/notification_icon_legacy_bg" android:insetBottom="8dp"
- android:insetLeft="8dp" android:insetRight="8dp" android:insetTop="8dp"
- android:visible="true"/>
diff --git a/core/res/res/drawable/progress_indeterminate_horizontal_material.xml b/core/res/res/drawable/progress_indeterminate_horizontal_material.xml
index 4fc68ce..e92f090 100644
--- a/core/res/res/drawable/progress_indeterminate_horizontal_material.xml
+++ b/core/res/res/drawable/progress_indeterminate_horizontal_material.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2014 The Android Open Source Project
@@ -14,20 +13,13 @@
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/vector_drawable_progress_indeterminate_horizontal" >
-
<target
- android:name="path1"
- android:animation="@anim/progress_indeterminate_horizontal_rect1_translate" />
+ android:name="rect2_grp"
+ android:animation="@anim/progress_indeterminate_horizontal_rect2" />
<target
- android:name="path1"
- android:animation="@anim/progress_indeterminate_horizontal_rect1_scale" />
-
- <target
- android:name="path2"
- android:animation="@anim/progress_indeterminate_horizontal_rect2_translate" />
- <target
- android:name="path2"
- android:animation="@anim/progress_indeterminate_horizontal_rect2_scale" />
-</animated-vector>
+ android:name="rect1_grp"
+ android:animation="@anim/progress_indeterminate_horizontal_rect1" />
+</animated-vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/spinner_textfield_background_material.xml b/core/res/res/drawable/spinner_textfield_background_material.xml
index f818baf..5bdff4a 100644
--- a/core/res/res/drawable/spinner_textfield_background_material.xml
+++ b/core/res/res/drawable/spinner_textfield_background_material.xml
@@ -14,18 +14,20 @@
limitations under the License.
-->
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- android:autoMirrored="true">
- <item android:state_checked="true">
- <nine-patch android:src="@drawable/spinner_textfield_activated_mtrl_alpha"
- android:tint="?attr/colorControlActivated" />
- </item>
- <item android:state_pressed="true">
- <nine-patch android:src="@drawable/spinner_textfield_activated_mtrl_alpha"
- android:tint="?attr/colorControlActivated" />
- </item>
- <item>
- <nine-patch android:src="@drawable/spinner_textfield_default_mtrl_alpha"
- android:tint="?attr/colorControlNormal" />
- </item>
-</selector>
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:inset="@dimen/control_inset_material">
+ <selector android:autoMirrored="true">
+ <item android:state_checked="true">
+ <nine-patch android:src="@drawable/spinner_textfield_activated_mtrl_alpha"
+ android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:state_pressed="true">
+ <nine-patch android:src="@drawable/spinner_textfield_activated_mtrl_alpha"
+ android:tint="?attr/colorControlActivated" />
+ </item>
+ <item>
+ <nine-patch android:src="@drawable/spinner_textfield_default_mtrl_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+ </selector>
+</inset>
diff --git a/core/res/res/drawable/switch_thumb_material_anim.xml b/core/res/res/drawable/switch_thumb_material_anim.xml
index 30bc8882..0d4d78e 100644
--- a/core/res/res/drawable/switch_thumb_material_anim.xml
+++ b/core/res/res/drawable/switch_thumb_material_anim.xml
@@ -16,22 +16,12 @@
<animated-selector xmlns:android="http://schemas.android.com/apk/res/android"
android:constantSize="true">
- <item
- android:state_enabled="false"
- android:state_checked="true">
- <nine-patch
- android:src="@drawable/btn_switch_to_on_mtrl_00012"
- android:gravity="center"
- android:tintMode="multiply"
- android:tint="?attr/colorControlActivated"
- android:alpha="?attr/disabledAlpha" />
- </item>
- <item android:state_enabled="false">
+ <item android:state_enabled="false" android:id="@+id/off">
<nine-patch
android:src="@drawable/btn_switch_to_on_mtrl_00001"
android:gravity="center"
android:tintMode="multiply"
- android:tint="?attr/colorButtonNormal" />
+ android:tint="?attr/colorSwitchThumbNormal" />
</item>
<item
android:state_checked="true"
@@ -47,29 +37,29 @@
android:src="@drawable/btn_switch_to_on_mtrl_00001"
android:gravity="center"
android:tintMode="multiply"
- android:tint="?attr/colorButtonNormal" />
+ android:tint="?attr/colorSwitchThumbNormal" />
</item>
<transition
android:fromId="@+id/off"
android:toId="@+id/on">
<animation-list>
<item android:duration="15">
- <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00001" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00001" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
</item>
<item android:duration="15">
- <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00002" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00002" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
</item>
<item android:duration="15">
- <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00003" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00003" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
</item>
<item android:duration="15">
- <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00004" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00004" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
</item>
<item android:duration="15">
- <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00005" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00005" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
</item>
<item android:duration="15">
- <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00006" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00006" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
</item>
<item android:duration="15">
<nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00007" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorControlActivated" />
@@ -112,22 +102,22 @@
<nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00006" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorControlActivated" />
</item>
<item android:duration="15">
- <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00007" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00007" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
</item>
<item android:duration="15">
- <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00008" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00008" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
</item>
<item android:duration="15">
- <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00009" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00009" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
</item>
<item android:duration="15">
- <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00010" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00010" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
</item>
<item android:duration="15">
- <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00011" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00011" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
</item>
<item android:duration="15">
- <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00012" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00012" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorSwitchThumbNormal" />
</item>
</animation-list>
</transition>
diff --git a/core/res/res/drawable/switch_track_material.xml b/core/res/res/drawable/switch_track_material.xml
index 0728055..1ec2f88 100644
--- a/core/res/res/drawable/switch_track_material.xml
+++ b/core/res/res/drawable/switch_track_material.xml
@@ -15,10 +15,10 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_enabled="false" android:state_checked="true">
+ <item android:state_enabled="false">
<nine-patch android:src="@drawable/switch_track_mtrl_alpha"
- android:tint="?attr/colorControlActivated"
- android:alpha="0.2" />
+ android:tint="?attr/colorForeground"
+ android:alpha="0.1" />
</item>
<item android:state_checked="true">
<nine-patch android:src="@drawable/switch_track_mtrl_alpha"
@@ -27,7 +27,7 @@
</item>
<item>
<nine-patch android:src="@drawable/switch_track_mtrl_alpha"
- android:tint="?attr/colorButtonNormal"
+ android:tint="?attr/colorForeground"
android:alpha="0.3" />
</item>
</selector>
diff --git a/packages/SystemUI/res/drawable/trust_circle.xml b/core/res/res/drawable/title_bar_shadow.xml
similarity index 76%
rename from packages/SystemUI/res/drawable/trust_circle.xml
rename to core/res/res/drawable/title_bar_shadow.xml
index 56fc62e..37b0b8f 100644
--- a/packages/SystemUI/res/drawable/trust_circle.xml
+++ b/core/res/res/drawable/title_bar_shadow.xml
@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
-
<!--
~ Copyright (C) 2014 The Android Open Source Project
~
@@ -15,8 +14,12 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="ring"
- android:innerRadius="22dp" android:thickness="2dp">
- <solid android:color="#4cffffff" />
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <gradient
+ android:startColor="#44000000"
+ android:centerColor="#1C000000"
+ android:endColor="#00000000"
+ android:centerY="0.3"
+ android:centerX="0.5"
+ android:angle="270"/>
</shape>
\ No newline at end of file
diff --git a/core/res/res/drawable/vector_drawable_progress_indeterminate_horizontal.xml b/core/res/res/drawable/vector_drawable_progress_indeterminate_horizontal.xml
index 0cc7202..7ceb772 100644
--- a/core/res/res/drawable/vector_drawable_progress_indeterminate_horizontal.xml
+++ b/core/res/res/drawable/vector_drawable_progress_indeterminate_horizontal.xml
@@ -13,48 +13,47 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<!--
- 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.
--->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="4dp"
- android:viewportHeight="4"
+ android:height="10dp"
+ android:viewportHeight="10"
android:viewportWidth="360"
android:width="360dp" >
<group
- android:name="linear_indeterminate"
- android:translateX="180.0"
- android:translateY="0.0" >
- <group
- android:name="path1"
- android:scaleX="0.1"
- android:translateX="-522.59" >
- <path
- android:name="rect1"
- android:fillColor="?attr/colorControlActivated"
- android:pathData="m 0 1.6 l 288 0 l 0 0.8 l -288 0 z" />
- </group>
- <group
- android:name="path2"
- android:scaleX="0.1"
- android:translateX="-197.6" >
- <path
- android:name="rect2"
- android:fillColor="?attr/colorControlActivated"
- android:pathData="m 0 1.6 l 288 0 l 0 0.8 l -288 0 z" />
+ android:name="v21"
+ android:translateX="180"
+ android:translateY="5" >
+ <group android:name="v21_pivot" >
+ <group
+ android:name="rectangle_path_1_position"
+ android:alpha="0.1" >
+ <path
+ android:name="rectangle_path_1"
+ android:fillColor="?attr/colorControlActivated"
+ android:pathData="M -180.0 -1.0 l 360 0 l 0 2 l -360 0 Z" />
+ </group>
+ <group
+ android:name="rect2_grp"
+ android:scaleX="0.1"
+ android:scaleY="1"
+ android:translateX="-197.60001" >
+ <path
+ android:name="rect2"
+ android:fillColor="?attr/colorControlActivated"
+ android:pathData="M -144.0 -1.0 l 288 0 l 0 2 l -288 0 Z" />
+ </group>
+ <group
+ android:name="rect1_grp"
+ android:scaleX="0.1"
+ android:scaleY="1"
+ android:translateX="-522.59998" >
+ <path
+ android:name="rect1"
+ android:fillColor="?attr/colorControlActivated"
+ android:pathData="M -144.0 -1.0 l 288 0 l 0 2 l -288 0 Z" />
+ </group>
</group>
</group>
+
</vector>
\ No newline at end of file
diff --git a/core/res/res/interpolator/progress_indeterminate_horizontal_rect1_grp_position.xml b/core/res/res/interpolator/progress_indeterminate_horizontal_rect1_grp_position.xml
new file mode 100644
index 0000000..1e5490b
--- /dev/null
+++ b/core/res/res/interpolator/progress_indeterminate_horizontal_rect1_grp_position.xml
@@ -0,0 +1,17 @@
+<!--
+ 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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0.0 0.0 L 0.00833333333334 0.0 L 0.0166666666667 0.0 L 0.025 0.0 L 0.0333333333333 0.0 L 0.0416666666667 0.0 L 0.05 0.0 L 0.0583333333333 0.0 L 0.0666666666667 0.0 L 0.075 0.0 L 0.0833333333333 0.0 L 0.0916666666667 0.0 L 0.1 0.0 L 0.108333333333 0.0 L 0.116666666667 0.0 L 0.125 0.0 L 0.133333333333 0.0 L 0.141666666667 0.0 L 0.15 0.0 L 0.158333333333 0.0 L 0.166666666667 0.0 L 0.175 0.0 L 0.183333333333 0.0 L 0.191666666667 0.0 L 0.2 0.0 L 0.208333333333 0.000179174746319 L 0.216666666667 0.000647632243805 L 0.225 0.0014154251096 L 0.233333333333 0.00248283027531 L 0.241666666667 0.00384069515149 L 0.25 0.00549731383962 L 0.258333333333 0.00745454178143 L 0.266666666667 0.00971365286228 L 0.275 0.012276004047 L 0.283333333333 0.0151429661471 L 0.291666666667 0.0183149545599 L 0.3 0.0217925231486 L 0.308333333333 0.0255762534696 L 0.316666666667 0.0296659101311 L 0.325 0.0340608700368 L 0.333333333333 0.0387607177895 L 0.341666666667 0.0437642487367 L 0.35 0.049069759749 L 0.358333333333 0.0546755338504 L 0.366666666667 0.0605792586621 L 0.375 0.0685372344023 L 0.383333333333 0.0769873314454 L 0.391666666667 0.0859319590963 L 0.4 0.0953722943142 L 0.408333333333 0.105309361746 L 0.416666666667 0.1157409044 L 0.425 0.126663931413 L 0.433333333333 0.13807316724 L 0.441666666667 0.149959722376 L 0.45 0.162313045726 L 0.458333333333 0.175118515302 L 0.466666666667 0.188357742846 L 0.475 0.20200918308 L 0.483333333333 0.216046541347 L 0.491666666667 0.230440850602 L 0.5 0.245158048258 L 0.508333333333 0.260161814735 L 0.516666666667 0.275413711928 L 0.525 0.290871992396 L 0.533333333333 0.306495421026 L 0.541666666667 0.322240921106 L 0.55 0.338067714457 L 0.558333333333 0.353935424452 L 0.566666666667 0.369805128355 L 0.575 0.385641337381 L 0.583333333333 0.401410902817 L 0.591666666667 0.417082932942 L 0.6 0.4326293192 L 0.608333333333 0.448024722349 L 0.616666666667 0.463246794008 L 0.625 0.478275138165 L 0.633333333333 0.493090341915 L 0.641666666667 0.507676232452 L 0.65 0.522041325423 L 0.658333333333 0.536401295159 L 0.666666666667 0.550844593615 L 0.675 0.565421677727 L 0.683333333333 0.580198055666 L 0.691666666667 0.595258150031 L 0.7 0.610706294803 L 0.708333333333 0.626667358442 L 0.716666666667 0.643276054324 L 0.725 0.66065384465 L 0.733333333333 0.678855644958 L 0.741666666667 0.697798860396 L 0.75 0.71721499193 L 0.758333333333 0.736690248362 L 0.766666666667 0.755795814951 L 0.775 0.774204843176 L 0.783333333333 0.791732522732 L 0.791666666667 0.808305909835 L 0.8 0.823921113596 L 0.808333333333 0.838609094968 L 0.816666666667 0.852414869183 L 0.825 0.865385279222 L 0.833333333333 0.877566835746 L 0.841666666667 0.889001244655 L 0.85 0.899725351699 L 0.858333333333 0.909772887147 L 0.866666666667 0.919172721118 L 0.875 0.927950539019 L 0.883333333333 0.936129852342 L 0.891666666667 0.943730807861 L 0.9 0.950771821528 L 0.908333333333 0.95726991079 L 0.916666666667 0.963271447844 L 0.925 0.968820243268 L 0.933333333333 0.973927263555 L 0.941666666667 0.978603045951 L 0.95 0.982857352297 L 0.958333333333 0.986698947476 L 0.966666666667 0.990136402522 L 0.975 0.993184062492 L 0.983333333333 0.995839116531 L 0.991666666667 0.998106161702 L 1.0 1.0 " />
diff --git a/core/res/res/interpolator/progress_indeterminate_horizontal_rect1_grp_scale.xml b/core/res/res/interpolator/progress_indeterminate_horizontal_rect1_grp_scale.xml
new file mode 100644
index 0000000..dc0e485
--- /dev/null
+++ b/core/res/res/interpolator/progress_indeterminate_horizontal_rect1_grp_scale.xml
@@ -0,0 +1,17 @@
+<!--
+ 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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0.0 0.0 L 0.366666666667 0.0 L 0.375 0.00607022199531 L 0.383333333333 0.0128313190317 L 0.391666666667 0.0203053863048 L 0.4 0.0285126230744 L 0.408333333333 0.0374704929422 L 0.416666666667 0.0471928710088 L 0.425 0.0576890073411 L 0.433333333333 0.0689623329923 L 0.441666666667 0.0810093447457 L 0.45 0.0938182996083 L 0.458333333333 0.107368099555 L 0.466666666667 0.121627281237 L 0.475 0.136553254984 L 0.483333333333 0.152092042392 L 0.491666666667 0.168178420646 L 0.5 0.184736670404 L 0.508333333333 0.201682058428 L 0.516666666667 0.218922661357 L 0.525 0.236361911116 L 0.533333333333 0.253901271529 L 0.541666666667 0.271443072385 L 0.55 0.288893107328 L 0.558333333333 0.306163048058 L 0.566666666667 0.323172254984 L 0.575 0.339849141772 L 0.583333333333 0.356131857619 L 0.591666666667 0.371968628391 L 0.6 0.387317389244 L 0.608333333333 0.402145469729 L 0.616666666667 0.416428517896 L 0.625 0.430149949228 L 0.633333333333 0.443299687056 L 0.641666666667 0.455873322838 L 0.65 0.467790610602 L 0.658333333333 0.478261214125 L 0.666666666667 0.486946515351 L 0.675 0.493642461739 L 0.683333333333 0.498097136568 L 0.691666666667 0.5 L 0.7 0.501026508147 L 0.708333333333 0.505424974058 L 0.716666666667 0.513673357225 L 0.725 0.526197764281 L 0.733333333333 0.543195110129 L 0.741666666667 0.564385504796 L 0.75 0.588845516061 L 0.758333333333 0.615150659843 L 0.766666666667 0.641819770802 L 0.775 0.667727568443 L 0.783333333333 0.692232321167 L 0.791666666667 0.715080485292 L 0.8 0.736255108924 L 0.808333333333 0.755857404851 L 0.816666666667 0.774035479111 L 0.825 0.790946989585 L 0.833333333333 0.806741984167 L 0.841666666667 0.821556051785 L 0.85 0.835508642948 L 0.858333333333 0.848703647061 L 0.866666666667 0.861230901301 L 0.875 0.873167948783 L 0.883333333333 0.884581809849 L 0.891666666667 0.895530464709 L 0.9 0.906064231101 L 0.908333333333 0.916226932039 L 0.916666666667 0.925949460993 L 0.925 0.935162278452 L 0.933333333333 0.943901111981 L 0.941666666667 0.952197936634 L 0.95 0.960081506342 L 0.958333333333 0.967577760656 L 0.966666666667 0.974710159318 L 0.975 0.981500003726 L 0.983333333333 0.987966699339 L 0.991666666667 0.994127959051 L 1.0 1.0 " />
diff --git a/core/res/res/interpolator/progress_indeterminate_horizontal_rect2_grp_position.xml b/core/res/res/interpolator/progress_indeterminate_horizontal_rect2_grp_position.xml
new file mode 100644
index 0000000..e2c463d
--- /dev/null
+++ b/core/res/res/interpolator/progress_indeterminate_horizontal_rect2_grp_position.xml
@@ -0,0 +1,17 @@
+<!--
+ 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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0.0 0.0 L 0.00833333333334 0.00229967744922 L 0.0166666666667 0.00521412430783 L 0.025 0.00874167982129 L 0.0333333333333 0.0128711540512 L 0.0416666666667 0.0175762490301 L 0.05 0.0228242656297 L 0.0583333333333 0.0285830529319 L 0.0666666666667 0.0348109630825 L 0.075 0.0414619464217 L 0.0833333333333 0.0484880345538 L 0.0916666666667 0.0558410655969 L 0.1 0.0634745223001 L 0.108333333333 0.0713444188538 L 0.116666666667 0.079410703663 L 0.125 0.0876382751487 L 0.133333333333 0.0959968850049 L 0.141666666667 0.104460460998 L 0.15 0.113007671299 L 0.158333333333 0.121621440773 L 0.166666666667 0.130288564002 L 0.175 0.138998350887 L 0.183333333333 0.147742658893 L 0.191666666667 0.156516005917 L 0.2 0.165314860841 L 0.208333333333 0.174136192385 L 0.216666666667 0.182978436537 L 0.225 0.191841222449 L 0.233333333333 0.200724646865 L 0.241666666667 0.209628467926 L 0.25 0.218553459576 L 0.258333333333 0.227500782731 L 0.266666666667 0.236470566383 L 0.275 0.245463519979 L 0.283333333333 0.254480675444 L 0.291666666667 0.263522016655 L 0.3 0.272587543612 L 0.308333333333 0.281677627163 L 0.316666666667 0.290791831964 L 0.325 0.299929045471 L 0.333333333333 0.309088509865 L 0.341666666667 0.318269435077 L 0.35 0.327474513787 L 0.358333333333 0.336748457377 L 0.366666666667 0.346105551561 L 0.375 0.355549440324 L 0.383333333333 0.365085073683 L 0.391666666667 0.374718256217 L 0.4 0.384454615142 L 0.408333333333 0.394301906021 L 0.416666666667 0.404268464874 L 0.425 0.414363869256 L 0.433333333333 0.424599921812 L 0.441666666667 0.434990214931 L 0.45 0.445549179441 L 0.458333333333 0.45629364862 L 0.466666666667 0.467242068132 L 0.475 0.478413609209 L 0.483333333333 0.489826169306 L 0.491666666667 0.501495178926 L 0.5 0.513430908951 L 0.508333333333 0.525634794401 L 0.516666666667 0.53809595169 L 0.525 0.550788614937 L 0.533333333333 0.563671442642 L 0.541666666667 0.576690097495 L 0.55 0.589782857472 L 0.558333333333 0.602885985073 L 0.566666666667 0.615938403227 L 0.575 0.628887306389 L 0.583333333333 0.641689563312 L 0.591666666667 0.654311104343 L 0.6 0.666726082982 L 0.608333333333 0.678916746891 L 0.616666666667 0.69086971329 L 0.625 0.702576630036 L 0.633333333333 0.714032144017 L 0.641666666667 0.725232143656 L 0.65 0.736175290675 L 0.658333333333 0.746879966241 L 0.666666666667 0.757365325464 L 0.675 0.767631174859 L 0.683333333333 0.77767703071 L 0.691666666667 0.787502199694 L 0.7 0.797107262267 L 0.708333333333 0.806492379668 L 0.716666666667 0.81565710043 L 0.725 0.82460216625 L 0.733333333333 0.833327480383 L 0.741666666667 0.841833333059 L 0.75 0.850119724279 L 0.758333333333 0.858187250623 L 0.766666666667 0.866036395807 L 0.775 0.873667014716 L 0.783333333333 0.88107965556 L 0.791666666667 0.888275060036 L 0.8 0.895253647364 L 0.808333333333 0.902015546533 L 0.816666666667 0.90856170885 L 0.825 0.914893101745 L 0.833333333333 0.921010096065 L 0.841666666667 0.926913352889 L 0.85 0.932604033131 L 0.858333333333 0.938083217089 L 0.866666666667 0.943351662581 L 0.875 0.94841012743 L 0.883333333333 0.953260127273 L 0.891666666667 0.957902806904 L 0.9 0.962339423981 L 0.908333333333 0.966571042677 L 0.916666666667 0.970598952899 L 0.925 0.974424621915 L 0.933333333333 0.978049533117 L 0.941666666667 0.981475153774 L 0.95 0.984702725421 L 0.958333333333 0.987733957184 L 0.966666666667 0.990574734261 L 0.975 0.993221525533 L 0.983333333333 0.995671735064 L 0.991666666667 0.997929361563 L 1.0 1.0 " />
diff --git a/core/res/res/interpolator/progress_indeterminate_horizontal_rect2_grp_scale.xml b/core/res/res/interpolator/progress_indeterminate_horizontal_rect2_grp_scale.xml
new file mode 100644
index 0000000..e19e3bd
--- /dev/null
+++ b/core/res/res/interpolator/progress_indeterminate_horizontal_rect2_grp_scale.xml
@@ -0,0 +1,17 @@
+<!--
+ 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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0.0 0.0 L 0.00833333333334 0.00574128947512 L 0.0166666666667 0.0126739914922 L 0.025 0.0207803148119 L 0.0333333333333 0.0300222867359 L 0.0416666666667 0.0403408876828 L 0.05 0.0516566104757 L 0.0583333333333 0.0638713854701 L 0.0666666666667 0.0768720363634 L 0.075 0.0905347780463 L 0.0833333333333 0.104730220757 L 0.0916666666667 0.1193286215 L 0.1 0.134204393671 L 0.108333333333 0.149240004408 L 0.116666666667 0.164328670953 L 0.125 0.179375985524 L 0.133333333333 0.194300633561 L 0.141666666667 0.209034228885 L 0.15 0.223520630773 L 0.158333333333 0.237714931359 L 0.166666666667 0.25158211334 L 0.175 0.265095825429 L 0.183333333333 0.278237040065 L 0.191666666667 0.290992875969 L 0.2 0.303355514884 L 0.208333333333 0.315321283173 L 0.216666666667 0.326889756956 L 0.225 0.33806322048 L 0.233333333333 0.348845959658 L 0.241666666667 0.35924381463 L 0.25 0.369263944281 L 0.258333333333 0.378914166866 L 0.266666666667 0.388203101304 L 0.275 0.397139649102 L 0.283333333333 0.40573308855 L 0.291666666667 0.413992650841 L 0.3 0.421927755558 L 0.308333333333 0.429547633895 L 0.316666666667 0.436861375749 L 0.325 0.44387807102 L 0.333333333333 0.450606385724 L 0.341666666667 0.457054891684 L 0.35 0.463219114597 L 0.358333333333 0.468983900047 L 0.366666666667 0.474313547811 L 0.375 0.47919783764 L 0.383333333333 0.483624100194 L 0.391666666667 0.487576651865 L 0.4 0.491036606388 L 0.408333333333 0.493981309661 L 0.416666666667 0.496384057166 L 0.425 0.498213340392 L 0.433333333333 0.499432658452 L 0.441666666667 0.5 L 0.45 0.500132156764 L 0.458333333333 0.501016702806 L 0.466666666667 0.502710909197 L 0.475 0.505274449001 L 0.483333333333 0.50876595913 L 0.491666666667 0.51323738859 L 0.5 0.518726651206 L 0.508333333333 0.525248535726 L 0.516666666667 0.532785286233 L 0.525 0.541279914244 L 0.533333333333 0.550635115456 L 0.541666666667 0.560719439572 L 0.55 0.571380006744 L 0.558333333333 0.582458709253 L 0.566666666667 0.593806906062 L 0.575 0.605296114045 L 0.583333333333 0.61682262358 L 0.591666666667 0.628307922435 L 0.6 0.639696058281 L 0.608333333333 0.65094958827 L 0.616666666667 0.662045528618 L 0.625 0.67297172806 L 0.633333333333 0.6837236181 L 0.641666666667 0.694302070048 L 0.65 0.704711440462 L 0.658333333333 0.714905644026 L 0.666666666667 0.724841350655 L 0.675 0.734529345772 L 0.683333333333 0.743980697388 L 0.691666666667 0.753206332221 L 0.7 0.762216965048 L 0.708333333333 0.771022839665 L 0.716666666667 0.779633823089 L 0.725 0.788059240706 L 0.733333333333 0.796307899828 L 0.741666666667 0.804388136787 L 0.75 0.812307746289 L 0.758333333333 0.820074122707 L 0.766666666667 0.827694118788 L 0.775 0.835174210498 L 0.783333333333 0.842520520564 L 0.791666666667 0.849738700738 L 0.8 0.856834167281 L 0.808333333333 0.863811912571 L 0.816666666667 0.870676681725 L 0.825 0.877432925497 L 0.833333333333 0.884084847374 L 0.841666666667 0.890636403584 L 0.85 0.897091314861 L 0.858333333333 0.90345309 L 0.866666666667 0.909725084729 L 0.875 0.915910419285 L 0.883333333333 0.92201207261 L 0.891666666667 0.928032882355 L 0.9 0.933975497778 L 0.908333333333 0.939842485715 L 0.916666666667 0.945636236386 L 0.925 0.951359045815 L 0.933333333333 0.95701309228 L 0.941666666667 0.962600459864 L 0.95 0.968123109018 L 0.958333333333 0.973582941322 L 0.966666666667 0.978981746494 L 0.975 0.984321249498 L 0.983333333333 0.989603092873 L 0.991666666667 0.994828842625 L 1.0 1.0 " />
diff --git a/core/res/res/layout-sw600dp/date_picker_holo.xml b/core/res/res/layout-sw600dp/date_picker_holo.xml
deleted file mode 100644
index e5c886b..0000000
--- a/core/res/res/layout-sw600dp/date_picker_holo.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2011 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:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:gravity="center"
- android:orientation="vertical" >
-
- <include
- layout="@layout/date_picker_selected_date"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/datepicker_selected_calendar_layout_height" />
-
- <include layout="@layout/date_picker_view_animator" />
-
-</LinearLayout>
diff --git a/core/res/res/layout/notification_material_action.xml b/core/res/res/layout/notification_material_action.xml
index 8f8c4fb..637d941 100644
--- a/core/res/res/layout/notification_material_action.xml
+++ b/core/res/res/layout/notification_material_action.xml
@@ -25,8 +25,8 @@
android:gravity="start|center_vertical"
android:drawablePadding="8dp"
android:paddingStart="8dp"
- android:textColor="#555555"
- android:textSize="@dimen/notification_text_size"
+ android:textColor="@color/secondary_text_material_light"
+ android:textSize="13sp"
android:singleLine="true"
android:ellipsize="end"
/>
diff --git a/core/res/res/layout/notification_material_action_list.xml b/core/res/res/layout/notification_material_action_list.xml
index ec4919b..2a36949 100644
--- a/core/res/res/layout/notification_material_action_list.xml
+++ b/core/res/res/layout/notification_material_action_list.xml
@@ -22,9 +22,6 @@
android:orientation="horizontal"
android:visibility="gone"
android:layout_marginBottom="8dp"
- android:showDividers="middle"
- android:divider="@drawable/list_divider_holo_light"
- android:dividerPadding="12dp"
>
<!-- actions will be added here -->
</LinearLayout>
diff --git a/core/res/res/layout/notification_template_icon_group.xml b/core/res/res/layout/notification_template_icon_group.xml
index 2ad6f9e..fa66163 100644
--- a/core/res/res/layout/notification_template_icon_group.xml
+++ b/core/res/res/layout/notification_template_icon_group.xml
@@ -23,20 +23,23 @@
android:id="@+id/icon_group"
>
<ImageView android:id="@+id/icon"
- android:layout_width="@dimen/notification_large_icon_width"
- android:layout_height="@dimen/notification_large_icon_height"
- android:padding="8dp"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginTop="12dp"
+ android:layout_marginBottom="12dp"
+ android:layout_marginStart="12dp"
+ android:layout_marginEnd="12dp"
android:scaleType="centerInside"
/>
<ImageView android:id="@+id/right_icon"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:padding="4dp"
+ android:layout_width="16dp"
+ android:layout_height="16dp"
+ android:padding="3dp"
android:layout_gravity="end|bottom"
android:scaleType="centerInside"
android:visibility="gone"
- android:layout_marginEnd="3dp"
- android:layout_marginBottom="3dp"
+ android:layout_marginEnd="8dp"
+ android:layout_marginBottom="8dp"
/>
</FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_base.xml b/core/res/res/layout/notification_template_material_base.xml
index 5e51db9..674d7b8 100644
--- a/core/res/res/layout/notification_template_material_base.xml
+++ b/core/res/res/layout/notification_template_material_base.xml
@@ -31,25 +31,12 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top"
- android:layout_marginEnd="8dp"
android:layout_marginStart="@dimen/notification_large_icon_width"
android:minHeight="@dimen/notification_large_icon_height"
android:orientation="vertical"
>
- <include layout="@layout/notification_template_part_line1"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- />
- <include layout="@layout/notification_template_part_line2"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- />
- <include layout="@layout/notification_template_part_line3"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- />
+ <include layout="@layout/notification_template_part_line1" />
+ <include layout="@layout/notification_template_part_line2" />
+ <include layout="@layout/notification_template_part_line3" />
</LinearLayout>
</FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_big_base.xml b/core/res/res/layout/notification_template_material_big_base.xml
index 2243a09..f264b7b 100644
--- a/core/res/res/layout/notification_template_material_big_base.xml
+++ b/core/res/res/layout/notification_template_material_big_base.xml
@@ -31,33 +31,52 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
- android:layout_marginEnd="8dp"
android:layout_marginStart="@dimen/notification_large_icon_width"
android:minHeight="@dimen/notification_large_icon_height"
android:orientation="vertical"
>
<include layout="@layout/notification_template_part_line1" />
<include layout="@layout/notification_template_part_line2" />
- <TextView android:id="@+id/big_text"
- android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:minHeight="@dimen/notification_large_icon_height"
- android:layout_weight="1"
- android:singleLine="false"
- android:visibility="gone"
+ android:layout_marginEnd="8dp"
+ android:orientation="horizontal"
+ android:gravity="top"
+ >
+ <TextView android:id="@+id/big_text"
+ android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:singleLine="false"
+ android:visibility="gone"
+ />
+ <ImageView android:id="@+id/profile_badge_large_template"
+ android:layout_width="20dp"
+ android:layout_height="20dp"
+ android:layout_weight="0"
+ android:layout_marginStart="4dp"
+ android:scaleType="fitCenter"
+ android:visibility="gone"
+ />
+ </LinearLayout>
+ <include
+ layout="@layout/notification_template_part_line3"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
/>
- <include layout="@layout/notification_template_part_line3" />
<ImageView
android:layout_width="match_parent"
android:layout_height="1dp"
+ android:layout_marginTop="10dp"
android:id="@+id/action_divider"
android:visibility="gone"
- android:background="@drawable/list_divider_holo_light" />
+ android:background="@drawable/notification_template_divider" />
<include
layout="@layout/notification_material_action_list"
- android:layout_marginLeft="-8dp"
- android:layout_marginRight="-8dp"
+ android:layout_marginStart="-8dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml
new file mode 100644
index 0000000..d9120f6
--- /dev/null
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+ android:id="@+id/status_bar_latest_event_content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ internal:layout_minHeight="65dp"
+ internal:layout_maxHeight="unbounded"
+ >
+ <include layout="@layout/notification_template_icon_group"
+ android:layout_width="@dimen/notification_large_icon_width"
+ android:layout_height="@dimen/notification_large_icon_height"
+ />
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:layout_marginStart="@dimen/notification_large_icon_width"
+ android:minHeight="@dimen/notification_large_icon_height"
+ android:orientation="vertical"
+ >
+ <include layout="@layout/notification_template_part_line1" />
+ <include layout="@layout/notification_template_part_line2" />
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:layout_marginBottom="10dp"
+ android:orientation="horizontal"
+ android:gravity="top"
+ >
+ <TextView android:id="@+id/big_text"
+ android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:singleLine="false"
+ android:visibility="gone"
+ />
+ <ImageView android:id="@+id/profile_badge_large_template"
+ android:layout_width="20dp"
+ android:layout_height="20dp"
+ android:layout_weight="0"
+ android:layout_marginStart="4dp"
+ android:scaleType="fitCenter"
+ android:visibility="gone"
+ />
+ </LinearLayout>
+ <ImageView
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:id="@+id/action_divider"
+ android:visibility="gone"
+ android:background="@drawable/notification_template_divider" />
+ <include
+ layout="@layout/notification_material_action_list"
+ android:layout_marginStart="-8dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ />
+ <ImageView
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:id="@+id/overflow_divider"
+ android:visibility="visible"
+ android:background="@drawable/notification_template_divider" />
+ <include
+ layout="@layout/notification_template_part_line3"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="10dp" />
+ </LinearLayout>
+</FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_inbox.xml b/core/res/res/layout/notification_template_material_inbox.xml
index 6133791..38b3ae2 100644
--- a/core/res/res/layout/notification_template_material_inbox.xml
+++ b/core/res/res/layout/notification_template_material_inbox.xml
@@ -37,83 +37,106 @@
>
<include layout="@layout/notification_template_part_line1" />
<include layout="@layout/notification_template_part_line2" />
- <TextView android:id="@+id/inbox_text0"
- android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+ <LinearLayout
android:layout_width="match_parent"
- android:layout_height="0dp"
- android:singleLine="true"
- android:ellipsize="end"
- android:visibility="gone"
- android:layout_weight="1"
- />
- <TextView android:id="@+id/inbox_text1"
- android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:singleLine="true"
- android:ellipsize="end"
- android:visibility="gone"
- android:layout_weight="1"
- />
- <TextView android:id="@+id/inbox_text2"
- android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:singleLine="true"
- android:ellipsize="end"
- android:visibility="gone"
- android:layout_weight="1"
- />
- <TextView android:id="@+id/inbox_text3"
- android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:singleLine="true"
- android:ellipsize="end"
- android:visibility="gone"
- android:layout_weight="1"
- />
- <TextView android:id="@+id/inbox_text4"
- android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:singleLine="true"
- android:ellipsize="end"
- android:visibility="gone"
- android:layout_weight="1"
- />
- <TextView android:id="@+id/inbox_text5"
- android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:singleLine="true"
- android:ellipsize="end"
- android:visibility="gone"
- android:layout_weight="1"
- />
- <TextView android:id="@+id/inbox_text6"
- android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:singleLine="true"
- android:ellipsize="end"
- android:visibility="gone"
- android:layout_weight="1"
- />
- <TextView android:id="@+id/inbox_more"
- android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:singleLine="true"
- android:ellipsize="end"
- android:visibility="gone"
- android:layout_weight="1"
- android:text="@android:string/ellipsis"
- />
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="top"
+ >
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ >
+ <TextView android:id="@+id/inbox_text0"
+ android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:visibility="gone"
+ android:layout_weight="1"
+ />
+ <TextView android:id="@+id/inbox_text1"
+ android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:visibility="gone"
+ android:layout_weight="1"
+ />
+ <TextView android:id="@+id/inbox_text2"
+ android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:visibility="gone"
+ android:layout_weight="1"
+ />
+ <TextView android:id="@+id/inbox_text3"
+ android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:visibility="gone"
+ android:layout_weight="1"
+ />
+ <TextView android:id="@+id/inbox_text4"
+ android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:visibility="gone"
+ android:layout_weight="1"
+ />
+ <TextView android:id="@+id/inbox_text5"
+ android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:visibility="gone"
+ android:layout_weight="1"
+ />
+ <TextView android:id="@+id/inbox_text6"
+ android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:visibility="gone"
+ android:layout_weight="1"
+ />
+ <TextView android:id="@+id/inbox_more"
+ android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:visibility="gone"
+ android:layout_weight="1"
+ android:text="@android:string/ellipsis"
+ />
+ </LinearLayout>
+ <ImageView android:id="@+id/profile_badge_large_template"
+ android:layout_width="20dp"
+ android:layout_height="20dp"
+ android:layout_weight="0"
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="8dp"
+ android:scaleType="fitCenter"
+ android:visibility="gone"
+ />
+ </LinearLayout>
<FrameLayout
android:id="@+id/inbox_end_pad"
android:layout_width="match_parent"
- android:layout_height="8dip"
+ android:layout_height="10dp"
android:visibility="gone"
android:layout_weight="0"
/>
@@ -122,7 +145,7 @@
android:layout_height="1dip"
android:id="@+id/action_divider"
android:visibility="gone"
- android:background="@drawable/list_divider_holo_light" />
+ android:background="@drawable/notification_template_divider" />
<include
layout="@layout/notification_material_action_list"
android:layout_width="match_parent"
@@ -136,7 +159,13 @@
android:layout_height="1dip"
android:id="@+id/overflow_divider"
android:visibility="visible"
- android:background="@drawable/list_divider_holo_light" />
- <include layout="@layout/notification_template_part_line3" />
+ android:background="@drawable/notification_template_divider" />
+ <include
+ layout="@layout/notification_template_part_line3"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="10dp" />
</LinearLayout>
</FrameLayout>
diff --git a/core/res/res/layout/notification_template_part_line1.xml b/core/res/res/layout/notification_template_part_line1.xml
index d652959..c6ea6bf 100644
--- a/core/res/res/layout/notification_template_part_line1.xml
+++ b/core/res/res/layout/notification_template_part_line1.xml
@@ -19,9 +19,8 @@
android:id="@+id/line1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
android:orientation="horizontal"
- android:paddingTop="@dimen/notification_vert_pad"
- android:layout_weight="0"
>
<TextView android:id="@+id/title"
android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Title"
diff --git a/core/res/res/layout/notification_template_part_line2.xml b/core/res/res/layout/notification_template_part_line2.xml
index 1e19df1..1f95150 100644
--- a/core/res/res/layout/notification_template_part_line2.xml
+++ b/core/res/res/layout/notification_template_part_line2.xml
@@ -16,23 +16,42 @@
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <TextView
- android:id="@+id/text2"
- android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Line2"
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="-2dp"
- android:layout_marginBottom="-2dp"
- android:singleLine="true"
- android:fadingEdge="horizontal"
- android:ellipsize="marquee"
+ android:layout_marginEnd="8dp"
android:visibility="gone"
android:layout_weight="0"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ >
+ <TextView
+ android:id="@+id/text2"
+ android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Line2"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="-1dp"
+ android:layout_marginBottom="-1dp"
+ android:singleLine="true"
+ android:fadingEdge="horizontal"
+ android:ellipsize="marquee"
+ android:visibility="gone"
+ android:layout_weight="1"
/>
+ <ImageView android:id="@+id/profile_badge_line2"
+ android:layout_width="20dp"
+ android:layout_height="20dp"
+ android:layout_weight="0"
+ android:layout_marginStart="4dp"
+ android:scaleType="fitCenter"
+ android:visibility="gone"
+ />
+ </LinearLayout>
<ProgressBar
android:id="@android:id/progress"
android:layout_width="match_parent"
- android:layout_height="8dp"
+ android:layout_height="15dp"
+ android:layout_marginEnd="8dp"
android:visibility="gone"
android:layout_weight="0"
style="@style/Widget.Material.Light.ProgressBar.Horizontal"
diff --git a/core/res/res/layout/notification_template_part_line3.xml b/core/res/res/layout/notification_template_part_line3.xml
index 2c8c704c..06de2a5 100644
--- a/core/res/res/layout/notification_template_part_line3.xml
+++ b/core/res/res/layout/notification_template_part_line3.xml
@@ -19,10 +19,9 @@
android:id="@+id/line3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
android:orientation="horizontal"
- android:layout_weight="0"
android:gravity="center_vertical"
- android:paddingBottom="@dimen/notification_vert_pad"
>
<TextView android:id="@+id/text"
android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
@@ -44,13 +43,13 @@
android:gravity="center"
android:paddingStart="8dp"
/>
- <ImageView android:id="@+id/profile_icon"
- android:layout_width="24dp"
- android:layout_height="24dp"
+ <ImageView android:id="@+id/profile_badge_line3"
+ android:layout_width="20dp"
+ android:layout_height="20dp"
android:layout_gravity="center"
android:layout_weight="0"
- android:layout_marginStart="8dp"
- android:scaleType="centerInside"
+ android:layout_marginStart="4dp"
+ android:scaleType="fitCenter"
android:visibility="gone"
/>
</LinearLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 45a392b..d27b49a 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Raak om USB-ontfouting te deaktiveer."</string>
<string name="select_input_method" msgid="8547250819326693584">"Verander sleutelbord"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Kies sleutelborde"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Fisiese sleutelbord"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardeware"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Kies sleutelborduitleg"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Raak om \'n sleutelborduitleg te kies."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 91f777d..ce5464c 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB ማረሚያ ላለማንቃት ዳስስ።"</string>
<string name="select_input_method" msgid="8547250819326693584">"ቁልፍ ሰሌዳ ይቀይሩ"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"ቁልፍ ሰሌዳዎችን ምረጥ"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"የሚዳሰስ የቁልፍ ሰሌዳ"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"ሃርድዌር"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"የቁልፍ ሰሌዳ አቀማመጥ ምረጥ"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"የቁልፍ ሰሌዳ አቀማመጥ ለመምረጥ ንካ።"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index e0cd94c..a6f65d0 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"المس لتعطيل تصحيح أخطاء USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"تغيير لوحة المفاتيح"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"اختيار لوحات المفاتيح"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"لوحة مفاتيح فعلية"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"أجهزة"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"تحديد تخطيط لوحة مفاتيح"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"المس لتحديد تخطيط لوحة مفاتيح."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 51d11c6..f2a9927 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Докоснете, за да деактивирате отстраняването на грешки през USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Промяна на клавиатурата"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Избиране на клавиатури"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Физическа клавиатура"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Хардуер"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Избиране на клавиатурна подредба"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Докоснете, за да изберете клавиатурна подредба."</string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index c288ab1..d0a6813 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB ডিবাগিং অক্ষম করতে স্পর্শ করুন৷"</string>
<string name="select_input_method" msgid="8547250819326693584">"কীবোর্ড পরিবর্তন করুন"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"কীবোর্ড চয়ন করুন"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"ফিজিক্যাল কীবোর্ড"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"হার্ডওয়্যার"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"কীবোর্ডের লেআউট নির্বাচন করুন"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"একটি কীবোর্ডের লেআউট নির্বাচন করতে স্পর্শ করুন৷"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 510c772..75cc1f0 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Toca per desactivar la depuració USB"</string>
<string name="select_input_method" msgid="8547250819326693584">"Canviar el teclat"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Tria els teclats"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Teclat físic"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Maquinari"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selecciona una disposició de teclat"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Toca per seleccionar una disposició de teclat."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 7bab386..7853f50 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Dotykem zakážete ladění USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Změna klávesnice"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Vyberte klávesnice"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Fyzická klávesnice"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardware"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Výběr rozložení klávesnice"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Dotykem vyberte rozložení klávesnice."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index c0351bc..6d05780 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Tryk for at deaktivere USB-fejlretning."</string>
<string name="select_input_method" msgid="8547250819326693584">"Skift tastatur"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Vælg tastaturer"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Fysisk tastatur"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardware"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Vælg tastaturlayout"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Tryk for at vælge et tastaturlayout."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index e45ce8a..8f7866f 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Zum Deaktivieren von USB-Debugging berühren"</string>
<string name="select_input_method" msgid="8547250819326693584">"Tastatur ändern"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Tastatur auswählen"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Physische Tastatur"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardware"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Tastaturlayout auswählen"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Zum Auswählen eines Tastaturlayouts berühren"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index b3db37d..b68c386 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -716,10 +716,8 @@
<string name="permdesc_use_sip" msgid="2297804849860225257">"Επιτρέπει στην εφαρμογή να πραγματοποιεί και να λαμβάνει κλήσεις SIP."</string>
<string name="permlab_bind_call_service" msgid="6724009726671246551">"αλληλεπίδραση με την οθόνη κατά τη διάρκεια κλήσης"</string>
<string name="permdesc_bind_call_service" msgid="8732547662442572435">"Επιτρέπει στην εφαρμογή να ελέγχει πότε και πώς βλέπει ο χρήστης την οθόνη κατά τη διάρκεια κλήσης."</string>
- <!-- no translation found for permlab_bind_connection_service (3557341439297014940) -->
- <skip />
- <!-- no translation found for permdesc_bind_connection_service (4008754499822478114) -->
- <skip />
+ <string name="permlab_bind_connection_service" msgid="3557341439297014940">"αλληλεπίδραση με υπηρεσίες τηλεφωνίας"</string>
+ <string name="permdesc_bind_connection_service" msgid="4008754499822478114">"Επιτρέπει στην εφαρμογή να αλληλεπιδρά με υπηρεσίες τηλεφωνίας για την πραγματοποίηση/λήψη κλήσεων."</string>
<string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"ανάγνωση ιστορικών δεδομένων χρήσης δικτύου"</string>
<string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"Επιτρέπει στην εφαρμογή την ανάγνωση ιστορικών στοιχείων χρήσης δικτύου για συγκεκριμένα δίκτυα και εφαρμογές."</string>
<string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"διαχείριση πολιτικής δικτύου"</string>
@@ -1352,7 +1350,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Αγγίξτε για απενεργοποίηση του εντοπισμού σφαλμάτων USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Αλλαγή πληκτρολογίου"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Επιλογή πληκτρολογίων"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Φυσικό πληκτρολόγιο"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Υλικό"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Επιλογή διάταξης πληκτρολογίου"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Αγγίξτε για να επιλέξετε διάταξη πληκτρολογίου."</string>
@@ -1764,31 +1763,20 @@
<string name="item_is_selected" msgid="949687401682476608">"Επιλέχτηκε το στοιχείο <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> διαγράφηκε"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Εργασία <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for lock_to_app_toast (1230563865743799321) -->
- <skip />
- <!-- no translation found for lock_to_app_toast_accessible (3340628918851844044) -->
- <skip />
- <!-- no translation found for lock_to_app_toast_locked (8739004135132606329) -->
- <skip />
- <!-- no translation found for lock_to_app_title (1682643873107812874) -->
- <skip />
- <!-- no translation found for lock_to_app_description (9076084599283282800) -->
- <skip />
- <!-- no translation found for lock_to_app_description_accessible (2132076937479670601) -->
- <skip />
+ <string name="lock_to_app_toast" msgid="1230563865743799321">"Για να ξεκαρφιτσώσετε αυτήν την οθόνη, αγγίξτε παρατεταμένα τα κουμπιά \"Επιστροφή\" και \"Πρόσφατα\" ταυτόχρονα."</string>
+ <string name="lock_to_app_toast_accessible" msgid="3340628918851844044">"Για να ξεκαρφιτσώσετε αυτήν την οθόνη, αγγίξτε παρατεταμένα το κουμπί \"Πρόσφατα\"."</string>
+ <string name="lock_to_app_toast_locked" msgid="8739004135132606329">"Η οθόνη καρφιστώθηκε. Το ξεκαρφίτσωμα δεν επιτρέπεται από τον οργανισμό σας."</string>
+ <string name="lock_to_app_title" msgid="1682643873107812874">"Χρήση καρφιτσώματος οθόνης;"</string>
+ <string name="lock_to_app_description" msgid="9076084599283282800">"Το καρφίτσωμα της οθόνης κλειδώνει την οθόνη σε μία μόνο προβολή.\n\nΓια έξοδο, αγγίξτε παρατεταμένα τα κουμπιά \"Επιστροφή\" και \"Πρόσφατα\" ταυτόχρονα."</string>
+ <string name="lock_to_app_description_accessible" msgid="2132076937479670601">"Το καρφίτσωμα της οθόνης κλειδώνει την οθόνη σε μία μόνο προβολή.\n\nΓια έξοδο, αγγίξτε παρατεταμένα το κουμπί \"Πρόσφατα\"."</string>
<string name="lock_to_app_negative" msgid="2259143719362732728">"ΟΧΙ, ΕΥΧΑΡΙΣΤΩ"</string>
<string name="lock_to_app_positive" msgid="7085139175671313864">"ΕΝΑΡΞΗ"</string>
- <!-- no translation found for lock_to_app_start (6643342070839862795) -->
- <skip />
- <!-- no translation found for lock_to_app_exit (8598219838213787430) -->
- <skip />
- <!-- no translation found for lock_to_app_use_screen_lock (5732663305876339596) -->
- <skip />
+ <string name="lock_to_app_start" msgid="6643342070839862795">"Η οθόνη καρφιτσώθηκε"</string>
+ <string name="lock_to_app_exit" msgid="8598219838213787430">"Η οθόνη ξεκαρφιτσώθηκε"</string>
+ <string name="lock_to_app_use_screen_lock" msgid="5732663305876339596">"Να γίνεται ερώτηση για %1$s πριν από το ξεκαρφίτσωμα"</string>
<string name="lock_to_app_unlock_pin" msgid="7908385370846820001">"Αριθμός PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="7763071104790758405">"μοτίβο ξεκλειδώματος"</string>
<string name="lock_to_app_unlock_password" msgid="795224196583495868">"κωδικός πρόσβασης"</string>
- <!-- no translation found for battery_saver_description (725676363406667978) -->
- <skip />
- <!-- no translation found for downtime_condition_summary (8761776337475705749) -->
- <skip />
+ <string name="battery_saver_description" msgid="725676363406667978">"Για τη βελτίωση της διάρκειας ζωής της μπαταρίας, η λειτουργία εξοικονόμησης μπαταρίας μειώνει την απόδοση της συσκευής σας και περιορίζει τη δόνηση και την πλειονότητα των δεδομένων παρασκηνίου. Το ηλεκτρονικό ταχυδρομείου, η ανταλλαγή μηνυμάτων και άλλες εφαρμογές που βασίζονται στο συγχρονισμό ενδέχεται να μην ενημερώνονται, παρά μόνο εάν τις ανοίξετε.\n\nΗ λειτουργία εξοικονόμησης μπαταρίας απενεργοποιείται αυτόματα κατά τη φόρτιση της συσκευής σας."</string>
+ <string name="downtime_condition_summary" msgid="8761776337475705749">"Έως τη λήξη του νεκρού χρόνου σας στις <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 3e2d93e..0d87540 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Touch to disable USB debugging."</string>
<string name="select_input_method" msgid="8547250819326693584">"Change keyboard"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Choose keyboards"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Physical keyboard"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardware"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Select keyboard layout"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Touch to select a keyboard layout."</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 3e2d93e..0d87540 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Touch to disable USB debugging."</string>
<string name="select_input_method" msgid="8547250819326693584">"Change keyboard"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Choose keyboards"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Physical keyboard"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardware"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Select keyboard layout"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Touch to select a keyboard layout."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index d321412..d853a0f 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Toca para desactivar la depuración por USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Cambiar el teclado"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Seleccionar teclados"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Teclado físico"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardware"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selecciona un diseño de teclado"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Toca para seleccionar un diseño de teclado."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index ccbb8d3..5782c9b 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Toca para inhabilitar la depuración USB"</string>
<string name="select_input_method" msgid="8547250819326693584">"Cambiar teclado"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Seleccionar teclados"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Teclado físico"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardware"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selecciona un diseño de teclado"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Toca para seleccionar un diseño de teclado."</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index a3820ee..a490e9c 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Puudutage USB-silumise keelamiseks."</string>
<string name="select_input_method" msgid="8547250819326693584">"Klaviatuuri muutmine"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Vali klaviatuurid"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Füüsiline klaviatuur"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Riistvara"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Klaviatuuri paigutuse valimine"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Puudutage klaviatuuri paigutuse valimiseks."</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index a82f4a3..f00e596 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB arazketa desgaitzeko, ukitu hau."</string>
<string name="select_input_method" msgid="8547250819326693584">"Aldatu teklatua"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Aukeratu teklatuak"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Teklatu fisikoa"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardwarea"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Hautatu teklatuaren diseinua"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Ukitu teklatuaren diseinua hautatzeko."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index bd725ae..99f6c0d 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"برای غیرفعال کردن اشکال زدایی USB لمس کنید."</string>
<string name="select_input_method" msgid="8547250819326693584">"تغییر صفحهکلید"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"انتخاب صفحهکلیدها"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"صفحهکلید فیزیکی"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"سختافزار"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"انتخاب طرحبندی صفحهکلید"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"برای انتخاب یک طرحبندی صفحهکلید لمس کنید…"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 71e33e9..3b62f74 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Poista USB-vianetsintä käytöstä koskettamalla tätä."</string>
<string name="select_input_method" msgid="8547250819326693584">"Vaihda näppäimistö"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Valitse näppäimistöt"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Fyysinen näppäimistö"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Laitteisto"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Valitse näppäimistöasettelu"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Kosketa ja valitse näppäimistöasettelu."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 4a63f0e..298c64a 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Appuyez pour désactiver le débogage USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Changer de clavier"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Choisir les claviers"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Clavier physique"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Matériel"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Sélectionnez la disposition du clavier"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Appuyez ici pour sélectionner une disposition de clavier."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index d300946..77fe1f9 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Appuyez pour désactiver le débogage USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Changer de clavier"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Sélectionner des claviers"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Clavier physique"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Matériel"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Sélectionnez la disposition du clavier"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Appuyez ici pour sélectionner une disposition de clavier."</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 622d3d0..f163c4e 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Toca para desactivar a depuración de erros de USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Cambiar teclado"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Seleccionar teclados"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Teclado físico"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardware"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Seleccionar deseño de teclado"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Toca para seleccionar un deseño de teclado."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 9662dda..720cc06 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB डीबग करना अक्षम करने के लिए स्पर्श करें."</string>
<string name="select_input_method" msgid="8547250819326693584">"कीबोर्ड बदल सकता है"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"कीबोर्ड चुनें"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"भौतिक कीबोर्ड"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"हार्डवेयर"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"कीबोर्ड लेआउट को चुनें"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"कीबोर्ड लेआउट का चयन करने के लिए स्पर्श करें."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 4e434f4..3ab351b 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Dodirnite da biste onemogućili rješavanje programske pogreške na USB-u."</string>
<string name="select_input_method" msgid="8547250819326693584">"Promjena tipkovnice"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Odaberi tipkovnice"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Fizička tipkovnica"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardver"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Odaberite izgled tipkovnice"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Dodirnite za odabir izgleda tipkovnice."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index d38e841..c18fe3d 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Érintse meg az USB hibakeresés kikapcsolásához."</string>
<string name="select_input_method" msgid="8547250819326693584">"Billentyűzet megváltoztatása"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Billentyűzetek kiválasztása"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Fizikai billentyűzet"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardver"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Válasszon billentyűzetkiosztást"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Érintse meg az egyik billentyűzetkiosztás kiválasztásához."</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 69c0c60..49c1354 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Հպեք` USB կարգաբերումը կասեցնելու համար:"</string>
<string name="select_input_method" msgid="8547250819326693584">"Փոխել ստեղնաշարը"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Ընտրել ստեղնաշար"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Ֆիզիկական ստեղնաշար"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Սարքաշար"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Ընտրեք ստեղնաշարի դիրքը"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Հպեք` ստեղնաշարի դիրքը ընտրելու համար:"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 465f9d4..e76cbbc 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Sentuh untuk menonaktifkan debugging USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Ubah keyboard"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Pilih keyboard"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Keyboard fisik"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Perangkat Keras"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Pilih tata letak keyboard"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Sentuh untuk memilih tata letak keyboard."</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 716c789..c7e94dd 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Snertu til að slökkva á USB-villuleit."</string>
<string name="select_input_method" msgid="8547250819326693584">"Skipta um lyklaborð"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Velja lyklaborð"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Vélbúnaðarlyklaborð"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Vélbúnaður"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Veldu lyklaskipan"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Snertu til að velja lyklaskipan."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 13374b7..de7961b 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Tocca per disattivare il debug USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Cambia tastiera"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Scegli tastiere"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Tastiera fisica"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardware"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Seleziona layout tastiera"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Tocca per selezionare un layout di tastiera."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 01444be..d53028d 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"גע כדי להשבית את ניקוי הבאגים בהתקן ה-USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"שינוי מקלדת"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"בחר מקלדות"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"מקלדת פיזית"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"חומרה"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"בחירת פריסת מקלדת"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"גע כדי לבחור פריסת מקלדת."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 09d51da..5666693 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"タップしてUSBデバッグを無効にします。"</string>
<string name="select_input_method" msgid="8547250819326693584">"キーボードの変更"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"キーボードの選択"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"物理キーボード"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"ハードウェア"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"キーボードレイアウトの選択"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"タップしてキーボードレイアウトを選択してください。"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 9849d9b..b0b5e80 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"შეეხეთ, რათა შეწყვიტოთ USB-ის გამართვა."</string>
<string name="select_input_method" msgid="8547250819326693584">"კლავიატურის შეცვლა"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"კლავიატურების არჩევა"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"ფიზიკური კლავიატურა"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"მოწყობილობა"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"შეარჩიეთ კლავიატურის განლაგება."</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"კლავიატურის განლაგების შესარჩევად შეეხეთ."</string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 3c3d15b..03a42f2 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB күйін келтіруді өшіру үшін түртіңіз."</string>
<string name="select_input_method" msgid="8547250819326693584">"Пернетақтаны өзгерту"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Пернетақталарды таңдау"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Қатты пернетақта"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Компьютерлік жабдық"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Пернетақта орналасуын таңдау"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Пернетақта орналасуын таңдау үшін түртіңіз."</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index f2eaf10..aeea46f 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1354,7 +1354,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"ប៉ះ ដើម្បីបិទការកែកំហុសយូអេសប៊ី។"</string>
<string name="select_input_method" msgid="8547250819326693584">"ប្ដូរក្ដារចុច"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"ជ្រើសក្ដារចុច"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"ក្ដារចុចពិតប្រាកដ"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"ផ្នែករឹង"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"ជ្រើសប្លង់ក្ដារចុច"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"ប៉ះ ដើម្បីជ្រើសប្លង់ក្ដារចុច។"</string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index 2e5fbee..2750032 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಸ್ಪರ್ಶಿಸಿ."</string>
<string name="select_input_method" msgid="8547250819326693584">"ಕೀಬೋರ್ಡ್ ಬದಲಿಸಿ"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"ಕೀಬೋರ್ಡ್ಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"ಹಾರ್ಡ್ವೇರ್"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"ಕೀಬೋರ್ಡ್ ಲೇಔಟ್ ಆಯ್ಕೆಮಾಡಿ"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"ಕೀಬೋರ್ಡ್ ಲೇಔಟ್ ಆಯ್ಕೆ ಮಾಡಲು ಸ್ಪರ್ಶಿಸಿ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 55ae682..2631902 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB 디버깅을 사용하지 않으려면 터치하세요."</string>
<string name="select_input_method" msgid="8547250819326693584">"키보드 변경"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"키보드 선택"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"물리적 키보드"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"하드웨어"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"키보드 레이아웃 선택"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"터치하여 키보드 레이아웃을 선택합니다."</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 2b66d13..4f14e95 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1747,7 +1747,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB мүчүлүштүктөрдү жоюу мүмкүнчүлүгүн өчүрүү үчүн тийип коюңуз."</string>
<string name="select_input_method" msgid="8547250819326693584">"Баскычтопту өзгөртүү"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Баскычтопторду тандаңыз"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Аппараттык тергич"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Аппараттык"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Тергичтин жайгашуусун тандоо"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Тергичтин жайгашуусун тандаш үчүн басыңыз."</string>
diff --git a/core/res/res/values-land/dimens_material.xml b/core/res/res/values-land/dimens_material.xml
index c8c95d7b..77719a6 100644
--- a/core/res/res/values-land/dimens_material.xml
+++ b/core/res/res/values-land/dimens_material.xml
@@ -19,5 +19,9 @@
<dimen name="action_bar_default_height_material">48dp</dimen>
<!-- Default padding of an action bar. -->
<dimen name="action_bar_default_padding_material">0dp</dimen>
+ <!-- Default text size for action bar title.-->
+ <dimen name="text_size_title_material_toolbar">14dp</dimen>
+ <!-- Default text size for action bar subtitle.-->
+ <dimen name="text_size_subtitle_material_toolbar">12dp</dimen>
</resources>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 7372528..d7e2b9b 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -716,10 +716,8 @@
<string name="permdesc_use_sip" msgid="2297804849860225257">"ອະນຸຍາດໃຫ້ແອັບຯສາມາດຮັບສາຍ ແລະໂທອອກຜ່ານ SIP ໄດ້"</string>
<string name="permlab_bind_call_service" msgid="6724009726671246551">"ໂຕ້ຕອບກັບໜ້າຈໍການໂທ"</string>
<string name="permdesc_bind_call_service" msgid="8732547662442572435">"ອະນຸຍາດໃຫ້ແອັບຯ ຄວບຄຸມເວລາ ແລະວິທີການທີ່ຜູ່ໃຊ້ເຫັນໜ້າຈໍການໂທໄດ້."</string>
- <!-- no translation found for permlab_bind_connection_service (3557341439297014940) -->
- <skip />
- <!-- no translation found for permdesc_bind_connection_service (4008754499822478114) -->
- <skip />
+ <string name="permlab_bind_connection_service" msgid="3557341439297014940">"ສັ່ງບໍລິການໂທລະສັບ"</string>
+ <string name="permdesc_bind_connection_service" msgid="4008754499822478114">"ອະນຸຍາດໃຫ້ແອັບຯສັ່ງບໍລິການໂທລະສັບເພື່ອໂທຫຼືຮັບສາຍໄດ້."</string>
<string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"ອ່ານປະຫວັດການນຳໃຊ້ເຄືອຂ່າຍ"</string>
<string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"ອະນຸຍາດໃຫ້ແອັບຯ ອ່ານປະຫວັດການນຳໃຊ້ເຄືອຂ່າຍຂອງແອັບຯ ແລະເຄືອຂ່າຍໃດນຶ່ງ."</string>
<string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"ຈັດການນະໂຍບາຍເຄືອຂ່າຍ"</string>
@@ -1352,7 +1350,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"ແຕະເພື່ອປິດການດີບັ໊ກຜ່ານ USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"ປ່ຽນແປ້ນພິມ"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"ເລືອກແປ້ນພິມ"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"ແປ້ນພິມແທ້"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"ຮາດແວ"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"ເລືອກຮູບແບບແປ້ນພິມ"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"ກົດເພື່ອເລືອກຮູບແບບແປ້ນພິມ."</string>
@@ -1764,30 +1763,20 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ຖືກເລືອກແລ້ວ"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ຖືກລຶບແລ້ວ"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"ບ່ອນເຮັດວຽກ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for lock_to_app_toast (1230563865743799321) -->
- <skip />
- <!-- no translation found for lock_to_app_toast_accessible (3340628918851844044) -->
- <skip />
- <!-- no translation found for lock_to_app_toast_locked (8739004135132606329) -->
- <skip />
- <!-- no translation found for lock_to_app_title (1682643873107812874) -->
- <skip />
- <!-- no translation found for lock_to_app_description (9076084599283282800) -->
- <skip />
- <!-- no translation found for lock_to_app_description_accessible (2132076937479670601) -->
- <skip />
+ <string name="lock_to_app_toast" msgid="1230563865743799321">"ເພື່ອຍົກເລີກການປັກໝຸດໜ້າຈໍນີ້, ໃຫ້ແຕະປຸ່ມກັບຄືນແລະປຸ່ມແອັບຯທີ່ຫາກໍໃຊ້ຄ້າງໄວ້ພ້ອມກັນ."</string>
+ <string name="lock_to_app_toast_accessible" msgid="3340628918851844044">"ເພື່ອຍົກເລີກການປັກໝຸດໜ້າຈໍນີ້, ໃຫ້ແຕະປຸ່ມແອັບຯທີ່ຫາກໍໃຊ້ຄ້າງໄວ້."</string>
+ <string name="lock_to_app_toast_locked" msgid="8739004135132606329">"ໜ້າຈໍຖືກປັກໝຸດໄວ້. ອົງກອນຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ຍົກເລີກການປັກໝຸດໄດ້."</string>
+ <string name="lock_to_app_title" msgid="1682643873107812874">"ໃຊ້ການປັກໝຸດໜ້າຈໍບໍ່?"</string>
+ <string name="lock_to_app_description" msgid="9076084599283282800">"ການປັກໝຸດໜ້າຈໍຈະລັອກໜ້າຈໍໄວ້ທີ່ມຸມມອງໃດນຶ່ງ.\n\nເພື່ອອອກ, ໃຫ້ແຕະປຸ່ມກັບຄືນແລະປຸ່ມແອັບຯທີ່ຫາກໍໃຊ້ຄ້າງໄວ້ພ້ອມກັນ."</string>
+ <string name="lock_to_app_description_accessible" msgid="2132076937479670601">"ການປັກໝຸດໜ້າຈໍຈະລັອກໜ້າຈໍໄວ້ທີ່ມຸມມອງໃດນຶ່ງ.\n\nເພື່ອອອກ, ໃຫ້ແຕະປຸ່ມແອັບຯທີ່ຫາກໍໃຊ້ຄ້າງໄວ້."</string>
<string name="lock_to_app_negative" msgid="2259143719362732728">"ບໍ່, ຂອບໃຈ"</string>
<string name="lock_to_app_positive" msgid="7085139175671313864">"ເລີ່ມ"</string>
- <!-- no translation found for lock_to_app_start (6643342070839862795) -->
- <skip />
- <!-- no translation found for lock_to_app_exit (8598219838213787430) -->
- <skip />
- <!-- no translation found for lock_to_app_use_screen_lock (5732663305876339596) -->
- <skip />
+ <string name="lock_to_app_start" msgid="6643342070839862795">"ປັກໝຸດໜ້າຈໍແລ້ວ"</string>
+ <string name="lock_to_app_exit" msgid="8598219838213787430">"ຍົກເລີກການປັກໝຸນຫນ້າຈໍແລ້ວ"</string>
+ <string name="lock_to_app_use_screen_lock" msgid="5732663305876339596">"ຖາມ %1$s ກ່ອນຍົກເລີກການປັກໝຸດ"</string>
<string name="lock_to_app_unlock_pin" msgid="7908385370846820001">"PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="7763071104790758405">"ຮູບແບບປົດລັອກ"</string>
<string name="lock_to_app_unlock_password" msgid="795224196583495868">"ລະຫັດຜ່ານ"</string>
<string name="battery_saver_description" msgid="725676363406667978">"ເພື່ອຊ່ວຍປັບປຸງອາຍຸແບັດເຕີຣີ, ໂຕປະຢັດແບັດເຕີຣີຈະຫຼຸດປະສິດທິພາບຂອງອຸປະກອນຂອງທ່ານລົງ ແລະຈຳກັດການສັ່ນເຕືອນ ຮວມທັງຂໍ້ມູນພື້ນຫຼັງສ່ວນໃຫຍ່. ອີເມວ, ການສົ່ງຂໍ້ຄວາມ ແລະແອັບຯອື່ນໆທີ່ອີງອາໃສການຊິ້ງຂໍ້ມູນອາດບໍ່ມີການອັບເດດຈົນກວ່າທ່ານຈະເປີດແອັບຯເຫຼົ່ານັ້ນ.\n\nໂຕປະຢັດແບັດເຕີຣີຈະປິດໂຕເອງອັດຕະໂນມັດໃນເວລາທີ່ອຸປະກອນຂອງທ່ານສາກໄຟຢູ່"</string>
- <!-- no translation found for downtime_condition_summary (8761776337475705749) -->
- <skip />
+ <string name="downtime_condition_summary" msgid="8761776337475705749">"ຈົນກວ່າດາວທາມຂອງທ່ານຈະສິ້ນສຸດທີ່ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 5d65ce3..058a5fc 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Palieskite, kad neleistumėte USB derinimo."</string>
<string name="select_input_method" msgid="8547250819326693584">"Klaviatūros keitimas"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Pasirinkti klaviatūras"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Fizinė klaviatūra"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Apar. įr."</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Pasirinkite klaviatūros išdėstymą"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Palieskite, kad pasirinktumėte klaviatūros išdėstymą."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 7c07f92..de566b8 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Pieskarieties, lai atspējotu USB atkļūdošanu."</string>
<string name="select_input_method" msgid="8547250819326693584">"Tastatūras maiņa"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Izvēlēties tastatūru"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Fiziskā tastatūra"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Aparatūra"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Atlasiet tastatūras izkārtojumu"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Pieskarieties, lai atlasītu tastatūras izkārtojumu."</string>
diff --git a/core/res/res/values-mcc310-mnc004/config.xml b/core/res/res/values-mcc310-mnc004/config.xml
index 4aac79d..423e250 100644
--- a/core/res/res/values-mcc310-mnc004/config.xml
+++ b/core/res/res/values-mcc310-mnc004/config.xml
@@ -33,4 +33,5 @@
<item>83</item>
</string-array>
+ <bool name="config_auto_attach_data_on_creation">false</bool>
</resources>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index 1c83644..e5af60b 100644
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -43,4 +43,5 @@
provisioning, availability etc -->
<bool name="config_mobile_allow_volte_vt">false</bool>
+ <bool name="config_auto_attach_data_on_creation">false</bool>
</resources>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index c53226a..4e58f49 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Допрете за да се оневозможи отстранувањето грешки преку USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Измени тастатура"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Избери тастатури"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Физичка тастатура"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Хардвер"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Избери изглед на тастатура"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Допри за да избереш изглед на тастатура."</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 733a508..4679b27 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB ഡീബഗ്ഗിംഗ് പ്രവർത്തനരഹിതമാക്കാൻ സ്പർശിക്കുക."</string>
<string name="select_input_method" msgid="8547250819326693584">"കീബോർട്ട് മാറ്റുക"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"കീബോർഡുകൾ തിരഞ്ഞെടുക്കുക"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"ഭൗതിക കീബോർഡ്"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"ഹാർഡ്വെയർ"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"കീബോർഡ് ലേഔട്ട് തിരഞ്ഞെടുക്കുക"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"ഒരു കീബോർഡ് ലേഔട്ട് തിരഞ്ഞെടുക്കാൻ സ്പർശിക്കുക."</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 0e90ada..9c0b211 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -716,10 +716,8 @@
<string name="permdesc_use_sip" msgid="2297804849860225257">"Апп-д SIP дуудлага хийх болон хүлээн авахыг зөвшөөрөх."</string>
<string name="permlab_bind_call_service" msgid="6724009726671246551">"дуудлагын дэлгэцтэй харьцах"</string>
<string name="permdesc_bind_call_service" msgid="8732547662442572435">"Апп-д дуудлагын дэлгэцийг хэрэглэгчид хэзээ хэрхэн харуулахыг удирдахыг зөвшөөрнө."</string>
- <!-- no translation found for permlab_bind_connection_service (3557341439297014940) -->
- <skip />
- <!-- no translation found for permdesc_bind_connection_service (4008754499822478114) -->
- <skip />
+ <string name="permlab_bind_connection_service" msgid="3557341439297014940">"телефоны үйлчилгээтэй харилцах"</string>
+ <string name="permdesc_bind_connection_service" msgid="4008754499822478114">"Апп-д телефон үйлчилгээтэй харилцаж дуудлага хийх/авахыг зөвшөөрнө."</string>
<string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"сүлжээний ашиглалтын түүхийг унших"</string>
<string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"Апп нь тусгай сүлжээ болон апп-н сүлжээ ашиглалтын түүхийг унших боломжтой."</string>
<string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"сүлжээний бодлогыг удирдах"</string>
@@ -1352,7 +1350,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB дебаг хийхийг идэвхгүй болгох бол хүрнэ үү."</string>
<string name="select_input_method" msgid="8547250819326693584">"Гарыг өөрчлөх"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Гар сонгох"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Бодит гар"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Хардвер"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Гарын схемийг сонгох"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Гарын схемийг сонгох бол хүрнэ үү."</string>
@@ -1764,30 +1763,20 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> сонгогдсон"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> устсан"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Ажлын <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for lock_to_app_toast (1230563865743799321) -->
- <skip />
- <!-- no translation found for lock_to_app_toast_accessible (3340628918851844044) -->
- <skip />
- <!-- no translation found for lock_to_app_toast_locked (8739004135132606329) -->
- <skip />
- <!-- no translation found for lock_to_app_title (1682643873107812874) -->
- <skip />
- <!-- no translation found for lock_to_app_description (9076084599283282800) -->
- <skip />
- <!-- no translation found for lock_to_app_description_accessible (2132076937479670601) -->
- <skip />
+ <string name="lock_to_app_toast" msgid="1230563865743799321">"Дэлгэцийг суллахын тулд Буцах болон Саяхных-г зэрэг дараад барина уу."</string>
+ <string name="lock_to_app_toast_accessible" msgid="3340628918851844044">"Дэлгэцийг суллахын тулд Саяхных-д хүрээд барина уу."</string>
+ <string name="lock_to_app_toast_locked" msgid="8739004135132606329">"Дэлгэцийг тогтоосон. Дэлгэц суллахыг таны байгууллага зөвшөөрөөгүй."</string>
+ <string name="lock_to_app_title" msgid="1682643873107812874">"Дэлгэц тогтоогчийг ашиглах уу?"</string>
+ <string name="lock_to_app_description" msgid="9076084599283282800">"Дэлгэц тогтоогч нь дэлгэцийг нэг янзаар түгжинэ.\n\nГарахын тулд Буцах болон Саяхных-д зэрэг хүрээд барина уу."</string>
+ <string name="lock_to_app_description_accessible" msgid="2132076937479670601">"Дэлгэц тогтоогч нь дэлгэцийг нэг янзаар түгжинэ.\n\nГарахын тулд Буцах болон Саяхных-д зэрэг хүрээд барина уу."</string>
<string name="lock_to_app_negative" msgid="2259143719362732728">"ҮГҮЙ"</string>
<string name="lock_to_app_positive" msgid="7085139175671313864">"ЭХЛҮҮЛЭХ"</string>
- <!-- no translation found for lock_to_app_start (6643342070839862795) -->
- <skip />
- <!-- no translation found for lock_to_app_exit (8598219838213787430) -->
- <skip />
- <!-- no translation found for lock_to_app_use_screen_lock (5732663305876339596) -->
- <skip />
+ <string name="lock_to_app_start" msgid="6643342070839862795">"Дэлгэцийг тогтоосон"</string>
+ <string name="lock_to_app_exit" msgid="8598219838213787430">"Дэлгэцийг сулласан"</string>
+ <string name="lock_to_app_use_screen_lock" msgid="5732663305876339596">"Суллахаас өмнө %1$s хүснэ үү"</string>
<string name="lock_to_app_unlock_pin" msgid="7908385370846820001">"PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="7763071104790758405">"тайлах хээ"</string>
<string name="lock_to_app_unlock_password" msgid="795224196583495868">"нууц үг"</string>
<string name="battery_saver_description" msgid="725676363406667978">"Батерейны ашиглалтыг уртасгахын тулд батерей хэмнэгч нь таны төхөөрөмжийн ажиллагааг бууруулж, чичрэлт болон далд датаны ихэнх хувийг хязгаарлана. Имэйл, зурвас гэх мэт синк хийгддэг бусад апп-ууд таныг нээхээс нааш шинэчлэгдэхгүй байж болно.\n\nТаныг төхөөрөмжөө цэнэглэх үед батерей хэмнэгч автоматаар унтарна."</string>
- <!-- no translation found for downtime_condition_summary (8761776337475705749) -->
- <skip />
+ <string name="downtime_condition_summary" msgid="8761776337475705749">"Таны уйтгартай байдал <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-д дуусах хүртэл"</string>
</resources>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index cde4dd1..7715a01 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB डीबग करणे अक्षम करण्यासाठी स्पर्श करा."</string>
<string name="select_input_method" msgid="8547250819326693584">"कीबोर्ड बदला"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"कीबोर्ड निवडा"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"वास्तविक कीबोर्ड"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"हार्डवेअर"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"कीबोर्ड लेआउट निवडा"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"कीबोर्ड लेआउट निवडण्यासाठी स्पर्श करा."</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 0bf4ca6..ce4bb30 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Sentuh untuk melumpuhkan penyahpepijatan USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Tukar papan kekunci"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Pilih papan kekunci"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Papan kekunci fizikal"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Perkakasan"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Pilih susun atur papan kekunci"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Sentuh untuk memilih susun atur papan kekunci."</string>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 8fdeedb..5066ea64 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -716,10 +716,8 @@
<string name="permdesc_use_sip" msgid="2297804849860225257">"SIP ခေါ်ဆိုမှုများ ခေါ်ရန်နှင့် လက်ခံနိုင်ရန် app ကို ခွင့်ပြုပါ။"</string>
<string name="permlab_bind_call_service" msgid="6724009726671246551">"တခါတည်း ခေါ်ဆိုနိုင်သော ဖန်သားပြင်နဲ့ ဆက်ဆံရန်"</string>
<string name="permdesc_bind_call_service" msgid="8732547662442572435">"ဖုန်းကိုင်သူ ဘယ်အချိန် ဘယ်လိုမှာ အပလီကေးရှင်းအတွင်း ဖုန်းခေါ်မှုကို မြင်ရခြင်းအား ထိန်းချုပ်ခွင့်ပေးခြင်း"</string>
- <!-- no translation found for permlab_bind_connection_service (3557341439297014940) -->
- <skip />
- <!-- no translation found for permdesc_bind_connection_service (4008754499822478114) -->
- <skip />
+ <string name="permlab_bind_connection_service" msgid="3557341439297014940">"တယ်လီဖုန်း ဝန်ဆောင်မှုများနှင့် အပြန်အလှန် တုံ့ပြန်မှု"</string>
+ <string name="permdesc_bind_connection_service" msgid="4008754499822478114">"appအား ခေါ်ဆိုမှုများ လုပ်ခြင်း/လက်ခံခြင်း ပြုလုပ်နိုင်ရန် တယ်လီဖုန်း ဝန်ဆောင်မှုများနှင့် အပြန်အလှန် တုံ့ပြန်မှုကို ခွင့်ပြုသည်။"</string>
<string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"ရာဇဝင်အလိုက် ကွန်ယက်သုံစွဲမှုအား ဖတ်ခြင်း"</string>
<string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"appအား အထူး ကွန်ရက်များ နှင့် appများ အတွက် ကွန်ရက် အသုံးပြုမှု မှတ်တမ်းကို ဖတ်ကြားခွင့် ပြုသည်။"</string>
<string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"ကွန်ယက်မူဝါဒအား စီမံခြင်း"</string>
@@ -1352,7 +1350,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB ဒီဘာဂင် ပိတ်ရန် ထိပါ။"</string>
<string name="select_input_method" msgid="8547250819326693584">"ကီးဘုတ် ပြောင်းလဲရန်"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"ကီးဘုတ်များကို ရွေးရန်"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"ခလုတ်ပါဝင်သော ကီးဘုတ်"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"ဟာ့ဒ်ဝဲ"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"လက်ကွက် အပြင်အဆင်ရွေးရန်"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"လက်ကွက် အပြင်အဆင်ရွေးရန် တို့ထိပါ"</string>
@@ -1481,7 +1480,7 @@
<string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g>မှ တည်နေရာအား တောင်းခံသည်"</string>
<string name="gpsNotifTitle" msgid="5446858717157416839">"တည်နေရာအား တောင်းခံသည်"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"<xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)မှတောင်းခံသည်"</string>
- <string name="gpsVerifYes" msgid="2346566072867213563">"ဟုတ်သည်"</string>
+ <string name="gpsVerifYes" msgid="2346566072867213563">"ဟုတ်ကဲ့"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"မဟုတ်ပါ"</string>
<string name="sync_too_many_deletes" msgid="5296321850662746890">"ပယ်ဖျက်မည့်ကန့်သတ်နှုန်းကျော်လွန်သည်"</string>
<string name="sync_too_many_deletes_desc" msgid="496551671008694245">"<xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>၊ account <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> အတွက် စုစုပေါင်း <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> အရာဖျက်ထားပါသည်။ သင်ဘာလုပ်ချင်ပါလဲ?"</string>
@@ -1764,31 +1763,20 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ခုရွေးချယ်ထားပြီး"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ကို ဖျက်ပြီးပါပြီ"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"အလုပ် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for lock_to_app_toast (1230563865743799321) -->
- <skip />
- <!-- no translation found for lock_to_app_toast_accessible (3340628918851844044) -->
- <skip />
- <!-- no translation found for lock_to_app_toast_locked (8739004135132606329) -->
- <skip />
- <!-- no translation found for lock_to_app_title (1682643873107812874) -->
- <skip />
- <!-- no translation found for lock_to_app_description (9076084599283282800) -->
- <skip />
- <!-- no translation found for lock_to_app_description_accessible (2132076937479670601) -->
- <skip />
+ <string name="lock_to_app_toast" msgid="1230563865743799321">"ဒီမျက်နှာပြင် ပင်ထိုးထားမှုကို ဖြုတ်ရန် နောက် နှင့် မကြာမီတုန်းက ခလုတ်များကို တစ်ချိန်တည်း ထိလျက် ကိုင်ထားပါ။"</string>
+ <string name="lock_to_app_toast_accessible" msgid="3340628918851844044">"ဒီမျက်နှာပြင် ပင်ထိုးထားမှုကို ဖြုတ်ရန် နောက် နှင့် မကြာမီတုန်းက ခလုတ်များကို ထိလျက် ကိုင်ထားပါ။."</string>
+ <string name="lock_to_app_toast_locked" msgid="8739004135132606329">"မျက်နှာပြင်ကို ပင်ထိုးထားသည်။ ပင်ထိုးထားမှု ဖြုတ်ခြင်းကို သင့် အဖွဲ့အစည်းက ခွင့် မပြုပါ။"</string>
+ <string name="lock_to_app_title" msgid="1682643873107812874">"မျက်နှာပြင် ပင်ထိုးမှုကို သုံးမလား?"</string>
+ <string name="lock_to_app_description" msgid="9076084599283282800">"မျက်နှာပြင်ကို ပင်ထိုးလိုက်ခြင်းက ပြကွက်ကို တစ်ခုတည်းသော မြင်းကွင်းသို့ သော့ပိတ်ထားမည်။ \n\nထွက်လိုက်ရန်၊ နောက် နှင့် မကြာမီတုန်းက ခလုတ်များကို တစ်ချိန်တည်း ထိလျက် ကိုင်ထားပါ။"</string>
+ <string name="lock_to_app_description_accessible" msgid="2132076937479670601">"မျက်နှာပြင်ကို ပင်ထိုးလိုက်ခြင်းက ပြကွက်ကို တစ်ခုတည်းသော မြင်းကွင်းသို့ သော့ပိတ်ထားမည်။ \n\nထွက်လိုက်ရန်၊ နောက် နှင့် မကြာမီတုန်းက ခလုတ်များကို ထိလျက် ကိုင်ထားပါ။"</string>
<string name="lock_to_app_negative" msgid="2259143719362732728">"မလို၊ ကျေးဇူးပါပဲ"</string>
<string name="lock_to_app_positive" msgid="7085139175671313864">"စတင်ရန်"</string>
- <!-- no translation found for lock_to_app_start (6643342070839862795) -->
- <skip />
- <!-- no translation found for lock_to_app_exit (8598219838213787430) -->
- <skip />
- <!-- no translation found for lock_to_app_use_screen_lock (5732663305876339596) -->
- <skip />
+ <string name="lock_to_app_start" msgid="6643342070839862795">"မျက်နှာပြင်ကို ပင်ထိုးထား"</string>
+ <string name="lock_to_app_exit" msgid="8598219838213787430">"မျက်နှာပြင် ပင်ထိုးမှု ဖြတ်လိုက်ပြီ"</string>
+ <string name="lock_to_app_use_screen_lock" msgid="5732663305876339596">"ပင်ထိုးမှုကို မဖြုတ်မီမှာ %1$sကို မေးကြည့်ပါ"</string>
<string name="lock_to_app_unlock_pin" msgid="7908385370846820001">"PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="7763071104790758405">"သော့ဖွင့် ပုံစံဒီဇိုင်း"</string>
<string name="lock_to_app_unlock_password" msgid="795224196583495868">"စကားဝှက်"</string>
- <!-- no translation found for battery_saver_description (725676363406667978) -->
- <skip />
- <!-- no translation found for downtime_condition_summary (8761776337475705749) -->
- <skip />
+ <string name="battery_saver_description" msgid="725676363406667978">"ဘက်ထရီ သက်တမ်းကို တိုးပေးရန်၊ ဘက်ထရီ ချွေတာသူက သင့်ကိရိယာ၏ လုပ်ကိုင်မှုများကို လျှော့ချလျက် တုန်ခါမှု နှင့် နောက်ခံ ဒေတာ အများစုကို ကန့်သတ်ပေးသည်။ စင့်ကို အားကိုးကြရသည့် အီးမေးလ်၊ စာပို့စနစ်၊ နှင့် အခြား appများသည် သင်က ၎င်းတို့ကို မဖွင့်မချင်း မွမ်းမံဖြစ်မည် မဟုတ်ပါ။ \n\nသင်၏ ကိရိယာက အားသွင်း နေချိန်မှာ ဘက်ထရီ ချွေတာသူကို အလိုအလျောက် ပိတ်ထားမည်။"</string>
+ <string name="downtime_condition_summary" msgid="8761776337475705749">"သင်၏ စက်ရပ်ချိန် <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> မှာ ပြီးဆုံးသည့် အထိ။"</string>
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 0073ad1..db5c292 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Trykk for å deaktivere USB-feilsøking."</string>
<string name="select_input_method" msgid="8547250819326693584">"Endre tastatur"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Velg tastatur"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Fysisk tastatur"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Maskinvare"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Velg tastaturoppsett"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Trykk for å velge et tastaturoppsett"</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index eb9c066..cee862a 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1360,7 +1360,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB डिबग गर्ने असक्षम पार्न छुनुहोस्।"</string>
<string name="select_input_method" msgid="8547250819326693584">"कुञ्जीपाटी परिवर्तन गर्नुहोस्"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"कीबोर्ड छान्नुहोस्"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"भौतिक किबोर्ड"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"हार्डवेयर"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"किबोर्ड रूपरेखा चयन गर्नुहोस्"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"किबोर्ड रूपरेखा चयन गर्न टच गर्नुहोस्।"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 5b0c5f4..dc6c38c 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Tik om USB-foutopsporing uit te schakelen."</string>
<string name="select_input_method" msgid="8547250819326693584">"Toetsenbord wijzigen"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Toetsenborden kiezen"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Fysiek toetsenbord"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardware"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Toetsenbordindeling selecteren"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Tik om een toetsenbordindeling te selecteren."</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 65616c2..505bd11 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Dotknij, aby wyłączyć debugowanie USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Zmień klawiaturę"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Wybierz klawiatury"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Klawiatura fizyczna"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Sprzęt"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Wybierz układ klawiatury"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Kliknij, by wybrać układ klawiatury."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index b54d6c0..7bcbd1f 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Toque para desativar a depuração USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Alterar teclado"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Escolher teclados"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Teclado físico"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardware"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selecionar esquema de teclado"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Toque para selecionar um esquema de teclado."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 5c3e589..9674c78 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Toque para desativar a depuração do USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Alterar teclado"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Escolher teclados"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Teclado físico"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardware"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selecione o layout de teclado"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Toque para selecionar um layout de teclado."</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 325c0a9..74c9084 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1354,7 +1354,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Atingeţi pentru a dezactiva depanarea USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Schimbați tastatura"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Alegeți tastaturi"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Tastatură fizică"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardware"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selectaţi aspectul tastaturii"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Atingeţi pentru a selecta un aspect de tastatură."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 632bdda..d4872bb 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Нажмите, чтобы отключить отладку по USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Выбор раскладки"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Выбрать раскладку"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Физическая клавиатура"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Аппаратура"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Выберите раскладку клавиатуры"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Нажмите, чтобы выбрать раскладку клавиатуры."</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 8db3349..230fbe7 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1355,7 +1355,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB නිදොස්කරණය අබල කිරීමට ස්පර්ශ කරන්න."</string>
<string name="select_input_method" msgid="8547250819326693584">"යතුරු පුවරු වෙනස් කිරීම"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"යතුරු පුවරු තෝරන්න"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"භෞතික යතුරු පුවරුව"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"දෘඨාංග"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"යතුරු පුවරුවට පිරිසැලැස්ම තෝරන්න"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"යතුරු පුවරුවට පිරිසැලැස්මක් තේරීමට ස්පර්ශ කරන්න."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index e561d9b..f37e911 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Dotknutím zakážete ladenie USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Zmeniť klávesnicu"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Vybrať klávesnice"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Fyzická klávesnica"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardvér"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Zvoľte rozloženie klávesnice"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Dotykom zvoľte rozloženie klávesnice."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 462dc19..a9e6011 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Dotaknite se, če želite onemogočiti iskanje in odpravljanje napak prek vrat USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Sprememba tipkovnice"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Izbira tipkovnic"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Fizična tipkovnica"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Strojna oprema"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Izberite razporeditev tipkovnice"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Dotaknite se, da izberete razporeditev tipkovnice"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index c11e1ff..7e139c7 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Додирните да бисте онемогућили отклањање грешака са USB-а."</string>
<string name="select_input_method" msgid="8547250819326693584">"Промените тастатуру"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Изаберите тастатуре"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Физичка тастатура"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Хардвер"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Избор распореда тастатуре"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Додирните да бисте изабрали распоред тастатуре."</string>
@@ -1448,7 +1449,7 @@
<string name="submit" msgid="1602335572089911941">"Пошаљи"</string>
<string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Режим рада у аутомобилу је омогућен"</string>
<string name="car_mode_disable_notification_message" msgid="8035230537563503262">"Додирните да бисте изашли из режима рада у аутомобилу."</string>
- <string name="tethered_notification_title" msgid="3146694234398202601">"Активно повезивање са Интернетом преко мобилног уређаја или врућа тачка"</string>
+ <string name="tethered_notification_title" msgid="3146694234398202601">"Активно повезивање са интернетом преко мобилног уређаја или врућа тачка"</string>
<string name="tethered_notification_message" msgid="6857031760103062982">"Додирните да бисте подесили."</string>
<string name="back_button_label" msgid="2300470004503343439">"Назад"</string>
<string name="next_button_label" msgid="1080555104677992408">"Next"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 9115c06..81625e7 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Tryck om du vill inaktivera USB-felsökning."</string>
<string name="select_input_method" msgid="8547250819326693584">"Byt tangentbord"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Välj tangentbord"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Fysiskt tangentbord"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Maskinvara"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Välj en tangentbordslayout"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Välj en tangentbordslayout genom att trycka."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 177730c..be1e0e6 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Gusa ili uzime utatuaji wa USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Badilisha kibodi"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Chagua kibodi"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Kibodi halisi"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Maunzi"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Teua mpangilio wa kibodi"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Gusa ili kuchagua mpangilio wa kibodi."</string>
diff --git a/core/res/res/values-sw720dp/dimens.xml b/core/res/res/values-sw720dp/dimens.xml
index 21235ec..2317d1f 100644
--- a/core/res/res/values-sw720dp/dimens.xml
+++ b/core/res/res/values-sw720dp/dimens.xml
@@ -35,9 +35,9 @@
<item type="dimen" name="dialog_fixed_height_minor">90%</item>
<!-- The width that is used when creating thumbnails of applications. -->
- <dimen name="thumbnail_width">640dp</dimen>
+ <dimen name="thumbnail_width">420dp</dimen>
<!-- The height that is used when creating thumbnails of applications. -->
- <dimen name="thumbnail_height">640dp</dimen>
+ <dimen name="thumbnail_height">420dp</dimen>
<!-- Preference activity, vertical padding for the header list -->
<dimen name="preference_screen_header_vertical_padding">32dp</dimen>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index a72e813..14a2dfc 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB பிழைத்திருத்தத்தை முடக்க, தொடவும்."</string>
<string name="select_input_method" msgid="8547250819326693584">"விசைப்பலகையை மாற்று"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"விசைப்பலகைகளைத் தேர்வுசெய்க"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"கைமுறை விசைப்பலகை"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"வன்பொருள்"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"விசைப்பலகைத் தளவமைப்பைத் தேர்ந்தெடுக்கவும்"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"விசைப்பலகைத் தளவமைப்பைத் தேர்ந்தெடுக்க தொடவும்."</string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index e7e24f7..9af8b76 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB డీబగ్గింగ్ను నిలిపివేయడానికి తాకండి."</string>
<string name="select_input_method" msgid="8547250819326693584">"కీబోర్డ్ను మార్చు"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"కీబోర్డ్లను ఎంచుకోండి"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"భౌతిక కీబోర్డ్"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"హార్డ్వేర్"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"కీబోర్డ్ లేఅవుట్ను ఎంచుకోండి"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"కీబోర్డ్ లేఅవుట్ను ఎంచుకోవడానికి తాకండి."</string>
diff --git a/core/res/res/values-television/themes.xml b/core/res/res/values-television/themes.xml
index a501fac..377982a 100644
--- a/core/res/res/values-television/themes.xml
+++ b/core/res/res/values-television/themes.xml
@@ -20,6 +20,8 @@
<style name="Theme.Holo.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
<style name="Theme.Material.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
<style name="Theme.Material.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
+ <style name="Theme.Material.Settings.Dialog.Alert" parent="Theme.Leanback.Settings.Dialog.Alert" />
<style name="Theme.Material.Dialog" parent="Theme.Leanback.Dialog" />
<style name="Theme.Material.Light.Dialog" parent="Theme.Leanback.Light.Dialog" />
+ <style name="Theme.Material.Settings.Dialog" parent="Theme.Leanback.Settings.Dialog" />
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index b4a5fbe..87dbb13 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"แตะเพื่อปิดใช้งานการแก้ไขข้อบกพร่องของ USB"</string>
<string name="select_input_method" msgid="8547250819326693584">"เปลี่ยนแป้นพิมพ์"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"เลือกแป้นพิมพ์"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"แป้นพิมพ์บนเครื่อง"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"ฮาร์ดแวร์"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"เลือกรูปแบบแป้นพิมพ์"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"แตะเพื่อเลือกรูปแบบแป้นพิมพ์"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index bdb5172..8dd86b3 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Pindutin upang huwag paganahin ang pag-debug ng USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Baguhin ang keyboard"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Piliin ang mga keyboard"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Aktwal na keyboard"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Hardware"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Pumili ng layout ng keyboard"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Pindutin upang pumili ng layout ng keyboard."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 8f32ec5..7f80ea1 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB hata ayıklama özelliğini devre dışı bırakmak için dokunun."</string>
<string name="select_input_method" msgid="8547250819326693584">"Klavyeyi değiştirin"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Klavyeleri seç"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Fiziksel klavye"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Donanım"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Klavye düzeni seçin"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Bir klavye düzeni seçmek için dokunun."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index f7583d6..dd716b0 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Торкніться, щоб вимкнути налагодження USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Змінити клавіатуру"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Вибрати клавіатури"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Фізична клавіатура"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Обладнання"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Виберіть розкладку клавіатури"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Торкніться, щоб вибрати розкладку клавіатури."</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 99534fd9..940ea9f 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB ڈیبگنگ کو غیر فعال کرنے کیلئے ٹچ کریں۔"</string>
<string name="select_input_method" msgid="8547250819326693584">"کی بورڈ تبدیل کریں"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"کی بورڈز منتخب کریں"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"طبعی کی بورڈ"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"ہارڈ ویئر"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"کی بورڈ کا خاکہ منتخب کریں"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"ایک کی بورڈ کا خاکہ منتخب کرنے کیلئے چھوئیں۔"</string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 206b2fc5..136e92c 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB orqali sozlashni o‘chirib qo‘yish uchun bosing."</string>
<string name="select_input_method" msgid="8547250819326693584">"Klaviaturani o‘zgartirish"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Klaviaturani tanlash"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Tashqi tugmatag"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Qurilma"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Tugmalar tartibini tanlash"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Tugmalar tartibini tanlash uchun bosing."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 7428d89..e6fb44e 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Chạm để vô hiệu hóa gỡ lỗi USB."</string>
<string name="select_input_method" msgid="8547250819326693584">"Thay đổi bàn phím"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Chọn bàn phím"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Bàn phím thực"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"Phần cứng"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Chọn bố cục bàn phím"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Chạm để chọn bố cục bàn phím."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 557f709..3e69115 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"触摸可停用USB调试。"</string>
<string name="select_input_method" msgid="8547250819326693584">"更改键盘"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"选择键盘"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"物理键盘"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"硬件"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"选择键盘布局"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"触摸可选择键盘布局。"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 1dfcad3..2879033 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"輕觸即可停用 USB 偵錯。"</string>
<string name="select_input_method" msgid="8547250819326693584">"變更鍵盤"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"選擇鍵盤"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"實體鍵盤"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"硬件"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"選取鍵盤配置"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"輕觸即可選取鍵盤配置。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index ec5a424..a8a736a 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"輕觸即可停用 USB 偵錯。"</string>
<string name="select_input_method" msgid="8547250819326693584">"變更鍵盤"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"選擇鍵盤"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"實體鍵盤"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"硬體"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"選取鍵盤配置"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"輕觸即可選取鍵盤配置。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 2c461d2..16ac1d0 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1352,7 +1352,8 @@
<string name="adb_active_notification_message" msgid="1016654627626476142">"Thinta ukwenza ukuthi ukudibhaga kwe-USB kungasebenzi."</string>
<string name="select_input_method" msgid="8547250819326693584">"Shintsha ikhibhodi"</string>
<string name="configure_input_methods" msgid="4769971288371946846">"Khetha amakhibhodi"</string>
- <string name="use_physical_keyboard" msgid="6203112478095117625">"Ukwakheka kwekhibhodi"</string>
+ <!-- no translation found for show_ime (9157568568695230830) -->
+ <skip />
<string name="hardware" msgid="7517821086888990278">"I-Hardware"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Khetha isendlalelo sekhibhodi"</string>
<string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Thinta ukuze ukhethe isendlalelo sekhibhodi."</string>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 327782d..f843d1f 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -506,12 +506,24 @@
<!-- Used in LocalePicker -->
<string-array translatable="false" name="special_locale_codes">
+ <!-- http://b/17150708 - ensure that the list of languages says "Arabic"
+ rather than "Arabic (Egypt)". If you're an OEM supporting multiple
+ Arabic locales, you should remove this entry so that ar_EG is shown
+ as "Arabic (Egypt)" in Settings. -->
+ <item>ar_EG</item>
+
<item>zh_CN</item>
<item>zh_TW</item>
</string-array>
<!-- Used in LocalePicker -->
<string-array translatable="false" name="special_locale_names">
+ <!-- http://b/17150708 - ensure that the list of languages says "Arabic"
+ rather than "Arabic (Egypt)". If you're an OEM supporting multiple
+ Arabic locales, you should remove this entry so that ar_EG is shown
+ as "Arabic (Egypt)" in Settings. -->
+ <item>العربية</item>
+
<item>中文 (简体)</item>
<item>中文 (繁體)</item>
</string-array>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index f9ea5d8..3524636 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -517,6 +517,10 @@
{@link android.view.Window#setAllowExitTransitionOverlap(boolean)}. -->
<attr name="windowAllowExitTransitionOverlap" format="boolean"/>
+ <!-- Indicates whether or not shared elements should use an overlay
+ during transitions. The default value is true. -->
+ <attr name="windowSharedElementsUseOverlay" format="boolean"/>
+
<!-- Internal layout used internally for window decor -->
<attr name="windowActionBarFullscreenDecorLayout" format="reference" />
@@ -1005,6 +1009,9 @@
<!-- The color applied to framework buttons in their normal state. -->
<attr name="colorButtonNormal" format="color" />
+ <!-- The color applied to framework switch thumbs in their normal state. -->
+ <attr name="colorSwitchThumbNormal" format="color" />
+
<!-- ================== -->
<!-- Hardware rendering -->
<!-- ================== -->
@@ -1836,6 +1843,10 @@
{@link android.view.Window#setAllowExitTransitionOverlap(boolean)}. -->
<attr name="windowAllowExitTransitionOverlap"/>
+ <!-- Indicates whether or not shared elements should use an overlay
+ during transitions. The default value is true. -->
+ <attr name="windowSharedElementsUseOverlay"/>
+
<!-- Flag indicating whether this Window is responsible for drawing the background for the
system bars. If true and the window is not floating, the system bars are drawn with a
transparent background and the corresponding areas in this window are filled with the
@@ -2513,6 +2524,19 @@
result to valid color values. Saturate(S + D) -->
<enum name="add" value="16" />
</attr>
+
+ <!-- ViewOutlineProvider used to determine the View's Outline. -->
+ <attr name="outlineProvider">
+ <!-- Default, background drawable-driven outline. -->
+ <enum name="background" value="0" />
+ <!-- No outline provider. -->
+ <enum name="none" value="1" />
+ <!-- Generates an opaque outline for the bounds of the view. -->
+ <enum name="bounds" value="2" />
+ <!-- Generates an opaque outline for the padded bounds of the view. -->
+ <enum name="paddedBounds" value="3" />
+ </attr>
+
</declare-styleable>
<!-- Attributes that can be assigned to a tag for a particular View. -->
@@ -3786,13 +3810,17 @@
<attr name="textColorLink" />
<!-- Present the text in ALL CAPS. This may use a small-caps form when available. -->
<attr name="textAllCaps" format="boolean" />
- <!-- Place a shadow of the specified color behind the text. -->
+ <!-- Place a blurred shadow of text underneath the text, drawn with the
+ specified color. The text shadow produced does not interact with
+ properties on View that are responsible for real time shadows,
+ {@link android.R.styleable#View_elevation elevation} and
+ {@link android.R.styleable#View_translationZ translationZ}. -->
<attr name="shadowColor" format="color" />
- <!-- Horizontal offset of the shadow. -->
+ <!-- Horizontal offset of the text shadow. -->
<attr name="shadowDx" format="float" />
- <!-- Vertical offset of the shadow. -->
+ <!-- Vertical offset of the text shadow. -->
<attr name="shadowDy" format="float" />
- <!-- Radius of the shadow. -->
+ <!-- Blur radius of the text shadow. -->
<attr name="shadowRadius" format="float" />
<!-- Elegant text height, especially for less compacted complex script text. -->
<attr name="elegantTextHeight" format="boolean" />
@@ -3933,13 +3961,17 @@
<!-- Set an input filter to constrain the text length to the
specified number. -->
<attr name="maxLength" format="integer" min="0" />
- <!-- Place a shadow of the specified color behind the text. -->
+ <!-- Place a blurred shadow of text underneath the text, drawn with the
+ specified color. The text shadow produced does not interact with
+ properties on View that are responsible for real time shadows,
+ {@link android.R.styleable#View_elevation elevation} and
+ {@link android.R.styleable#View_translationZ translationZ}. -->
<attr name="shadowColor" />
- <!-- Horizontal offset of the shadow. -->
+ <!-- Horizontal offset of the text shadow. -->
<attr name="shadowDx" />
- <!-- Vertical offset of the shadow. -->
+ <!-- Vertical offset of the text shadow. -->
<attr name="shadowDy" />
- <!-- Radius of the shadow. -->
+ <!-- Blur radius of the text shadow. -->
<attr name="shadowRadius" />
<attr name="autoLink" />
<!-- If set to false, keeps the movement method from being set
@@ -5576,6 +5608,19 @@
</attr>
</declare-styleable>
+ <!-- Use <code>changeTransform</code> as the root tag of the XML resource that
+ describes a {@link android.transition.ChangeTransform} transition. -->
+ <declare-styleable name="ChangeTransform">
+ <!-- A parent change should use an overlay or affect the transform of the
+ transitionining View. Default is true. Corresponds to
+ {@link android.transition.ChangeTransform#setReparentWithOverlay(boolean)}. -->
+ <attr name="reparentWithOverlay" format="boolean"/>
+
+ <!-- Tells ChangeTransform to track parent changes. Default is true. Corresponds to
+ {@link android.transition.ChangeTransform#setReparent(boolean)}. -->
+ <attr name="reparent" format="boolean"/>
+ </declare-styleable>
+
<!-- Use <code>transitionManager</code> as the root tag of the XML resource that
describes a {@link android.transition.TransitionManager
TransitionManager}. -->
@@ -7279,7 +7324,7 @@
<attr name="colorPrimary" />
</declare-styleable>
- <!-- Use <code>tv-input</code> as the root tag of the XML resource that describes an
+ <!-- Use <code>tv-input</code> as the root tag of the XML resource that describes a
{@link android.media.tv.TvInputService}, which is referenced from its
{@link android.media.tv.TvInputService#SERVICE_META_DATA} meta-data entry.
Described here are the attributes that can be included in that tag. -->
@@ -7294,6 +7339,36 @@
<attr name="tvContentRatingDescription" format="reference" />
</declare-styleable>
+ <!-- Attributes that can be used with <code>rating-system-definition</code> tags inside of the
+ XML resource that describes TV content rating of a
+ {@link android.media.tv.TvInputService}, which is referenced from
+ {@link android.R.attr#tvContentRatingDescription}. -->
+ <declare-styleable name="RatingSystemDefinition">
+ <!-- The unique name of the content rating system. -->
+ <attr name="name" />
+ <!-- The title of the content rating system which is shown to the user. -->
+ <attr name="title" />
+ <!-- The short description of the content rating system. -->
+ <attr name="description" />
+ <!-- The country associated with the content rating system. -->
+ <attr name="country" format="string" />
+ </declare-styleable>
+
+ <!-- Attributes that can be used with <code>rating-definition</code> tags inside of the XML
+ resource that describes TV content rating of a {@link android.media.tv.TvInputService},
+ which is referenced from {@link android.R.attr#tvContentRatingDescription}. -->
+ <declare-styleable name="RatingDefinition">
+ <!-- The unique name of the content rating. -->
+ <attr name="name" />
+ <!-- The title of the content rating which is shown to the user. -->
+ <attr name="title" />
+ <!-- The short description of the content rating. -->
+ <attr name="description" />
+ <!-- The age associated with the content rating. The content of this rating is suitable for
+ people of this age or above. -->
+ <attr name="ageHint" format="integer" />
+ </declare-styleable>
+
<declare-styleable name="ResolverDrawerLayout">
<attr name="maxWidth" />
<attr name="maxCollapsedHeight" format="dimension" />
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index d538352..0360460 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -127,6 +127,7 @@
<drawable name="notification_template_icon_bg">#3333B5E5</drawable>
<drawable name="notification_template_icon_low_bg">#0cffffff</drawable>
+ <drawable name="notification_template_divider">#29000000</drawable>
<color name="notification_icon_bg_color">#ff9e9e9e</color>
<color name="notification_action_legacy_color_filter">#ff555555</color>
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index ccbb8bc..2348951 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -25,6 +25,11 @@
<color name="button_material_dark">#ff5a595b</color>
<color name="button_material_light">#ffd6d7d7</color>
+ <color name="switch_thumb_normal_material_dark">#ffbdbdbd</color>
+ <color name="switch_thumb_normal_material_light">#fff1f1f1</color>
+ <color name="switch_thumb_disabled_material_dark">#ff616161</color>
+ <color name="switch_thumb_disabled_material_light">#ffbdbdbd</color>
+
<color name="bright_foreground_material_dark">@color/white</color>
<color name="bright_foreground_material_light">@color/black</color>
<!-- White 50% -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a59a489..df7268f 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1371,6 +1371,13 @@
may have a specific value set in an overlay config.xml file. -->
<integer name="config_mobile_mtu">1500</integer>
+ <!-- Configure mobile tcp buffer sizes in the form:
+ rat-name:rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max
+ If no value is found for the rat-name in use, the system default will be applied.
+ -->
+ <string-array name="config_mobile_tcp_buffers">
+ </string-array>
+
<!-- Whether WiFi display is supported by this device.
There are many prerequisites for this feature to work correctly.
Here are a few of them:
@@ -1668,4 +1675,6 @@
Examples: <item>311480;prefix</item> <item>310260;suffix</item>
-->
<string-array translatable="false" name="no_ems_support_sim_operators" />
+
+ <bool name="config_auto_attach_data_on_creation">true</bool>
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index d170fd4..6fd2bb1 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -19,9 +19,9 @@
-->
<resources>
<!-- The width that is used when creating thumbnails of applications. -->
- <dimen name="thumbnail_width">256dp</dimen>
+ <dimen name="thumbnail_width">192dp</dimen>
<!-- The height that is used when creating thumbnails of applications. -->
- <dimen name="thumbnail_height">256dp</dimen>
+ <dimen name="thumbnail_height">192dp</dimen>
<!-- The standard size (both width and height) of an application icon that
will be displayed in the app launcher and elsewhere. -->
<dimen name="app_icon_size">48dip</dimen>
@@ -215,17 +215,26 @@
<dimen name="action_bar_stacked_tab_max_width">180dp</dimen>
<!-- Size of notification text (see TextAppearance.StatusBar.EventContent) -->
- <dimen name="notification_text_size">13sp</dimen>
+ <dimen name="notification_text_size">14sp</dimen>
<!-- Size of notification text titles (see TextAppearance.StatusBar.EventContent.Title) -->
<dimen name="notification_title_text_size">16sp</dimen>
<!-- Size of smaller notification text (see TextAppearance.StatusBar.EventContent.Line2, Info, Time) -->
<dimen name="notification_subtext_size">12sp</dimen>
- <!-- 8dp at the top/bottom of the notification view -->
- <dimen name="notification_vert_pad">10dp</dimen>
+ <!-- Top padding for notifications in the standard layout. -->
+ <dimen name="notification_top_pad">10dp</dimen>
- <!-- Replacement for @dimen/notification_vert_pad when the text is large -->
- <dimen name="notification_large_font_vert_pad">3dp</dimen>
+ <!-- Top padding for notifications when narrow (i.e. it has 3 lines) -->
+ <dimen name="notification_top_pad_narrow">4dp</dimen>
+
+ <!-- Top padding for notification when text is large -->
+ <dimen name="notification_top_pad_large_text">5dp</dimen>
+
+ <!-- Top padding for notification when text is large and narrow (i.e. it has 3 lines -->
+ <dimen name="notification_top_pad_large_text_narrow">-4dp</dimen>
+
+ <!-- Padding for notification icon when drawn with circle around it -->
+ <dimen name="notification_large_icon_circle_padding">11dp</dimen>
<!-- Keyguard dimensions -->
<!-- TEMP -->
@@ -374,7 +383,6 @@
<dimen name="datepicker_year_label_height">64dp</dimen>
<dimen name="datepicker_year_label_text_size">22dp</dimen>
<dimen name="datepicker_component_width">270dp</dimen>
- <dimen name="datepicker_selected_calendar_layout_height">155dp</dimen>
<dimen name="datepicker_selected_date_day_size">75dp</dimen>
<dimen name="datepicker_selected_date_month_size">30dp</dimen>
<dimen name="datepicker_selected_date_year_size">30dp</dimen>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index c64e910..4c59f73 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -85,4 +85,6 @@
<item type="id" name="scene_layoutid_cache" />
<item type="id" name="mask" />
<item type="id" name="transitionPosition" />
+ <item type="id" name="transitionTransform" />
+ <item type="id" name="parentMatrix" />
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 7ade51d..f2466f7 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2272,6 +2272,12 @@
<public type="attr" name="inset" />
<public type="attr" name="letterSpacing" />
<public type="attr" name="fontFeatureSettings" />
+ <public type="attr" name="outlineProvider" />
+ <public type="attr" name="ageHint" />
+ <public type="attr" name="country" />
+ <public type="attr" name="windowSharedElementsUseOverlay" />
+ <public type="attr" name="reparent" />
+ <public type="attr" name="reparentWithOverlay" />
<public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 78ba738..bbbe1ae 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3958,9 +3958,9 @@
<string name="permission_request_notification_with_subtitle">Permission requested\nfor account <xliff:g id="account" example="foo@gmail.com">%s</xliff:g>.</string>
<!-- Message to show when an intent automatically switches users into the personal profile. -->
- <string name="forward_intent_to_owner">You\'re using this app in your personal space</string>
+ <string name="forward_intent_to_owner">You\'re using this app outside of your work profile</string>
<!-- Message to show when an intent automatically switches users into a work profile. -->
- <string name="forward_intent_to_work">You\'re using this app in your work space</string>
+ <string name="forward_intent_to_work">You\'re using this app in your work profile</string>
<!-- Label to show for a service that is running because it is an input method. -->
<string name="input_method_binding_label">Input method</string>
@@ -4325,7 +4325,7 @@
<!-- Text for the toast that is shown when the user clicks on a launcher that
doesn't support the work profile. [CHAR LIMIT=100] -->
- <string name="activity_resolver_work_profiles_support">%1$s doesn\'t support work profile.</string>
+ <string name="activity_resolver_work_profiles_support">%1$s doesn\'t support work profile</string>
<!-- Name of the default audio route for tablets when nothing
is connected to a headphone or other wired audio output jack. [CHAR LIMIT=50] -->
@@ -4821,7 +4821,7 @@
<string name="deleted_key"><xliff:g id="key" example="4">%1$s</xliff:g> deleted</string>
<!--
- Used to wrap a label for content description for a managed profile, e.g. "Work Email" instead
+ Used to wrap a label for content description for a work profile, e.g. "Work Email" instead
of email when there are two email apps.
[CHAR LIMIT=20]
-->
@@ -4859,667 +4859,12 @@
<!-- Exting lock-to-app indication. -->
<string name="lock_to_app_exit">Screen unpinned</string>
- <!-- Lock-to-app checkbox for lock on exit -->
- <string name="lock_to_app_use_screen_lock">Ask for %1$s before unpinning</string>
-
<!-- Lock-to-app unlock pin string -->
- <string name="lock_to_app_unlock_pin">PIN</string>
+ <string name="lock_to_app_unlock_pin">Ask for PIN before unpinning</string>
<!-- Lock-to-app unlock pattern string -->
- <string name="lock_to_app_unlock_pattern">unlock pattern</string>
+ <string name="lock_to_app_unlock_pattern">Ask for unlock pattern before unpinning</string>
<!-- Lock-to-app unlock password string -->
- <string name="lock_to_app_unlock_password">password</string>
-
- <!-- Range specific TV content rating system strings for AM TV -->
- <string name="display_name_amtvrs" translatable="false">AM-TV-RS</string>
- <string name="description_amtvrs" translatable="false">Range specific TV content rating system strings for Armenia</string>
- <string name="display_name_amtvrs_y" translatable="false">Y</string>
- <string name="display_name_amtvrs_y7" translatable="false">Y7</string>
- <string name="display_name_amtvrs_ga" translatable="false">GA</string>
- <string name="display_name_amtvrs_tw" translatable="false">TW</string>
- <string name="display_name_amtvrs_t" translatable="false">T</string>
- <string name="display_name_amtvrs_a" translatable="false">A</string>
- <string name="description_amtvrs_y" translatable="false">Suitable for ages 2-11</string>
- <string name="description_amtvrs_y7" translatable="false">Suitable for ages 7-16</string>
- <string name="description_amtvrs_ga" translatable="false">Suitable for general audiences</string>
- <string name="description_amtvrs_tw" translatable="false">Suitable for teens ages 9 and up</string>
- <string name="description_amtvrs_t" translatable="false">Suitable for teens ages 12 and up</string>
- <string name="description_amtvrs_a" translatable="false">Suitable only for adults ages 18 and up</string>
-
- <!-- Age specific TV content rating system strings for AM TV -->
- <string name="display_name_amtvas" translatable="false">AM-TV-AS</string>
- <string name="description_amtvas" translatable="false">Age specific TV content rating system strings for Armenia</string>
- <string name="display_name_amtvas_ec" translatable="false">EC</string>
- <string name="display_name_amtvas_e" translatable="false">E</string>
- <string name="display_name_amtvas_e9" translatable="false">E9</string>
- <string name="display_name_amtvas_t" translatable="false">T</string>
- <string name="display_name_amtvas_m" translatable="false">M</string>
- <string name="display_name_amtvas_ao" translatable="false">AO</string>
- <string name="description_amtvas_ec" translatable="false">Suitable for ages 2 and up</string>
- <string name="description_amtvas_e" translatable="false">Suitable for ages 5 and up</string>
- <string name="description_amtvas_e9" translatable="false">Suitable for ages 9 and up</string>
- <string name="description_amtvas_t" translatable="false">Suitable for ages 12 and up</string>
- <string name="description_amtvas_m" translatable="false">Suitable for ages 16 and up</string>
- <string name="description_amtvas_ao" translatable="false">Suitable for ages 17 and up</string>
-
- <!-- TV content rating system strings for AR TV -->
- <string name="display_name_artv" translatable="false">AR-TV</string>
- <string name="display_name_artv_all" translatable="false">Apto para todo público</string>
- <string name="display_name_artv_13" translatable="false">Apto para mayores de 13 años</string>
- <string name="display_name_artv_16" translatable="false">Apto para mayores de 16 años</string>
- <string name="display_name_artv_18" translatable="false">Apto para mayores de 18 años</string>
- <string name="description_artv_all" translatable="false">Suitable for all audiences. Programs may contain mild violence, language and mature situations</string>
- <string name="description_artv_13" translatable="false">Suitable for ages 13 and up. Programs may contain mild to moderate language and mild violence and sexual references</string>
- <string name="description_artv_16" translatable="false">Suitable for ages 16 and up. Programs may contain more intensive violence and coarse language, partial nudity and moderate sexual references</string>
- <string name="description_artv_18" translatable="false">Suitable for mature audiences only. Programs contain strong violence, coarse language and explicit sexual references</string>
-
- <!-- TV content rating system strings for AU TV -->
- <string name="display_name_autv" translatable="false">Australian TV Classification</string>
- <string name="display_name_autv_ctc" translatable="false">CTC</string>
- <string name="display_name_autv_g" translatable="false">G</string>
- <string name="display_name_autv_pg" translatable="false">PG</string>
- <string name="display_name_autv_m" translatable="false">M</string>
- <string name="display_name_autv_ma15" translatable="false">MA 15+</string>
- <string name="display_name_autv_r18" translatable="false">R 18+</string>
- <string name="display_name_autv_x18" translatable="false">X 18+</string>
- <string name="description_autv_ctc" translatable="false">This has advertising approval, but is not yet classified</string>
- <string name="description_autv_g" translatable="false">The content is very mild in impact, and suitable for everyone</string>
- <string name="description_autv_pg" translatable="false">The content is mild in impact, but it may contain content that children find confusing or upsetting and may require the guidance or parents and guardians</string>
- <string name="description_autv_m" translatable="false">The content is moderate in impact, and it is recommended for teenagers aged 15 years and over</string>
- <string name="description_autv_ma15" translatable="false">The content is strong in impact, and it is legally restricted to persons 15 years and over</string>
- <string name="description_autv_r18" translatable="false">The content is high in impact, and it is restricted to adults</string>
- <string name="description_autv_x18" translatable="false">The content is restricted to adults. This classification is a special and legally restricted category which contains only sexually explicit content</string>
-
- <!-- TV content rating system strings for BG TV -->
- <string name="display_name_bgtv" translatable="false">BG-TV</string>
- <string name="display_name_bgtv_a" translatable="false">A</string>
- <string name="display_name_bgtv_b" translatable="false">B</string>
- <string name="display_name_bgtv_c" translatable="false">C</string>
- <string name="display_name_bgtv_d" translatable="false">D</string>
- <string name="display_name_bgtv_x" translatable="false">X</string>
- <string name="description_bgtv_a" translatable="false">Recommended to children. When the film confirms the ideals of humanism or popularizes the national and world cultures or contributes to upbringing children</string>
- <string name="description_bgtv_b" translatable="false">No restrictive recommendations from the Committee. When the film is in no way contrary to the universal rules of morality in this country, has no restrictive recommendations from the Committee and does not fall in rating A</string>
- <string name="description_bgtv_c" translatable="false">No persons under the age of 12 are admitted unless accompanied by an adult. When the film contains certain erotic scenes or scenes with drinking, taking drugs or stimulants or a few scenes of violence</string>
- <string name="description_bgtv_d" translatable="false">No persons under the age of 16 are admitted. When the film contains quite a number of erotic scenes or scenes with drinking, taking drugs or stimulants or a considerable number of scenes showing violence</string>
- <string name="description_bgtv_x" translatable="false">No persons under the age of 18 are admitted. When the film is naturalistically erotic or shows violence in an ostentatious manner</string>
-
- <!-- TV content rating system strings for BR TV -->
- <string name="display_name_brtv" translatable="false">Brazil Content Rating</string>
- <string name="display_name_brtv_l" translatable="false">Livre</string>
- <string name="display_name_brtv_10" translatable="false">10 anos</string>
- <string name="display_name_brtv_12" translatable="false">12 anos</string>
- <string name="display_name_brtv_14" translatable="false">14 anos</string>
- <string name="display_name_brtv_16" translatable="false">16 anos</string>
- <string name="display_name_brtv_18" translatable="false">18 anos</string>
- <string name="description_brtv_l" translatable="false">Content is suitable for all audiences</string>
- <string name="description_brtv_10" translatable="false">Content suitable for viewers over the age of 10</string>
- <string name="description_brtv_12" translatable="false">Content suitable for viewers over the age of 12</string>
- <string name="description_brtv_14" translatable="false">Content suitable for viewers over the age of 14</string>
- <string name="description_brtv_16" translatable="false">Content suitable for viewers over the age of 16</string>
- <string name="description_brtv_18" translatable="false">Content suitable for viewers over the age of 18</string>
-
- <!-- TV content rating system strings for CA TV -->
- <string name="display_name_catv" translatable="false">Canadian TV Classification System</string>
- <string name="display_name_catv_exempt" translatable="false">Exempt</string>
- <string name="display_name_catv_c" translatable="false">C</string>
- <string name="display_name_catv_c8" translatable="false">C8</string>
- <string name="display_name_catv_g" translatable="false">G</string>
- <string name="display_name_catv_pg" translatable="false">PG</string>
- <string name="display_name_catv_14" translatable="false">14+</string>
- <string name="display_name_catv_18" translatable="false">18+</string>
- <string name="description_catv_exempt" translatable="false">Shows which are exempt from ratings (such as news and sports programming) will not display an on-screen rating at all</string>
- <string name="description_catv_c" translatable="false">Programming suitable for children ages of 2-7 years. No profanity or sexual content of any level allowed. Contains little violence</string>
- <string name="description_catv_c8" translatable="false">Suitable for children ages 8+. Low level violence and fantasy horror is allowed. No foul language is allowed, but occasional "socially offensive and discriminatory" language is allowed if in the context of the story. No sexual content of any level allowed</string>
- <string name="description_catv_g" translatable="false">Suitable for general audiences. Programming suitable for the entire family with mild violence, and mild profanity and/or censored language</string>
- <string name="description_catv_pg" translatable="false">Parental guidance. Moderate violence and moderate profanity is allowed, as is brief nudity and sexual references if important to the context of the story</string>
- <string name="description_catv_14" translatable="false">Programming intended for viewers ages 14 and older. May contain strong violence and strong profanity, and depictions of sexual activity as long as they are within the context of a story</string>
- <string name="description_catv_18" translatable="false">Programming intended for viewers ages 18 and older. May contain explicit violence and sexual activity</string>
-
- <!-- TV content rating system strings for CH TV -->
- <string name="display_name_chtv" translatable="false">CH-TV</string>
- <string name="display_name_chtv_all" translatable="false">All ages</string>
- <string name="display_name_chtv_red" translatable="false">Red rectangle</string>
- <string name="description_chtv_all" translatable="false">This program is suitable for all ages</string>
- <string name="description_chtv_red" translatable="false">This program contains scenes that may hurt sensitive people, therefore the red symbol will be displayed</string>
-
- <!-- TV content rating system strings for CL TV -->
- <string name="display_name_cltv" translatable="false">CL-TV</string>
- <string name="display_name_cltv_i" translatable="false">I</string>
- <string name="display_name_cltv_i7" translatable="false">I7</string>
- <string name="display_name_cltv_i10" translatable="false">I10</string>
- <string name="display_name_cltv_i12" translatable="false">I12</string>
- <string name="display_name_cltv_f" translatable="false">F</string>
- <string name="display_name_cltv_r" translatable="false">R</string>
- <string name="display_name_cltv_a" translatable="false">A</string>
- <string name="description_cltv_i" translatable="false">Programs suitable for all children</string>
- <string name="description_cltv_i7" translatable="false">Programs recommended for children ages 7 or older</string>
- <string name="description_cltv_i10" translatable="false">Programs recommended for children ages 10 or older</string>
- <string name="description_cltv_i12" translatable="false">Programs recommended for children and teens ages 12 or older</string>
- <string name="description_cltv_f" translatable="false">Programs suitable for a general audience, with content appropriate for all ages</string>
- <string name="description_cltv_r" translatable="false">Programs may content not suitable for children not accompanied by an adult</string>
- <string name="description_cltv_a" translatable="false">Programs suitable for adult audiences only (ages 18 or older), may contain coarse language, and sexual or explicit situations</string>
-
- <!-- TV content rating system strings for DE TV -->
- <string name="display_name_detv" translatable="false">DE-TV</string>
- <string name="display_name_detv_all" translatable="false">ab 0 Jahren</string>
- <string name="display_name_detv_12" translatable="false">ab 12 Jahren</string>
- <string name="display_name_detv_16" translatable="false">ab 16 Jahren</string>
- <string name="display_name_detv_18" translatable="false">ab 18 Jahren</string>
- <string name="description_detv_all" translatable="false">The program is suitable for all ages</string>
- <string name="description_detv_12" translatable="false">The program is not suitable for viewers under the age of 12</string>
- <string name="description_detv_16" translatable="false">The program is not suitable for viewers under the age of 16</string>
- <string name="description_detv_18" translatable="false">The program is not suitable for viewers under the age of 18</string>
-
- <!-- TV content rating system strings for DK TV -->
- <string name="display_name_dktv" translatable="false">DK-TV</string>
- <string name="display_name_dktv_g" translatable="false">Green symbol</string>
- <string name="display_name_dktv_y" translatable="false">Yellow symbol</string>
- <string name="display_name_dktv_r" translatable="false">Red symbol</string>
- <string name="display_name_dktv_b" translatable="false">Blue symbol</string>
- <string name="description_dktv_g" translatable="false">programs suitable for all ages</string>
- <string name="description_dktv_y" translatable="false">programs suitable children accompanied by an adult</string>
- <string name="description_dktv_r" translatable="false">programs containing material with more intensive content </string>
- <string name="description_dktv_b" translatable="false">programs containing explicit content and strictly for adults only</string>
-
- <!-- TV content rating system strings for ES TV -->
- <string name="display_name_estv" translatable="false">ES-TV</string>
- <string name="display_name_estv_tp" translatable="false">TP</string>
- <string name="display_name_estv_i" translatable="false">I</string>
- <string name="display_name_estv_7" translatable="false">+7</string>
- <string name="display_name_estv_7i" translatable="false">7I</string>
- <string name="display_name_estv_12" translatable="false">12</string>
- <string name="display_name_estv_16" translatable="false">16</string>
- <string name="display_name_estv_18" translatable="false">18</string>
- <string name="description_estv_tp" translatable="false">Recommended for all ages</string>
- <string name="description_estv_i" translatable="false">Specially recommended for preschoolers and kids</string>
- <string name="description_estv_7" translatable="false">Recommended for people older than 7 years old</string>
- <string name="description_estv_7i" translatable="false">Recommended for kids older than 7 years old</string>
- <string name="description_estv_12" translatable="false">Recommended for people older than 12 years old</string>
- <string name="description_estv_16" translatable="false">Recommended for people older than 16 years old</string>
- <string name="description_estv_18" translatable="false">Recommended for people older than 18 years old</string>
-
- <!-- TV content rating system strings for FI TV -->
- <string name="display_name_fitv" translatable="false">FI-TV</string>
- <string name="display_name_fitv_s" translatable="false">S</string>
- <string name="display_name_fitv_k7" translatable="false">K7</string>
- <string name="display_name_fitv_k12" translatable="false">K12</string>
- <string name="display_name_fitv_k16" translatable="false">K16</string>
- <string name="display_name_fitv_k18" translatable="false">K18</string>
- <string name="description_fitv_s" translatable="false">Allowed at all times</string>
- <string name="description_fitv_k7" translatable="false">Not recommended for children under 7</string>
- <string name="description_fitv_k12" translatable="false">Not recommended for children under 12</string>
- <string name="description_fitv_k16" translatable="false">Not recommended for children under 16</string>
- <string name="description_fitv_k18" translatable="false">Not recommended for children under 18</string>
-
- <!-- TV content rating system strings for FR TV -->
- <string name="display_name_frtv" translatable="false">FR-TV</string>
- <string name="display_name_frtv_all" translatable="false">Les programmes tous publics</string>
- <string name="display_name_frtv_10" translatable="false">Déconseillé aux -10 ans</string>
- <string name="display_name_frtv_12" translatable="false">Déconseillé aux -12 ans</string>
- <string name="display_name_frtv_16" translatable="false">Déconseillé aux -16 ans</string>
- <string name="display_name_frtv_18" translatable="false">Déconseillé aux -18 ans</string>
- <string name="description_frtv_all" translatable="false">Appropriate for all ages</string>
- <string name="description_frtv_10" translatable="false">Not recommended for children under 10</string>
- <string name="description_frtv_12" translatable="false">Not recommended for children under 12</string>
- <string name="description_frtv_16" translatable="false">Not recommended for children under 16</string>
- <string name="description_frtv_18" translatable="false">Not recommended for persons under 18</string>
-
- <!-- TV content rating system strings for GR TV -->
- <string name="display_name_grtv" translatable="false">GR-TV</string>
- <string name="display_name_grtv_all" translatable="false">White rhombus in green background</string>
- <string name="display_name_grtv_10" translatable="false">White circle in blue background</string>
- <string name="display_name_grtv_12" translatable="false">White triangle in orange background</string>
- <string name="display_name_grtv_15" translatable="false">White square in purple background</string>
- <string name="display_name_grtv_18" translatable="false">White X in red background</string>
- <string name="description_grtv_all" translatable="false">Suitable for all ages</string>
- <string name="description_grtv_10" translatable="false">Parental consent suggested</string>
- <string name="description_grtv_12" translatable="false">Required parental consent</string>
- <string name="description_grtv_15" translatable="false">Suitable for minors over the age of 15</string>
- <string name="description_grtv_18" translatable="false">Suitable only for adults profanity before midnight is punishable by fine, except when used in the context of the program</string>
-
- <!-- TV content rating system strings for HK TV -->
- <string name="display_name_hktv" translatable="false">HK-TV</string>
- <string name="display_name_hktv_g" translatable="false">G</string>
- <string name="display_name_hktv_pg" translatable="false">PG</string>
- <string name="display_name_hktv_m" translatable="false">M</string>
- <string name="description_hktv_g" translatable="false">For general audiences</string>
- <string name="description_hktv_pg" translatable="false">Programs are unsuitable for children, parental guidance is recommended</string>
- <string name="description_hktv_m" translatable="false">Programs are recommended only for adult viewers above the age of 18</string>
-
- <!-- TV content rating system strings for HU TV -->
- <string name="display_name_hutv" translatable="false">HU-TV</string>
- <string name="display_name_hutv_u" translatable="false">Unrated</string>
- <string name="display_name_hutv_cf" translatable="false">Children Friendly</string>
- <string name="display_name_hutv_6" translatable="false">6</string>
- <string name="display_name_hutv_12" translatable="false">12</string>
- <string name="display_name_hutv_16" translatable="false">16</string>
- <string name="display_name_hutv_18" translatable="false">18</string>
- <string name="description_hutv_u" translatable="false">Programs can be viewed by any age</string>
- <string name="description_hutv_cf" translatable="false">Programs recommended for children. It is an optional rating, there is no obligation for broadcasters to indicate it</string>
- <string name="description_hutv_6" translatable="false">Programs not recommended for children below the age of 6, may not contain any violence or sexual content</string>
- <string name="description_hutv_12" translatable="false">Programs not recommended for children below the age of 12, may contain light sexual content or explicit language</string>
- <string name="description_hutv_16" translatable="false">Programs not recommended for teens and children below the age of 16, may contain more intensive violence and sexual content</string>
- <string name="description_hutv_18" translatable="false">The program is recommended only for adult viewers (for ages 18 and up), may contain explicit violence and explicit sexual content</string>
-
- <!-- TV content rating system strings for ID TV -->
- <string name="display_name_idtv" translatable="false">ID-TV</string>
- <string name="display_name_idtv_p" translatable="false">P</string>
- <string name="display_name_idtv_a" translatable="false">A</string>
- <string name="display_name_idtv_a_bo" translatable="false">A-BO</string>
- <string name="display_name_idtv_su" translatable="false">SU</string>
- <string name="display_name_idtv_bo" translatable="false">BO</string>
- <string name="display_name_idtv_r" translatable="false">R</string>
- <string name="display_name_idtv_r_bo" translatable="false">R-BO</string>
- <string name="display_name_idtv_d" translatable="false">D</string>
- <string name="description_idtv_p" translatable="false">Suitable for children from ages 2 through 11</string>
- <string name="description_idtv_a" translatable="false">Suitable for teens and children from ages 7 through 16</string>
- <string name="description_idtv_a_bo" translatable="false">Suitable for children ages 5 through 10, with parental guidance or permission</string>
- <string name="description_idtv_su" translatable="false">Suitable for general audiences</string>
- <string name="description_idtv_bo" translatable="false">Parental guidance suggested for ages 5 and under</string>
- <string name="description_idtv_r" translatable="false">Suitable for teens from ages 13 through 17</string>
- <string name="description_idtv_r_bo" translatable="false">Suitable for teens with parental guidance or permission</string>
- <string name="description_idtv_d" translatable="false">Suitable for viewers over 18 and older only</string>
-
- <!-- TV content rating system strings for IE TV -->
- <string name="display_name_ietv" translatable="false">RTÉ programme classifications</string>
- <string name="display_name_ietv_ga" translatable="false">GA</string>
- <string name="display_name_ietv_ch" translatable="false">Ch</string>
- <string name="display_name_ietv_ya" translatable="false">YA</string>
- <string name="display_name_ietv_ps" translatable="false">PS</string>
- <string name="display_name_ietv_ma" translatable="false">MA</string>
- <string name="description_ietv_ga" translatable="false">Suitable for all ages</string>
- <string name="description_ietv_ch" translatable="false">Suitable for children ages 5 to 10, may contain comedic violence or action fantasy violence</string>
- <string name="description_ietv_ya" translatable="false">Suitable for adolescent audiences, may contain thematic elements that would appeal to teenagers</string>
- <string name="description_ietv_ps" translatable="false">Suitable for more mature viewers, more mature themes may be present</string>
- <string name="description_ietv_ma" translatable="false">Most restrictive classification, allowing for heavy subject matter and coarse language</string>
-
- <!-- TV content rating system strings for IL TV -->
- <string name="display_name_iltv" translatable="false">IL-TV</string>
- <string name="display_name_iltv_g" translatable="false">G</string>
- <string name="display_name_iltv_12" translatable="false">12+</string>
- <string name="display_name_iltv_15" translatable="false">15+</string>
- <string name="display_name_iltv_18" translatable="false">18+</string>
- <string name="display_name_iltv_e" translatable="false">E</string>
- <string name="description_iltv_g" translatable="false">General audience; anyone, regardless of age, can view the program, usually news and children\'s programming</string>
- <string name="description_iltv_12" translatable="false">Suitable for teens and children ages 12 and over, no child under 12 are permitted to view the program</string>
- <string name="description_iltv_15" translatable="false">Suitable for teens ages 15 and over, no child under 15 may view the programme</string>
- <string name="description_iltv_18" translatable="false">Suitable for adults only, no minors may view the programme</string>
- <string name="description_iltv_e" translatable="false">Exempt from classification</string>
-
- <!-- TV content rating system strings for IN TV -->
- <string name="display_name_intv" translatable="false">IN-TV</string>
- <string name="display_name_intv_u" translatable="false">U</string>
- <string name="display_name_intv_u/a" translatable="false">U/A</string>
- <string name="display_name_intv_a" translatable="false">A</string>
- <string name="display_name_intv_s" translatable="false">S</string>
- <string name="description_intv_u" translatable="false">Unrestricted public exhibition</string>
- <string name="description_intv_u/a" translatable="false">Unrestricted public exhibition, but with a caution regarding parental guidance to those under 12 years of age</string>
- <string name="description_intv_a" translatable="false">Public exhibition restricted to adults 18 years of age and older only</string>
- <string name="description_intv_s" translatable="false">Public exhibition restricted to members of any profession or any class of persons</string>
-
- <!-- TV content rating system strings for IS TV -->
- <string name="display_name_istv" translatable="false">IS-TV</string>
- <string name="display_name_istv_l" translatable="false">L</string>
- <string name="display_name_istv_7" translatable="false">7</string>
- <string name="display_name_istv_10" translatable="false">10</string>
- <string name="display_name_istv_12" translatable="false">12</string>
- <string name="display_name_istv_14" translatable="false">14</string>
- <string name="display_name_istv_16" translatable="false">16</string>
- <string name="display_name_istv_18" translatable="false">18</string>
- <string name="description_istv_l" translatable="false">Programs suitable for all ages</string>
- <string name="description_istv_7" translatable="false">Programs suitable for ages 7 and older</string>
- <string name="description_istv_10" translatable="false">Programs suitable for ages 10 and older</string>
- <string name="description_istv_12" translatable="false">Programs suitable for ages 12 and older</string>
- <string name="description_istv_14" translatable="false">Programs suitable for ages 14 and older</string>
- <string name="description_istv_16" translatable="false">Programs suitable for ages 16 and older</string>
- <string name="description_istv_18" translatable="false">Programs suitable for ages 18 and older</string>
-
- <!-- TV content rating system strings for KR TV -->
- <string name="display_name_krtv" translatable="false">KR-TV</string>
- <string name="display_name_krtv_all" translatable="false">모든연령시청가</string>
- <string name="display_name_krtv_7" translatable="false">7세이상시청가</string>
- <string name="display_name_krtv_12" translatable="false">12세이상시청가</string>
- <string name="display_name_krtv_15" translatable="false">15세이상시청가</string>
- <string name="display_name_krtv_19" translatable="false">19세이상시청가</string>
- <string name="description_krtv_all" translatable="false">Appropriate for all ages</string>
- <string name="description_krtv_7" translatable="false">May contain material inappropriate for children younger than 7, and parental discretion should be used</string>
- <string name="description_krtv_12" translatable="false">May deemed inappropriate for those younger than 12, and parental discretion should be used</string>
- <string name="description_krtv_15" translatable="false">May be inappropriate for children under 15, and that parental discretion should be used</string>
- <string name="description_krtv_19" translatable="false">For adults only</string>
-
- <!-- TV content rating system strings for MV TV -->
- <string name="display_name_mvtv" translatable="false">MV-TV</string>
- <string name="display_name_mvtv_y" translatable="false">Y</string>
- <string name="display_name_mvtv_g" translatable="false">G</string>
- <string name="display_name_mvtv_pg" translatable="false">PG</string>
- <string name="display_name_mvtv_pg-12" translatable="false">PG-12</string>
- <string name="display_name_mvtv_12" translatable="false">12+</string>
- <string name="display_name_mvtv_15" translatable="false">15+</string>
- <string name="display_name_mvtv_18" translatable="false">18+</string>
- <string name="display_name_mvtv_21" translatable="false">21+</string>
- <string name="display_name_mvtv_x" translatable="false">X</string>
- <string name="description_mvtv_y" translatable="false">Young children</string>
- <string name="description_mvtv_g" translatable="false">General viewing for all ages</string>
- <string name="description_mvtv_pg" translatable="false">Parental guidance is required unaccompanied children</string>
- <string name="description_mvtv_pg-12" translatable="false">Parental guidance is required for children under the age of 12</string>
- <string name="description_mvtv_12" translatable="false">Teens and children aged 12 and older may watch, otherwise restricted</string>
- <string name="description_mvtv_15" translatable="false">Restricted to viewers aged 15 and above</string>
- <string name="description_mvtv_18" translatable="false">Restricted to viewers aged 18 and above</string>
- <string name="description_mvtv_21" translatable="false">Restricted to viewers aged 21 and above</string>
- <string name="description_mvtv_x" translatable="false">Most restrictive classification, only adults ages 25 and above may view</string>
-
- <!-- TV content rating system strings for MX TV -->
- <string name="display_name_mxtv" translatable="false">MX-TV</string>
- <string name="display_name_mxtv_a" translatable="false">A</string>
- <string name="display_name_mxtv_b" translatable="false">B</string>
- <string name="display_name_mxtv_b-15" translatable="false">B-15</string>
- <string name="display_name_mxtv_c" translatable="false">C</string>
- <string name="display_name_mxtv_d" translatable="false">D</string>
- <string name="display_name_mxtv_rc" translatable="false">RC</string>
- <string name="description_mxtv_a" translatable="false">Appropriate for all ages, parental guidance is recommended for children under 7 years</string>
- <string name="description_mxtv_b" translatable="false">Designed for ages 12 and older, may contain some sexual situations, mild violence, and mild language</string>
- <string name="description_mxtv_b-15" translatable="false">Designed for ages 15 and up, slightly more intensive than the \'A\' and \'B\' ratings</string>
- <string name="description_mxtv_c" translatable="false">Designed to be viewed by adults aged 18 or older only, generally more intensive content </string>
- <string name="description_mxtv_d" translatable="false">Designed to be viewed only by mature adults (at least 21 years of age and over), contains extreme content matter</string>
- <string name="description_mxtv_rc" translatable="false">Banned from public television in Mexico</string>
-
- <!-- TV content rating system strings for MY TV -->
- <string name="display_name_mytv" translatable="false">MY-TV</string>
- <string name="display_name_mytv_u" translatable="false">U</string>
- <string name="display_name_mytv_p13" translatable="false">P13</string>
- <string name="display_name_mytv_18" translatable="false">18</string>
- <string name="description_mytv_u" translatable="false">General viewing for all ages, can be broadcast anytime</string>
- <string name="description_mytv_p13" translatable="false">For viewers ages 13 and above, children under 13 needs parental guidance, can be broadcast anytime, but some elements may only be broadcast at night</string>
- <string name="description_mytv_18" translatable="false">For viewers ages 18 and above only</string>
-
- <!-- TV content rating system strings for NL TV -->
- <string name="display_name_nltv" translatable="false">NICAM</string>
- <string name="display_name_nltv_v" translatable="false">Geweld</string>
- <string name="display_name_nltv_f" translatable="false">Angst</string>
- <string name="display_name_nltv_s" translatable="false">Seks</string>
- <string name="display_name_nltv_d" translatable="false">Discriminatie</string>
- <string name="display_name_nltv_da" translatable="false">Drugs- en/of alcoholmisbruik</string>
- <string name="display_name_nltv_l" translatable="false">Grof taalgebruik</string>
- <string name="display_name_nltv_al" translatable="false">Alle leeftijden</string>
- <string name="display_name_nltv_6" translatable="false">Let op met kinderen tot 6 jaar</string>
- <string name="display_name_nltv_9" translatable="false">Let op met kinderen tot 9 jaar</string>
- <string name="display_name_nltv_12" translatable="false">Let op met kinderen tot 12 jaar</string>
- <string name="display_name_nltv_16" translatable="false">Let op met kinderen tot 16 jaar</string>
- <string name="description_nltv_v" translatable="false">Violence\nApplicable to NL_TV_AL, NL_TV_6, NL_TV_9, NL_TV_12, NL_TV_16</string>
- <string name="description_nltv_f" translatable="false">Scary or Disturbing ContentViolence\nApplicable to NL_TV_AL, NL_TV_6, NL_TV_9, NL_TV_12, NL_TV_16</string>
- <string name="description_nltv_s" translatable="false">Sexual Content\nApplicable to NL_TV_AL, NL_TV_6, NL_TV_9, NL_TV_12, NL_TV_16</string>
- <string name="description_nltv_d" translatable="false">Discrimination\nApplicable to NL_TV_AL, NL_TV_6, NL_TV_9, NL_TV_12, NL_TV_16</string>
- <string name="description_nltv_da" translatable="false">Drug and/or Alcohol abuse\nApplicable to NL_TV_AL, NL_TV_6, NL_TV_9, NL_TV_12, NL_TV_16</string>
- <string name="description_nltv_l" translatable="false">Bad Language\nApplicable to NL_TV_AL, NL_TV_6, NL_TV_9, NL_TV_12, NL_TV_16</string>
- <string name="description_nltv_al" translatable="false">All Ages</string>
- <string name="description_nltv_6" translatable="false">Parental advisory for children under 6</string>
- <string name="description_nltv_9" translatable="false">Parental advisory for children under 9</string>
- <string name="description_nltv_12" translatable="false">Parental advisory for children under 12</string>
- <string name="description_nltv_16" translatable="false">Parental advisory for children under 16</string>
-
- <!-- TV content rating system strings for NZF(Free) TV -->
- <string name="display_name_nzftv" translatable="false">NZ-Free-TV</string>
- <string name="description_nzftv" translatable="false">TV content rating system for free-to-air channels in New Zealand</string>
- <string name="display_name_nzftv_g" translatable="false">G</string>
- <string name="display_name_nzftv_pgr" translatable="false">PGR</string>
- <string name="display_name_nzftv_ao" translatable="false">AO</string>
- <string name="description_nzftv_g" translatable="false">These exclude material likely to harm children under 14 and can screen at any time. Programmes may not necessarily be designed for younger viewers, but must not contain material likely to cause them undue distress or discomfort</string>
- <string name="description_nzftv_pgr" translatable="false">Programmes more suited to more mature viewers. These are not necessarily unsuitable for children, but viewer discretion is advised, and parents and guardians are encouraged to supervise younger viewers</string>
- <string name="description_nzftv_ao" translatable="false">Contain material of an adult nature handled in such a way that it is unsuitable for children</string>
-
- <!-- TV content rating system strings for NZP(Pay) TV -->
- <string name="display_name_nzptv" translatable="false">NZ-Pay-TV</string>
- <string name="description_nzptv" translatable="false">TV content rating system for Pay TV channels in New Zealand</string>
- <string name="display_name_nzptv_c" translatable="false">C</string>
- <string name="display_name_nzptv_v" translatable="false">V</string>
- <string name="display_name_nzptv_l" translatable="false">L</string>
- <string name="display_name_nzptv_s" translatable="false">S</string>
- <string name="display_name_nzptv_g" translatable="false">G</string>
- <string name="display_name_nzptv_pg" translatable="false">PG</string>
- <string name="display_name_nzptv_m" translatable="false">M</string>
- <string name="display_name_nzptv_16" translatable="false">16</string>
- <string name="display_name_nzptv_18" translatable="false">18</string>
- <string name="description_nzptv_c" translatable="false">Content may offend\nApplicable to NZ_PTV_PG, NZ_PTV_M, NZ_PTV_16, NZ_PTV_18</string>
- <string name="description_nzptv_v" translatable="false">Violence\nApplicable to NZ_PTV_PG, NZ_PTV_M, NZ_PTV_16, NZ_PTV_18</string>
- <string name="description_nzptv_l" translatable="false">Language\nApplicable to NZ_PTV_PG, NZ_PTV_M, NZ_PTV_16, NZ_PTV_18</string>
- <string name="description_nzptv_s" translatable="false">Sexual content\nApplicable to NZ_PTV_PG, NZ_PTV_M, NZ_PTV_16, NZ_PTV_18</string>
- <string name="description_nzptv_g" translatable="false">suitable for general audiences</string>
- <string name="description_nzptv_pg" translatable="false">Parental guidance recommended for under 10</string>
- <string name="description_nzptv_m" translatable="false">Suitable for mature audiences 13 and up</string>
- <string name="description_nzptv_16" translatable="false">Suitable for viewers 16 and up</string>
- <string name="description_nzptv_18" translatable="false">Suitable for viewers 18 and up</string>
-
- <!-- TV content rating system strings for PE TV -->
- <string name="display_name_petv" translatable="false">PE-TV</string>
- <string name="description_petv" translatable="false">TV content rating system for some Peruvian channels in Peru</string>
- <string name="display_name_petv_a" translatable="false">Apt</string>
- <string name="display_name_petv_14" translatable="false">14</string>
- <string name="display_name_petv_18" translatable="false">18</string>
- <string name="description_petv_a" translatable="false">Suitable for all audiences</string>
- <string name="description_petv_14" translatable="false">Suitable for people aged 14 and above only</string>
- <string name="description_petv_18" translatable="false">Suitable for people aged 18 and above only</string>
-
- <!-- TV content rating system strings for America TV in PE -->
- <string name="display_name_peatv" translatable="false">PE-ATV</string>
- <string name="description_peatv" translatable="false">TV content rating system for America Television in Peru that uses its own rating system</string>
- <string name="display_name_peatv_gp" translatable="false">GP</string>
- <string name="display_name_peatv_pg" translatable="false">PG</string>
- <string name="display_name_peatv_14" translatable="false">TV-14</string>
- <string name="display_name_peatv_18" translatable="false">TV-18</string>
- <string name="description_peatv_gp" translatable="false">General audience</string>
- <string name="description_peatv_pg" translatable="false">Parental guidance required for under 6</string>
- <string name="description_peatv_14" translatable="false">Suitable for people aged 14 and above only</string>
- <string name="description_peatv_18" translatable="false">Suitable for people aged 18 and above only</string>
-
- <!-- TV content rating system strings for PH TV -->
- <string name="display_name_phtv" translatable="false">MTRCB</string>
- <string name="display_name_phtv_g" translatable="false">G</string>
- <string name="display_name_phtv_pg" translatable="false">PG</string>
- <string name="display_name_phtv_spg" translatable="false">SPG</string>
- <string name="description_phtv_g" translatable="false">Suitable for all public viewers</string>
- <string name="description_phtv_pg" translatable="false">Programmes rated PG may contain scenes or other content that are unsuitable for children without the guidance of a parent</string>
- <string name="description_phtv_spg" translatable="false">Contains mature themes or moderate to intense violence, which may be deemed unfit for children to watch without strict parental supervision</string>
-
- <!-- TV content rating system strings for PL TV -->
- <string name="display_name_pltv" translatable="false">PL-TV</string>
- <string name="display_name_pltv_g" translatable="false">No age limit</string>
- <string name="display_name_pltv_7" translatable="false">7</string>
- <string name="display_name_pltv_12" translatable="false">12</string>
- <string name="display_name_pltv_16" translatable="false">16</string>
- <string name="display_name_pltv_18" translatable="false">18</string>
- <string name="description_pltv_g" translatable="false">Positive or neutral view of the world, little to no violence, non-sexual love, and no sexual content</string>
- <string name="description_pltv_7" translatable="false">Age 7 and above. May additionally contain some mild language, bloodless violence, and a more negative view of the world</string>
- <string name="description_pltv_12" translatable="false">Age 12 and above. May contain some foul language, some violence, and some sexual content</string>
- <string name="description_pltv_16" translatable="false">Age 16 and above. Deviant social behaviour, world filled with violence and sexuality, simplified picture of adulthood, display of physical force, especially in controversial social context, immoral behaviour without ethic dilemma, putting the blame on the victim, excessive concentration on material possessions</string>
- <string name="description_pltv_18" translatable="false">Age 18 and above. One-sided display of the joys of adult life without showing responsibilities, social justification of violent behaviour, excessive vulgarity, use of racial slurs and social stereotypes, explicit sexual content, praise of aggression or vulgarity</string>
-
- <!-- TV content rating system strings for PT TV -->
- <string name="display_name_pttv" translatable="false">PT-TV</string>
- <string name="display_name_pttv_t" translatable="false">Todos</string>
- <string name="display_name_pttv_10" translatable="false">10</string>
- <string name="display_name_pttv_12" translatable="false">12</string>
- <string name="display_name_pttv_16" translatable="false">16</string>
- <string name="description_pttv_t" translatable="false">Suitable for all</string>
- <string name="description_pttv_10" translatable="false">May not be suitable for children under 10, parental guidance advised</string>
- <string name="description_pttv_12" translatable="false">May not be suitable for children under 12, parental guidance advised</string>
- <string name="description_pttv_16" translatable="false">Not suitable for children under 16</string>
-
- <!-- TV content rating system strings for RO TV -->
- <string name="display_name_rotv" translatable="false">RO-TV</string>
- <string name="display_name_rotv_y" translatable="false">Y</string>
- <string name="display_name_rotv_g" translatable="false">G</string>
- <string name="display_name_rotv_ap" translatable="false">AP</string>
- <string name="display_name_rotv_12" translatable="false">12</string>
- <string name="display_name_rotv_15" translatable="false">15</string>
- <string name="display_name_rotv_18" translatable="false">18</string>
- <string name="description_rotv_y" translatable="false">Young Ages</string>
- <string name="description_rotv_g" translatable="false">General Exhibition</string>
- <string name="description_rotv_ap" translatable="false">Parental guidance is recommended for children below the age of 12</string>
- <string name="description_rotv_12" translatable="false">Forbidden for children under 12 years of age</string>
- <string name="description_rotv_15" translatable="false">Forbidden for children under 15 years of age</string>
- <string name="description_rotv_18" translatable="false">Forbidden for children under 18 years of age</string>
-
- <!-- TV content rating system strings for RU TV -->
- <string name="display_name_rutv" translatable="false">RU-TV</string>
- <string name="display_name_rutv_0" translatable="false">0+</string>
- <string name="display_name_rutv_6" translatable="false">6+</string>
- <string name="display_name_rutv_12" translatable="false">12+</string>
- <string name="display_name_rutv_16" translatable="false">16+</string>
- <string name="display_name_rutv_18" translatable="false">18+</string>
- <string name="description_rutv_0" translatable="false">Can be watched by Any Age</string>
- <string name="description_rutv_6" translatable="false">Only kids the age of 6 or older can watch</string>
- <string name="description_rutv_12" translatable="false">Only kids the age of 12 or older can watch</string>
- <string name="description_rutv_16" translatable="false">Only teens the age of 16 or older can watch</string>
- <string name="description_rutv_18" translatable="false">Restricted to children ONLY people 18 or older</string>
-
- <!-- TV content rating system strings for RS TV -->
- <string name="display_name_rstv" translatable="false">RS-TV</string>
- <string name="display_name_rstv_g" translatable="false">G</string>
- <string name="display_name_rstv_12" translatable="false">12</string>
- <string name="display_name_rstv_14" translatable="false">14</string>
- <string name="display_name_rstv_15" translatable="false">15</string>
- <string name="display_name_rstv_16" translatable="false">16</string>
- <string name="display_name_rstv_17" translatable="false">17</string>
- <string name="display_name_rstv_18" translatable="false">18</string>
- <string name="description_rstv_g" translatable="false">Program suitable for all ages</string>
- <string name="description_rstv_12" translatable="false">Program not suitable for children under the age of 12 </string>
- <string name="description_rstv_14" translatable="false">Program not suitable for children/teens under the age of 14</string>
- <string name="description_rstv_15" translatable="false">Program not suitable for children/teens under the age of 15</string>
- <string name="description_rstv_16" translatable="false">Program not suitable for children/teens under the age of 16</string>
- <string name="description_rstv_17" translatable="false">Program not suitable for children/teens under the age of 17</string>
- <string name="description_rstv_18" translatable="false">Program not suitable for minors under the age of 18</string>
-
- <!-- TV content rating system strings for SGF(Free-to-Air) TV -->
- <string name="display_name_sgftv" translatable="false">SG-Free-TV</string>
- <string name="display_name_sgftv_pg" translatable="false">PG</string>
- <string name="display_name_sgftv_pg13" translatable="false">PG13</string>
- <string name="description_sgftv_pg" translatable="false">Suitable for most but parents should guide their young</string>
- <string name="description_sgftv_pg13" translatable="false">Parental Guidance Strongly Cautioned - Suitable for 13 And Above</string>
-
- <!-- TV content rating system strings for SGP(Pay TV) TV -->
- <string name="display_name_sgptv" translatable="false">SG-Pay-TV</string>
- <string name="display_name_sgptv_nc16" translatable="false">NC16</string>
- <string name="display_name_sgptv_m18" translatable="false">M18</string>
- <string name="description_sgptv_nc16" translatable="false">No Children Under 16</string>
- <string name="description_sgptv_m18" translatable="false">Nobody under age 18 is admitted</string>
-
- <!-- TV content rating system strings for SI TV -->
- <string name="display_name_sitv" translatable="false">SI-TV</string>
- <string name="display_name_sitv_vs" translatable="false">VS</string>
- <string name="display_name_sitv_12" translatable="false">+12</string>
- <string name="display_name_sitv_15" translatable="false">+15</string>
- <string name="display_name_sitv_ad" translatable="false">AD</string>
- <string name="description_sitv_vs" translatable="false">Parental guidance suggested (for children under 6)</string>
- <string name="description_sitv_12" translatable="false">Content suitable for teens over 12 years</string>
- <string name="description_sitv_15" translatable="false">Content suitable for teens over 15 years</string>
- <string name="description_sitv_ad" translatable="false">Content exclusively for adults</string>
-
- <!-- TV content rating system strings for TH TV -->
- <string name="display_name_thtv" translatable="false">TH-TV</string>
- <string name="display_name_thtv_primary" translatable="false">Primary</string>
- <string name="display_name_thtv_children" translatable="false">Children</string>
- <string name="display_name_thtv_general" translatable="false">General</string>
- <string name="display_name_thtv_pg13" translatable="false">PG13</string>
- <string name="display_name_thtv_pg18" translatable="false">PG18</string>
- <string name="display_name_thtv_adults" translatable="false">Adults</string>
- <string name="description_thtv_primary" translatable="false">Content suitable for primary school aged children</string>
- <string name="description_thtv_children" translatable="false">Content suitable for children between 6-12 years old</string>
- <string name="description_thtv_general" translatable="false">Content suitable for general audiences</string>
- <string name="description_thtv_pg13" translatable="false">Content suitable for people aged 13 and above, but can be watched by those who are under the recommended age if parental guidance is provided</string>
- <string name="description_thtv_pg18" translatable="false">Content suitable for people aged above 18 years old; those who are younger that 18 must be provided with parental guidance</string>
- <string name="description_thtv_adults" translatable="false">Content unsuitable for children and youngsters</string>
-
- <!-- TV content rating system strings for TR TV -->
- <string name="display_name_trtv" translatable="false">TR-TV</string>
- <string name="display_name_trtv_g" translatable="false">Genel İzleyici</string>
- <string name="display_name_trtv_7" translatable="false">7+</string>
- <string name="display_name_trtv_13" translatable="false">13+</string>
- <string name="display_name_trtv_18" translatable="false">18+</string>
- <string name="description_trtv_g" translatable="false">General audience. Suitable for all ages</string>
- <string name="description_trtv_7" translatable="false">Suitable for ages 7 and over</string>
- <string name="description_trtv_13" translatable="false">Suitable for ages 13 and over</string>
- <string name="description_trtv_18" translatable="false">Suitable for ages 13 and over</string>
-
- <!-- TV content rating system strings for TW TV -->
- <string name="display_name_twtv" translatable="false">TW-TV</string>
- <string name="display_name_twtv_g" translatable="false">General audiences category</string>
- <string name="display_name_twtv_p" translatable="false">Protected category</string>
- <string name="display_name_twtv_pg" translatable="false">Parental guidance category</string>
- <string name="display_name_twtv_r" translatable="false">Restricted category</string>
- <string name="description_twtv_g" translatable="false">For all ages</string>
- <string name="description_twtv_p" translatable="false">Not suitable for children under 6 years old. People aged 6 but under 12 require guidance from accompanying adults to watch</string>
- <string name="description_twtv_pg" translatable="false">Not suitable for people under 12 years of age. Parental guidance is required for people aged 12 but under 18</string>
- <string name="description_twtv_r" translatable="false">For adults only and people under 18 years of age must not watch</string>
-
- <!-- TV content rating system strings for UA TV -->
- <string name="display_name_uatv" translatable="false">UA-TV</string>
- <string name="display_name_uatv_green circle" translatable="false">Green Circle</string>
- <string name="display_name_uatv_yellow triangle" translatable="false">Yellow Triangle</string>
- <string name="display_name_uatv_red square" translatable="false">Red Square</string>
- <string name="description_uatv_green circle" translatable="false">This program does not have age restrictions</string>
- <string name="description_uatv_yellow triangle" translatable="false">Children must view this program with parents. In it program there are fragments, which unsuitable for children</string>
- <string name="description_uatv_red square" translatable="false">This program is only for adult viewers. In it there are scenes with nudity, drug use, or violence</string>
-
- <!-- TV content rating system strings for US TV -->
- <string name="display_name_ustv" translatable="false">US-TV</string>
- <string name="description_ustv" translatable="false">TV content rating system for United States</string>
- <string name="display_name_ustv_d" translatable="false">D</string>
- <string name="display_name_ustv_l" translatable="false">L</string>
- <string name="display_name_ustv_s" translatable="false">S</string>
- <string name="display_name_ustv_v" translatable="false">V</string>
- <string name="display_name_ustv_fv" translatable="false">FV</string>
- <string name="display_name_ustv_y" translatable="false">TV-Y</string>
- <string name="display_name_ustv_y7" translatable="false">TV-Y7</string>
- <string name="display_name_ustv_g" translatable="false">TV-G</string>
- <string name="display_name_ustv_pg" translatable="false">TV-PG</string>
- <string name="display_name_ustv_14" translatable="false">TV-14</string>
- <string name="display_name_ustv_ma" translatable="false">TV-MA</string>
- <string name="description_ustv_d" translatable="false">Suggestive dialogue (Usually means talks about sex)\nApplicable to US_TV_PG, US_TV_14, US_TV</string>
- <string name="description_ustv_l" translatable="false">Coarse language\nApplicable to US_TV_PG, US_TV_14</string>
- <string name="description_ustv_s" translatable="false">Sexual content\nApplicable to US_TV_PG, US_TV_14, US_TV_MA</string>
- <string name="description_ustv_v" translatable="false">Violence\nApplicable to US_TV_PG, US_TV_14, US_TV_MA</string>
- <string name="description_ustv_fv" translatable="false">Fantasy violence (Children\'s programming only)\nApplicable to US_TV_Y7</string>
- <string name="description_ustv_y" translatable="false">This program is designed to be appropriate for all children</string>
- <string name="description_ustv_y7" translatable="false">This program is designed for children age 7 and above</string>
- <string name="description_ustv_g" translatable="false">Most parents would find this program suitable for all ages</string>
- <string name="description_ustv_pg" translatable="false">This program contains material that parents may find unsuitable for younger children</string>
- <string name="description_ustv_14" translatable="false">This program contains some material that many parents would find unsuitable for children under 14 years of age</string>
- <string name="description_ustv_ma" translatable="false">This program is specifically designed to be viewed by adults and therefore may be unsuitable for children under 17</string>
-
- <!-- TV content rating system strings for VE TV -->
- <string name="display_name_vetv" translatable="false">VE-TV</string>
- <string name="display_name_vetv_tu" translatable="false">TU</string>
- <string name="display_name_vetv_su" translatable="false">SU</string>
- <string name="display_name_vetv_a" translatable="false">A</string>
- <string name="description_vetv_tu" translatable="false">For all ages</string>
- <string name="description_vetv_su" translatable="false">Parental guidance for young viewers</string>
- <string name="description_vetv_a" translatable="false">Mature viewers</string>
-
- <!-- TV content rating system strings for ZA TV -->
- <string name="display_name_zatv" translatable="false">ZA-TV</string>
- <string name="display_name_zatv_d" translatable="false">D</string>
- <string name="display_name_zatv_v" translatable="false">V</string>
- <string name="display_name_zatv_n" translatable="false">N</string>
- <string name="display_name_zatv_p" translatable="false">P</string>
- <string name="display_name_zatv_s" translatable="false">S</string>
- <string name="display_name_zatv_l" translatable="false">L</string>
- <string name="display_name_zatv_f" translatable="false">Family</string>
- <string name="display_name_zatv_pg" translatable="false">PG</string>
- <string name="display_name_zatv_13" translatable="false">13</string>
- <string name="display_name_zatv_16" translatable="false">16</string>
- <string name="display_name_zatv_18" translatable="false">18</string>
- <string name="display_name_zatv_r18" translatable="false">R18</string>
- <string name="description_zatv_d" translatable="false">Drug\nApplicable to ZA_TV_F, ZA_TV_PG, ZA_TV_13, ZA_TV_16, ZA_TV_18, ZA_TV_R18</string>
- <string name="description_zatv_v" translatable="false">Violence\nApplicable to ZA_TV_F, ZA_TV_PG, ZA_TV_13, ZA_TV_16, ZA_TV_18, ZA_TV_R18</string>
- <string name="description_zatv_n" translatable="false">Nudity\nApplicable to ZA_TV_F, ZA_TV_PG, ZA_TV_13, ZA_TV_16, ZA_TV_18, ZA_TV_R18</string>
- <string name="description_zatv_p" translatable="false">Prejudice\nApplicable to ZA_TV_F, ZA_TV_PG, ZA_TV_13, ZA_TV_16, ZA_TV_18, ZA_TV_R18</string>
- <string name="description_zatv_s" translatable="false">Sex\nApplicable to ZA_TV_F, ZA_TV_PG, ZA_TV_13, ZA_TV_16, ZA_TV_18, ZA_TV_R18</string>
- <string name="description_zatv_l" translatable="false">Language\nApplicable to ZA_TV_F, ZA_TV_PG, ZA_TV_13, ZA_TV_16, ZA_TV_18, ZA_TV_R18</string>
- <string name="description_zatv_f" translatable="false">This is a program/film that does not contain any obscenity, and is suitable for family viewing. A logo must be displayed in the corner of the screen for 30 seconds after each commercial break</string>
- <string name="description_zatv_pg" translatable="false">Children under 6 may watch this program/film, but must be accompanied by an adult. This program contains an adult related theme, which might include very mild language, violence and sexual innuendo. A logo must be displayed in the corner of the screen for one minute after each commercial break</string>
- <string name="description_zatv_13" translatable="false">Children under 13 are prohibited from watching this program/film. This program contains mild language, violence and sexual innuendo. A logo must be displayed in the corner of the screen for two minutes after each commercial break</string>
- <string name="description_zatv_16" translatable="false">Children under 16 are prohibited from watching this program/film. It contains moderate violence, language, and some sexual situations. In the case of television, this program may only be broadcast after 9pm-4:30am. A logo must be displayed in the corner of the screen for five minutes after each commercial break. A full-screen warning must be issued before the start of the program. If the program is longer than an hour, a warning must be displayed every half an hour</string>
- <string name="description_zatv_18" translatable="false">Children under 18 are prohibited from watching this program/film. It contains extreme violence, language and/or graphic sexual content. In the case of television, this program may only be broadcast from 10pm-4:30am. A logo must be displayed in the corner of the screen for the duration of the program. A full-screen warning must be issued before the start of the program and after each commercial break</string>
- <string name="description_zatv_r18" translatable="false">This is reserved for films of an extreme sexual nature (pornography). R18 films may only be distributed in the form of video and DVD in a controlled environment (e.g. Adult Shops). No public viewing of this film may take place. R18 films may not be broadcast on television and in cinemas</string>
+ <string name="lock_to_app_unlock_password">Ask for password before unpinning</string>
<!-- [CHAR_LIMIT=NONE] Battery saver: Feature description -->
<string name="battery_saver_description">To help improve battery life, battery saver reduces your device’s performance and limits vibration and most background data. Email, messaging, and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging</string>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index c8ea699..fb70d6b 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -413,12 +413,12 @@
<style name="TextAppearance.StatusBar.Material" />
<style name="TextAppearance.StatusBar.Material.EventContent">
- <item name="textColor">#90000000</item>
+ <item name="textColor">@color/secondary_text_material_light</item>
<item name="textSize">@dimen/notification_text_size</item>
</style>
<style name="TextAppearance.StatusBar.Material.EventContent.Title">
- <item name="textColor">#DD000000</item>
+ <item name="textColor">@color/primary_text_default_material_light</item>
<item name="textSize">@dimen/notification_title_text_size</item>
</style>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 0b3a132..ed7afeb 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -216,7 +216,9 @@
<java-symbol type="id" name="pin_confirm_text" />
<java-symbol type="id" name="pin_error_message" />
<java-symbol type="id" name="timePickerLayout" />
- <java-symbol type="id" name="profile_icon" />
+ <java-symbol type="id" name="profile_badge_large_template" />
+ <java-symbol type="id" name="profile_badge_line2" />
+ <java-symbol type="id" name="profile_badge_line3" />
<java-symbol type="id" name="transitionPosition" />
<java-symbol type="attr" name="actionModeShareDrawable" />
@@ -321,6 +323,7 @@
<java-symbol type="integer" name="config_multiuserMaximumUsers" />
<java-symbol type="integer" name="config_safe_media_volume_index" />
<java-symbol type="integer" name="config_mobile_mtu" />
+ <java-symbol type="array" name="config_mobile_tcp_buffers" />
<java-symbol type="integer" name="config_volte_replacement_rat"/>
<java-symbol type="integer" name="config_valid_wappush_index" />
<java-symbol type="integer" name="config_overrideHasPermanentMenuKey" />
@@ -349,7 +352,11 @@
<java-symbol type="dimen" name="notification_text_size" />
<java-symbol type="dimen" name="notification_title_text_size" />
<java-symbol type="dimen" name="notification_subtext_size" />
- <java-symbol type="dimen" name="notification_large_font_vert_pad" />
+ <java-symbol type="dimen" name="notification_top_pad" />
+ <java-symbol type="dimen" name="notification_top_pad_narrow" />
+ <java-symbol type="dimen" name="notification_top_pad_large_text" />
+ <java-symbol type="dimen" name="notification_top_pad_large_text_narrow" />
+ <java-symbol type="dimen" name="notification_large_icon_circle_padding" />
<java-symbol type="dimen" name="immersive_mode_cling_width" />
<java-symbol type="dimen" name="circular_display_mask_offset" />
@@ -621,7 +628,6 @@
<java-symbol type="id" name="lock_to_app_checkbox" />
<java-symbol type="string" name="lock_to_app_start" />
<java-symbol type="string" name="lock_to_app_exit" />
- <java-symbol type="string" name="lock_to_app_use_screen_lock" />
<java-symbol type="string" name="lock_to_app_unlock_pin" />
<java-symbol type="string" name="lock_to_app_unlock_pattern" />
<java-symbol type="string" name="lock_to_app_unlock_password" />
@@ -1265,7 +1271,6 @@
<java-symbol type="xml" name="audio_assets" />
<java-symbol type="xml" name="global_keys" />
<java-symbol type="xml" name="default_zen_mode_config" />
- <java-symbol type="xml" name="tv_content_rating_systems" />
<java-symbol type="raw" name="color_fade_vert" />
<java-symbol type="raw" name="color_fade_frag" />
@@ -1705,12 +1710,12 @@
<java-symbol type="layout" name="notification_template_material_inbox" />
<java-symbol type="layout" name="notification_template_material_media" />
<java-symbol type="layout" name="notification_template_material_big_media" />
+ <java-symbol type="layout" name="notification_template_material_big_text" />
<java-symbol type="layout" name="notification_template_icon_group" />
<java-symbol type="layout" name="notification_material_media_action" />
<java-symbol type="color" name="notification_action_legacy_color_filter" />
<java-symbol type="color" name="notification_icon_bg_color" />
<java-symbol type="drawable" name="notification_icon_legacy_bg" />
- <java-symbol type="drawable" name="notification_icon_legacy_bg_inset" />
<java-symbol type="drawable" name="notification_material_media_progress" />
<java-symbol type="color" name="notification_media_action_bg" />
<java-symbol type="color" name="notification_media_progress" />
@@ -1987,4 +1992,7 @@
<java-symbol type="color" name="battery_saver_mode_color" />
<java-symbol type="color" name="system_notification_accent_color" />
<java-symbol type="dimen" name="text_handle_min_size" />
+ <java-symbol type="id" name="transitionTransform" />
+ <java-symbol type="id" name="parentMatrix" />
+ <java-symbol type="bool" name="config_auto_attach_data_on_creation" />
</resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index b36cdb9..5445816 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -116,12 +116,12 @@
<!-- Button styles -->
<item name="buttonStyle">@style/Widget.Button</item>
-
<item name="buttonStyleSmall">@style/Widget.Button.Small</item>
<item name="buttonStyleInset">@style/Widget.Button.Inset</item>
-
<item name="buttonStyleToggle">@style/Widget.Button.Toggle</item>
+ <item name="switchStyle">@style/Widget.CompoundButton.Switch</item>
+
<item name="selectableItemBackground">@drawable/item_background</item>
<item name="selectableItemBackgroundBorderless">?attr/selectableItemBackground</item>
<item name="borderlessButtonStyle">?attr/buttonStyle</item>
diff --git a/core/res/res/values/themes_leanback.xml b/core/res/res/values/themes_leanback.xml
index 2b3b8d5..720733f 100644
--- a/core/res/res/values/themes_leanback.xml
+++ b/core/res/res/values/themes_leanback.xml
@@ -34,6 +34,16 @@
<item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
</style>
+ <style name="Theme.Leanback.Settings.Dialog" parent="Theme.Material.Settings.BaseDialog">
+ <item name="colorBackground">@color/background_leanback_dark</item>
+ <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
+ <item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
+ <item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
+ <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
+ <item name="datePickerStyle">@style/Widget.Leanback.DatePicker</item>
+ <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
+ </style>
+
<style name="Theme.Leanback.Dialog.Alert" parent="Theme.Material.Dialog.BaseAlert">
<item name="colorBackground">@color/background_leanback_dark</item>
<item name="textColorPrimary">@color/primary_text_leanback_dark</item>
@@ -54,6 +64,16 @@
<item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
</style>
+ <style name="Theme.Leanback.Settings.Dialog.Alert" parent="Theme.Material.Settings.Dialog.BaseAlert">
+ <item name="colorBackground">@color/background_leanback_light</item>
+ <item name="textColorPrimary">@color/primary_text_leanback_light</item>
+ <item name="textColorSecondary">@color/secondary_text_leanback_light</item>
+ <item name="alertDialogStyle">@style/AlertDialog.Leanback.Light</item>
+ <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
+ <item name="datePickerStyle">@style/Widget.Leanback.DatePicker</item>
+ <item name="numberPickerStyle">@style/Widget.Leanback.NumberPicker</item>
+ </style>
+
<style name="Theme.Leanback.Dialog.AppError" parent="Theme.Leanback.Dialog">
<item name="windowContentTransitions">false</item>
<item name="windowCloseOnTouchOutside">false</item>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 18170ac..7a208f7 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -333,8 +333,7 @@
<item name="dividerVertical">?attr/listDivider</item>
<item name="dividerHorizontal">?attr/listDivider</item>
<item name="buttonBarStyle">@style/Widget.Material.ButtonBar</item>
- <item name="buttonBarButtonStyle">@style/Widget.Material.Button.Borderless</item>
- <item name="buttonBarPositiveButtonStyle">@style/Widget.Material.Button.Borderless.Colored</item>
+ <item name="buttonBarButtonStyle">@style/Widget.Material.Button.Borderless.Colored</item>
<item name="segmentedButtonStyle">@style/Widget.Material.SegmentedButton</item>
<!-- SearchView attributes -->
@@ -357,10 +356,10 @@
<item name="timePickerDialogTheme">?attr/dialogTheme</item>
<!-- DatePicker style -->
- <item name="datePickerStyle">?attr/dialogTheme</item>
+ <item name="datePickerStyle">@style/Widget.Material.DatePicker</item>
<!-- DatePicker dialog theme -->
- <item name="datePickerDialogTheme">@style/Theme.Material.Dialog.Alert</item>
+ <item name="datePickerDialogTheme">?attr/dialogTheme</item>
<!-- TODO: This belongs in a FastScroll style -->
<item name="fastScrollThumbDrawable">@drawable/fastscroll_thumb_material</item>
@@ -379,6 +378,7 @@
<item name="colorControlHighlight">@color/ripple_material_dark</item>
<item name="colorButtonNormal">@color/btn_default_material_dark</item>
+ <item name="colorSwitchThumbNormal">@color/switch_thumb_material_dark</item>
</style>
<!-- Material theme (light version). -->
@@ -679,8 +679,7 @@
<item name="dividerVertical">?attr/listDivider</item>
<item name="dividerHorizontal">?attr/listDivider</item>
<item name="buttonBarStyle">@style/Widget.Material.Light.ButtonBar</item>
- <item name="buttonBarButtonStyle">@style/Widget.Material.Light.Button.Borderless</item>
- <item name="buttonBarPositiveButtonStyle">@style/Widget.Material.Light.Button.Borderless.Colored</item>
+ <item name="buttonBarButtonStyle">@style/Widget.Material.Light.Button.Borderless.Colored</item>
<item name="segmentedButtonStyle">@style/Widget.Material.Light.SegmentedButton</item>
<!-- SearchView attributes -->
@@ -721,6 +720,7 @@
<item name="colorControlHighlight">@color/ripple_material_light</item>
<item name="colorButtonNormal">@color/btn_default_material_light</item>
+ <item name="colorSwitchThumbNormal">@color/switch_thumb_material_light</item>
</style>
<!-- Variant of the material (light) theme that has a solid (opaque) action bar
@@ -774,6 +774,7 @@
<item name="colorControlNormal">?attr/textColorSecondary</item>
<item name="colorControlHighlight">@color/ripple_material_light</item>
<item name="colorButtonNormal">@color/btn_default_material_light</item>
+ <item name="colorSwitchThumbNormal">@color/switch_thumb_material_light</item>
</style>
<!-- Theme overlay that replaces colors with their dark versions but preserves
@@ -811,6 +812,7 @@
<item name="colorControlNormal">?attr/textColorSecondary</item>
<item name="colorControlHighlight">@color/ripple_material_dark</item>
<item name="colorButtonNormal">@color/btn_default_material_dark</item>
+ <item name="colorSwitchThumbNormal">@color/switch_thumb_material_dark</item>
</style>
<!-- Theme overlay that replaces the normal control color, which by default is the same as the
@@ -1192,7 +1194,7 @@
<style name="Theme.Material.Light.Dialog.Alert" parent="Theme.Material.Light.Dialog.BaseAlert"/>
<!-- Theme for a presentation window on a secondary display. -->
- <style name="Theme.Material.Light.Dialog.Presentation" parent="@style/Theme.Material.Light.NoActionBar.Fullscreen" />
+ <style name="Theme.Material.Light.Dialog.Presentation" parent="Theme.Material.Light.NoActionBar.Fullscreen" />
<!-- Default material (dark) for windows that want to have the user's selected
wallpaper appear behind them. -->
@@ -1209,7 +1211,47 @@
</style>
<!-- Default theme for Settings and activities launched from Settings. -->
- <style name="Theme.Material.Settings" parent="@style/Theme.Material.Light.DarkActionBar">
+ <style name="Theme.Material.Settings" parent="Theme.Material.Light.DarkActionBar">
+ <item name="colorPrimary">@color/material_blue_grey_900</item>
+ <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+ <item name="colorAccent">@color/material_deep_teal_A500</item>
+
+ <item name="dialogTheme">@style/Theme.Material.Settings.Dialog</item>
+ <item name="alertDialogTheme">@style/Theme.Material.Settings.Dialog.Alert</item>
+ <item name="presentationTheme">@style/Theme.Material.Settings.Dialog.Presentation</item>
+ <item name="searchDialogTheme">@style/Theme.Material.Settings.SearchBar</item>
+ <item name="panelMenuListTheme">@style/Theme.Material.Settings.CompactMenu</item>
+ </style>
+
+ <style name="Theme.Material.Settings.BaseDialog" parent="Theme.Material.Light.BaseDialog">
+ <item name="colorPrimary">@color/material_blue_grey_900</item>
+ <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+ <item name="colorAccent">@color/material_deep_teal_A500</item>
+ </style>
+
+ <style name="Theme.Material.Settings.Dialog" parent="Theme.Material.Settings.BaseDialog" />
+
+ <style name="Theme.Material.Settings.Dialog.BaseAlert" parent="Theme.Material.Light.Dialog.BaseAlert">
+ <item name="colorPrimary">@color/material_blue_grey_900</item>
+ <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+ <item name="colorAccent">@color/material_deep_teal_A500</item>
+ </style>
+
+ <style name="Theme.Material.Settings.Dialog.Alert" parent="Theme.Material.Settings.Dialog.BaseAlert" />
+
+ <style name="Theme.Material.Settings.Dialog.Presentation" parent="Theme.Material.Light.Dialog.Presentation">
+ <item name="colorPrimary">@color/material_blue_grey_900</item>
+ <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+ <item name="colorAccent">@color/material_deep_teal_A500</item>
+ </style>
+
+ <style name="Theme.Material.Settings.SearchBar" parent="Theme.Material.Light.SearchBar">
+ <item name="colorPrimary">@color/material_blue_grey_900</item>
+ <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+ <item name="colorAccent">@color/material_deep_teal_A500</item>
+ </style>
+
+ <style name="Theme.Material.Settings.CompactMenu" parent="Theme.Material.Light.CompactMenu">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
<item name="colorAccent">@color/material_deep_teal_A500</item>
diff --git a/core/res/res/xml/tv_content_rating_systems.xml b/core/res/res/xml/tv_content_rating_systems.xml
deleted file mode 100644
index 1318274..0000000
--- a/core/res/res/xml/tv_content_rating_systems.xml
+++ /dev/null
@@ -1,1744 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<rating-system-definitions version="1.0">
- <!-- Range specific TV content rating system for AM TV-->
- <rating-system-definition id="AM_TV_RS"
- displayName="@string/display_name_amtvrs"
- description="@string/description_amtvrs"
- country="AM">
- <rating-definition id="AM_TV_RS_Y"
- displayName="@string/display_name_amtvrs_y"
- description="@string/description_amtvrs_y"
- ageHint="2" />
- <rating-definition id="AM_TV_RS_Y7"
- displayName="@string/display_name_amtvrs_y7"
- description="@string/description_amtvrs_y7"
- ageHint="7" />
- <rating-definition id="AM_TV_RS_GA"
- displayName="@string/display_name_amtvrs_ga"
- description="@string/description_amtvrs_ga"
- ageHint="0" />
- <rating-definition id="AM_TV_RS_TW"
- displayName="@string/display_name_amtvrs_tw"
- description="@string/description_amtvrs_tw"
- ageHint="9" />
- <rating-definition id="AM_TV_RS_T"
- displayName="@string/display_name_amtvrs_t"
- description="@string/description_amtvrs_t"
- ageHint="12" />
- <rating-definition id="AM_TV_RS_A"
- displayName="@string/display_name_amtvrs_a"
- description="@string/description_amtvrs_a"
- ageHint="18" />
- <order>
- <rating id="AM_TV_RS_Y" />
- <rating id="AM_TV_RS_Y7" />
- </order>
- <order>
- <rating id="AM_TV_RS_GA" />
- <rating id="AM_TV_RS_TW" />
- <rating id="AM_TV_RS_T" />
- <rating id="AM_TV_RS_A" />
- </order>
- </rating-system-definition>
-
- <!-- Age specific TV content rating system for AM TV-->
- <rating-system-definition id="AM_TV_AS"
- displayName="@string/display_name_amtvas"
- description="@string/description_amtvas"
- country="AM">
- <rating-definition id="AM_TV_AS_EC"
- displayName="@string/display_name_amtvas_ec"
- description="@string/description_amtvas_ec"
- ageHint="2" />
- <rating-definition id="AM_TV_AS_E"
- displayName="@string/display_name_amtvas_e"
- description="@string/description_amtvas_e"
- ageHint="5" />
- <rating-definition id="AM_TV_AS_E9"
- displayName="@string/display_name_amtvas_e9"
- description="@string/description_amtvas_e9"
- ageHint="9" />
- <rating-definition id="AM_TV_AS_T"
- displayName="@string/display_name_amtvas_t"
- description="@string/description_amtvas_t"
- ageHint="12" />
- <rating-definition id="AM_TV_AS_M"
- displayName="@string/display_name_amtvas_m"
- description="@string/description_amtvas_m"
- ageHint="16" />
- <rating-definition id="AM_TV_AS_AO"
- displayName="@string/display_name_amtvas_ao"
- description="@string/description_amtvas_ao"
- ageHint="17" />
- <order>
- <rating id="AM_TV_AS_EC" />
- <rating id="AM_TV_AS_E" />
- <rating id="AM_TV_AS_E9" />
- <rating id="AM_TV_AS_T" />
- <rating id="AM_TV_AS_M" />
- <rating id="AM_TV_AS_AO" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for AR TV -->
- <rating-system-definition id="AR_TV"
- displayName="@string/display_name_artv"
- country="AR">
- <rating-definition id="AR_TV_ALL"
- displayName="@string/display_name_artv_all"
- description="@string/description_artv_all"
- ageHint="0" />
- <rating-definition id="AR_TV_13"
- displayName="@string/display_name_artv_13"
- description="@string/description_artv_13"
- ageHint="13" />
- <rating-definition id="AR_TV_16"
- displayName="@string/display_name_artv_16"
- description="@string/description_artv_16"
- ageHint="16" />
- <rating-definition id="AR_TV_18"
- displayName="@string/display_name_artv_18"
- description="@string/description_artv_18"
- ageHint="18" />
- <order>
- <rating id="AR_TV_ALL" />
- <rating id="AR_TV_13" />
- <rating id="AR_TV_16" />
- <rating id="AR_TV_18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for AU TV -->
- <rating-system-definition id="AU_TV"
- displayName="@string/display_name_autv"
- country="AU">
- <rating-definition id="AU_TV_CTC"
- displayName="@string/display_name_autv_ctc"
- description="@string/description_autv_ctc"
- ageHint="0" />
- <rating-definition id="AU_TV_G"
- displayName="@string/display_name_autv_g"
- description="@string/description_autv_g"
- ageHint="0" />
- <rating-definition id="AU_TV_PG"
- displayName="@string/display_name_autv_pg"
- description="@string/description_autv_pg"
- ageHint="15" />
- <rating-definition id="AU_TV_M"
- displayName="@string/display_name_autv_m"
- description="@string/description_autv_m"
- ageHint="15" />
- <rating-definition id="AU_TV_MA15"
- displayName="@string/display_name_autv_ma15"
- description="@string/description_autv_ma15"
- ageHint="15" />
- <rating-definition id="AU_TV_R18"
- displayName="@string/display_name_autv_r18"
- description="@string/description_autv_r18"
- ageHint="18" />
- <rating-definition id="AU_TV_X18"
- displayName="@string/display_name_autv_x18"
- description="@string/description_autv_x18"
- ageHint="18" />
- <order>
- <rating id="AU_TV_G" />
- <rating id="AU_TV_PG" />
- <rating id="AU_TV_M" />
- <rating id="AU_TV_MA15" />
- <rating id="AU_TV_R18" />
- <rating id="AU_TV_X18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for BG TV -->
- <rating-system-definition id="BG_TV"
- displayName="@string/display_name_bgtv"
- country="BG">
- <rating-definition id="BG_TV_A"
- displayName="@string/display_name_bgtv_a"
- description="@string/description_bgtv_a"
- ageHint="0" />
- <rating-definition id="BG_TV_B"
- displayName="@string/display_name_bgtv_b"
- description="@string/description_bgtv_b"
- ageHint="0" />
- <rating-definition id="BG_TV_C"
- displayName="@string/display_name_bgtv_c"
- description="@string/description_bgtv_c"
- ageHint="12" />
- <rating-definition id="BG_TV_D"
- displayName="@string/display_name_bgtv_d"
- description="@string/description_bgtv_d"
- ageHint="16" />
- <rating-definition id="BG_TV_X"
- displayName="@string/display_name_bgtv_x"
- description="@string/description_bgtv_x"
- ageHint="18" />
- <order>
- <rating id="BG_TV_A" />
- <rating id="BG_TV_B" />
- <rating id="BG_TV_C" />
- <rating id="BG_TV_D" />
- <rating id="BG_TV_X" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for BR TV -->
- <rating-system-definition id="BR_TV"
- displayName="@string/display_name_brtv"
- country="BR">
- <rating-definition id="BR_TV_L"
- displayName="@string/display_name_brtv_l"
- description="@string/description_brtv_l"
- ageHint="0" />
- <rating-definition id="BR_TV_10"
- displayName="@string/display_name_brtv_10"
- description="@string/description_brtv_10"
- ageHint="10" />
- <rating-definition id="BR_TV_12"
- displayName="@string/display_name_brtv_12"
- description="@string/description_brtv_12"
- ageHint="12" />
- <rating-definition id="BR_TV_14"
- displayName="@string/display_name_brtv_14"
- description="@string/description_brtv_14"
- ageHint="14" />
- <rating-definition id="BR_TV_16"
- displayName="@string/display_name_brtv_16"
- description="@string/description_brtv_16"
- ageHint="16" />
- <rating-definition id="BR_TV_18"
- displayName="@string/display_name_brtv_18"
- description="@string/description_brtv_18"
- ageHint="18" />
- <order>
- <rating id="BR_TV_L" />
- <rating id="BR_TV_10" />
- <rating id="BR_TV_12" />
- <rating id="BR_TV_14" />
- <rating id="BR_TV_16" />
- <rating id="BR_TV_18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for CA TV -->
- <rating-system-definition id="CA_TV"
- displayName="@string/display_name_catv"
- country="CA">
- <rating-definition id="CA_TV_EXEMPT"
- displayName="@string/display_name_catv_exempt"
- description="@string/description_catv_exempt"
- ageHint="0" />
- <rating-definition id="CA_TV_C"
- displayName="@string/display_name_catv_c"
- description="@string/description_catv_c"
- ageHint="0" />
- <rating-definition id="CA_TV_C8"
- displayName="@string/display_name_catv_c8"
- description="@string/description_catv_c8"
- ageHint="8" />
- <rating-definition id="CA_TV_G"
- displayName="@string/display_name_catv_g"
- description="@string/description_catv_g"
- ageHint="0" />
- <rating-definition id="CA_TV_PG"
- displayName="@string/display_name_catv_pg"
- description="@string/description_catv_pg"
- ageHint="14" />
- <rating-definition id="CA_TV_14"
- displayName="@string/display_name_catv_14"
- description="@string/description_catv_14"
- ageHint="14" />
- <rating-definition id="CA_TV_18"
- displayName="@string/display_name_catv_18"
- description="@string/description_catv_18"
- ageHint="18" />
- <order>
- <rating id="CA_TV_C" />
- <rating id="CA_TV_C8" />
- </order>
- <order>
- <rating id="CA_TV_G" />
- <rating id="CA_TV_PG" />
- <rating id="CA_TV_14" />
- <rating id="CA_TV_18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for CH TV -->
- <rating-system-definition id="CH_TV"
- displayName="@string/display_name_chtv"
- country="CH">
- <rating-definition id="CH_TV_ALL"
- displayName="@string/display_name_chtv_all"
- description="@string/description_chtv_all"
- ageHint="0" />
- <rating-definition id="CH_TV_RED"
- displayName="@string/display_name_chtv_red"
- description="@string/description_chtv_red"
- ageHint="18" />
- <order>
- <rating id="CH_TV_ALL" />
- <rating id="CH_TV_RED" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for CL TV -->
- <rating-system-definition id="CL_TV"
- displayName="@string/display_name_cltv"
- country="CL">
- <rating-definition id="CL_TV_I"
- displayName="@string/display_name_cltv_i"
- description="@string/description_cltv_i"
- ageHint="0" />
- <rating-definition id="CL_TV_I7"
- displayName="@string/display_name_cltv_i7"
- description="@string/description_cltv_i7"
- ageHint="7" />
- <rating-definition id="CL_TV_I10"
- displayName="@string/display_name_cltv_i10"
- description="@string/description_cltv_i10"
- ageHint="10" />
- <rating-definition id="CL_TV_I12"
- displayName="@string/display_name_cltv_i12"
- description="@string/description_cltv_i12"
- ageHint="12" />
- <rating-definition id="CL_TV_F"
- displayName="@string/display_name_cltv_f"
- description="@string/description_cltv_f"
- ageHint="0" />
- <rating-definition id="CL_TV_R"
- displayName="@string/display_name_cltv_r"
- description="@string/description_cltv_r"
- ageHint="12" />
- <rating-definition id="CL_TV_A"
- displayName="@string/display_name_cltv_a"
- description="@string/description_cltv_a"
- ageHint="18" />
- <order>
- <rating id="CL_TV_I" />
- <rating id="CL_TV_I7" />
- <rating id="CL_TV_I10" />
- <rating id="CL_TV_I12" />
- </order>
- <order>
- <rating id="CL_TV_F" />
- <rating id="CL_TV_R" />
- <rating id="CL_TV_A" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for DE TV -->
- <rating-system-definition id="DE_TV"
- displayName="@string/display_name_detv"
- country="DE">
- <rating-definition id="DE_TV_ALL"
- displayName="@string/display_name_detv_all"
- description="@string/description_detv_all"
- ageHint="0" />
- <rating-definition id="DE_TV_12"
- displayName="@string/display_name_detv_12"
- description="@string/description_detv_12"
- ageHint="12" />
- <rating-definition id="DE_TV_16"
- displayName="@string/display_name_detv_16"
- description="@string/description_detv_16"
- ageHint="16" />
- <rating-definition id="DE_TV_18"
- displayName="@string/display_name_detv_18"
- description="@string/description_detv_18"
- ageHint="18" />
- <order>
- <rating id="DE_TV_ALL" />
- <rating id="DE_TV_12" />
- <rating id="DE_TV_16" />
- <rating id="DE_TV_18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for DK TV -->
- <rating-system-definition id="DK_TV"
- displayName="@string/display_name_dktv"
- country="DK">
- <rating-definition id="DK_TV_G"
- displayName="@string/display_name_dktv_g"
- description="@string/description_dktv_g"
- ageHint="0" />
- <rating-definition id="DK_TV_Y"
- displayName="@string/display_name_dktv_y"
- description="@string/description_dktv_y"
- ageHint="13" />
- <rating-definition id="DK_TV_R"
- displayName="@string/display_name_dktv_r"
- description="@string/description_dktv_r"
- ageHint="18" />
- <rating-definition id="DK_TV_B"
- displayName="@string/display_name_dktv_b"
- description="@string/description_dktv_b"
- ageHint="18" />
- <order>
- <rating id="DK_TV_G" />
- <rating id="DK_TV_Y" />
- <rating id="DK_TV_R" />
- <rating id="DK_TV_B" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for ES TV -->
- <rating-system-definition id="ES_TV"
- displayName="@string/display_name_estv"
- country="ES">
- <rating-definition id="ES_TV_TP"
- displayName="@string/display_name_estv_tp"
- description="@string/description_estv_tp"
- ageHint="0" />
- <rating-definition id="ES_TV_I"
- displayName="@string/display_name_estv_i"
- description="@string/description_estv_i"
- ageHint="0" />
- <rating-definition id="ES_TV_7"
- displayName="@string/display_name_estv_7"
- description="@string/description_estv_7"
- ageHint="7" />
- <rating-definition id="ES_TV_7I"
- displayName="@string/display_name_estv_7i"
- description="@string/description_estv_7i"
- ageHint="7" />
- <rating-definition id="ES_TV_12"
- displayName="@string/display_name_estv_12"
- description="@string/description_estv_12"
- ageHint="12" />
- <rating-definition id="ES_TV_16"
- displayName="@string/display_name_estv_16"
- description="@string/description_estv_16"
- ageHint="16" />
- <rating-definition id="ES_TV_18"
- displayName="@string/display_name_estv_18"
- description="@string/description_estv_18"
- ageHint="18" />
- <order>
- <rating id="ES_TV_TP" />
- <rating id="ES_TV_I" />
- <rating id="ES_TV_7" />
- <rating id="ES_TV_7I" />
- <rating id="ES_TV_12" />
- <rating id="ES_TV_16" />
- <rating id="ES_TV_18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for FI TV -->
- <rating-system-definition id="FI_TV"
- displayName="@string/display_name_fitv"
- country="FI">
- <rating-definition id="FI_TV_S"
- displayName="@string/display_name_fitv_s"
- description="@string/description_fitv_s"
- ageHint="0" />
- <rating-definition id="FI_TV_K7"
- displayName="@string/display_name_fitv_k7"
- description="@string/description_fitv_k7"
- ageHint="7" />
- <rating-definition id="FI_TV_K12"
- displayName="@string/display_name_fitv_k12"
- description="@string/description_fitv_k12"
- ageHint="12" />
- <rating-definition id="FI_TV_K16"
- displayName="@string/display_name_fitv_k16"
- description="@string/description_fitv_k16"
- ageHint="16" />
- <rating-definition id="FI_TV_K18"
- displayName="@string/display_name_fitv_k18"
- description="@string/description_fitv_k18"
- ageHint="18" />
- <order>
- <rating id="FI_TV_S" />
- <rating id="FI_TV_K7" />
- <rating id="FI_TV_K12" />
- <rating id="FI_TV_K16" />
- <rating id="FI_TV_K18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for FR TV -->
- <rating-system-definition id="FR_TV"
- displayName="@string/display_name_frtv"
- country="FR">
- <rating-definition id="FR_TV_ALL"
- displayName="@string/display_name_frtv_all"
- description="@string/description_frtv_all"
- ageHint="0" />
- <rating-definition id="FR_TV_10"
- displayName="@string/display_name_frtv_10"
- description="@string/description_frtv_10"
- ageHint="10" />
- <rating-definition id="FR_TV_12"
- displayName="@string/display_name_frtv_12"
- description="@string/description_frtv_12"
- ageHint="12" />
- <rating-definition id="FR_TV_16"
- displayName="@string/display_name_frtv_16"
- description="@string/description_frtv_16"
- ageHint="16" />
- <rating-definition id="FR_TV_18"
- displayName="@string/display_name_frtv_18"
- description="@string/description_frtv_18"
- ageHint="18" />
- <order>
- <rating id="FR_TV_ALL" />
- <rating id="FR_TV_10" />
- <rating id="FR_TV_12" />
- <rating id="FR_TV_16" />
- <rating id="FR_TV_18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for GR TV -->
- <rating-system-definition id="GR_TV"
- displayName="@string/display_name_grtv"
- country="GR">
- <rating-definition id="GR_TV_all"
- displayName="@string/display_name_grtv_all"
- description="@string/description_grtv_all"
- ageHint="0" />
- <rating-definition id="GR_TV_10"
- displayName="@string/display_name_grtv_10"
- description="@string/description_grtv_10"
- ageHint="10" />
- <rating-definition id="GR_TV_12"
- displayName="@string/display_name_grtv_12"
- description="@string/description_grtv_12"
- ageHint="12" />
- <rating-definition id="GR_TV_15"
- displayName="@string/display_name_grtv_15"
- description="@string/description_grtv_15"
- ageHint="15" />
- <rating-definition id="GR_TV_18"
- displayName="@string/display_name_grtv_18"
- description="@string/description_grtv_18"
- ageHint="18" />
- <order>
- <rating id="GR_TV_all" />
- <rating id="GR_TV_10" />
- <rating id="GR_TV_12" />
- <rating id="GR_TV_15" />
- <rating id="GR_TV_18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for HK TV -->
- <rating-system-definition id="HK_TV"
- displayName="@string/display_name_hktv"
- country="HK">
- <rating-definition id="HK_TV_G"
- displayName="@string/display_name_hktv_g"
- description="@string/description_hktv_g"
- ageHint="0" />
- <rating-definition id="HK_TV_PG"
- displayName="@string/display_name_hktv_pg"
- description="@string/description_hktv_pg"
- ageHint="14" />
- <rating-definition id="HK_TV_M"
- displayName="@string/display_name_hktv_m"
- description="@string/description_hktv_m"
- ageHint="18" />
- <order>
- <rating id="HK_TV_G" />
- <rating id="HK_TV_PG" />
- <rating id="HK_TV_M" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for HU TV -->
- <rating-system-definition id="HU_TV"
- displayName="@string/display_name_hutv"
- country="HU">
- <rating-definition id="HU_TV_U"
- displayName="@string/display_name_hutv_u"
- description="@string/description_hutv_u"
- ageHint="0" />
- <rating-definition id="HU_TV_CF"
- displayName="@string/display_name_hutv_cf"
- description="@string/description_hutv_cf"
- ageHint="0" />
- <rating-definition id="HU_TV_6"
- displayName="@string/display_name_hutv_6"
- description="@string/description_hutv_6"
- ageHint="6" />
- <rating-definition id="HU_TV_12"
- displayName="@string/display_name_hutv_12"
- description="@string/description_hutv_12"
- ageHint="12" />
- <rating-definition id="HU_TV_16"
- displayName="@string/display_name_hutv_16"
- description="@string/description_hutv_16"
- ageHint="16" />
- <rating-definition id="HU_TV_18"
- displayName="@string/display_name_hutv_18"
- description="@string/description_hutv_18"
- ageHint="18" />
- <order>
- <rating id="HU_TV_U" />
- <rating id="HU_TV_CF" />
- <rating id="HU_TV_6" />
- <rating id="HU_TV_12" />
- <rating id="HU_TV_16" />
- <rating id="HU_TV_18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for ID TV -->
- <rating-system-definition id="ID_TV"
- displayName="@string/display_name_idtv"
- country="ID">
- <rating-definition id="ID_TV_P"
- displayName="@string/display_name_idtv_p"
- description="@string/description_idtv_p"
- ageHint="2" />
- <rating-definition id="ID_TV_A"
- displayName="@string/display_name_idtv_a"
- description="@string/description_idtv_a"
- ageHint="7" />
- <rating-definition id="ID_TV_A_BO"
- displayName="@string/display_name_idtv_a_bo"
- description="@string/description_idtv_a_bo"
- ageHint="10" />
- <rating-definition id="ID_TV_SU"
- displayName="@string/display_name_idtv_su"
- description="@string/description_idtv_su"
- ageHint="0" />
- <rating-definition id="ID_TV_BO"
- displayName="@string/display_name_idtv_bo"
- description="@string/description_idtv_bo"
- ageHint="5" />
- <rating-definition id="ID_TV_R"
- displayName="@string/display_name_idtv_r"
- description="@string/description_idtv_r"
- ageHint="13" />
- <rating-definition id="ID_TV_R_BO"
- displayName="@string/display_name_idtv_r_bo"
- description="@string/description_idtv_r_bo"
- ageHint="18" />
- <rating-definition id="ID_TV_D"
- displayName="@string/display_name_idtv_d"
- description="@string/description_idtv_d"
- ageHint="18" />
- <order>
- <rating id="ID_TV_P" />
- <rating id="ID_TV_A" />
- <rating id="ID_TV_A_BO" />
- </order>
- <order>
- <rating id="ID_TV_SU" />
- <rating id="ID_TV_BO" />
- <rating id="ID_TV_R" />
- <rating id="ID_TV_R_BO" />
- <rating id="ID_TV_D" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for IE TV -->
- <rating-system-definition id="IE_TV"
- displayName="@string/display_name_ietv"
- country="IE">
- <rating-definition id="IE_TV_GA"
- displayName="@string/display_name_ietv_ga"
- description="@string/description_ietv_ga"
- ageHint="0" />
- <rating-definition id="IE_TV_Ch"
- displayName="@string/display_name_ietv_ch"
- description="@string/description_ietv_ch"
- ageHint="10" />
- <rating-definition id="IE_TV_YA"
- displayName="@string/display_name_ietv_ya"
- description="@string/description_ietv_ya"
- ageHint="13" />
- <rating-definition id="IE_TV_PS"
- displayName="@string/display_name_ietv_ps"
- description="@string/description_ietv_ps"
- ageHint="18" />
- <rating-definition id="IE_TV_MA"
- displayName="@string/display_name_ietv_ma"
- description="@string/description_ietv_ma"
- ageHint="21" />
- <order>
- <rating id="IE_TV_GA" />
- <rating id="IE_TV_Ch" />
- <rating id="IE_TV_YA" />
- <rating id="IE_TV_PS" />
- <rating id="IE_TV_MA" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for IL TV -->
- <rating-system-definition id="IL_TV"
- displayName="@string/display_name_iltv"
- country="IL">
- <rating-definition id="IL_TV_G"
- displayName="@string/display_name_iltv_g"
- description="@string/description_iltv_g"
- ageHint="0" />
- <rating-definition id="IL_TV_12"
- displayName="@string/display_name_iltv_12"
- description="@string/description_iltv_12"
- ageHint="12" />
- <rating-definition id="IL_TV_15"
- displayName="@string/display_name_iltv_15"
- description="@string/description_iltv_15"
- ageHint="15" />
- <rating-definition id="IL_TV_18"
- displayName="@string/display_name_iltv_18"
- description="@string/description_iltv_18"
- ageHint="18" />
- <rating-definition id="IL_TV_E"
- displayName="@string/display_name_iltv_e"
- description="@string/description_iltv_e"
- ageHint="0" />
- <order>
- <rating id="IL_TV_G" />
- <rating id="IL_TV_12" />
- <rating id="IL_TV_15" />
- <rating id="IL_TV_18" />
- <rating id="IL_TV_E" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for IN TV -->
- <rating-system-definition id="IN_TV"
- displayName="@string/display_name_intv"
- country="IN">
- <rating-definition id="IN_TV_U"
- displayName="@string/display_name_intv_u"
- description="@string/description_intv_u"
- ageHint="0" />
- <rating-definition id="IN_TV_U/A"
- displayName="@string/display_name_intv_u/a"
- description="@string/description_intv_u/a"
- ageHint="12" />
- <rating-definition id="IN_TV_A"
- displayName="@string/display_name_intv_a"
- description="@string/description_intv_a"
- ageHint="18" />
- <rating-definition id="IN_TV_S"
- displayName="@string/display_name_intv_s"
- description="@string/description_intv_s"
- ageHint="0" />
- <order>
- <rating id="IN_TV_U" />
- <rating id="IN_TV_U/A" />
- <rating id="IN_TV_A" />
- <rating id="IN_TV_S" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for IS TV -->
- <rating-system-definition id="IS_TV"
- displayName="@string/display_name_istv"
- country="IS">
- <rating-definition id="IS_TV_L"
- displayName="@string/display_name_istv_l"
- description="@string/description_istv_l"
- ageHint="0" />
- <rating-definition id="IS_TV_7"
- displayName="@string/display_name_istv_7"
- description="@string/description_istv_7"
- ageHint="7" />
- <rating-definition id="IS_TV_10"
- displayName="@string/display_name_istv_10"
- description="@string/description_istv_10"
- ageHint="10" />
- <rating-definition id="IS_TV_12"
- displayName="@string/display_name_istv_12"
- description="@string/description_istv_12"
- ageHint="12" />
- <rating-definition id="IS_TV_14"
- displayName="@string/display_name_istv_14"
- description="@string/description_istv_14"
- ageHint="14" />
- <rating-definition id="IS_TV_16"
- displayName="@string/display_name_istv_16"
- description="@string/description_istv_16"
- ageHint="16" />
- <rating-definition id="IS_TV_18"
- displayName="@string/display_name_istv_18"
- description="@string/description_istv_18"
- ageHint="18" />
- <order>
- <rating id="IS_TV_L" />
- <rating id="IS_TV_7" />
- <rating id="IS_TV_10" />
- <rating id="IS_TV_12" />
- <rating id="IS_TV_14" />
- <rating id="IS_TV_16" />
- <rating id="IS_TV_18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for KR TV -->
- <rating-system-definition id="KR_TV"
- displayName="@string/display_name_krtv"
- country="KR">
- <rating-definition id="KR_TV_All"
- displayName="@string/display_name_krtv_all"
- description="@string/description_krtv_all"
- ageHint="0" />
- <rating-definition id="KR_TV_7"
- displayName="@string/display_name_krtv_7"
- description="@string/description_krtv_7"
- ageHint="7" />
- <rating-definition id="KR_TV_12"
- displayName="@string/display_name_krtv_12"
- description="@string/description_krtv_12"
- ageHint="12" />
- <rating-definition id="KR_TV_15"
- displayName="@string/display_name_krtv_15"
- description="@string/description_krtv_15"
- ageHint="15" />
- <rating-definition id="KR_TV_19"
- displayName="@string/display_name_krtv_19"
- description="@string/description_krtv_19"
- ageHint="19" />
- <order>
- <rating id="KR_TV_All" />
- <rating id="KR_TV_7" />
- <rating id="KR_TV_12" />
- <rating id="KR_TV_15" />
- <rating id="KR_TV_19" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for MV TV -->
- <rating-system-definition id="MV_TV"
- displayName="@string/display_name_mvtv"
- country="MV">
- <rating-definition id="MV_TV_Y"
- displayName="@string/display_name_mvtv_y"
- description="@string/description_mvtv_y"
- ageHint="0" />
- <rating-definition id="MV_TV_G"
- displayName="@string/display_name_mvtv_g"
- description="@string/description_mvtv_g"
- ageHint="0" />
- <rating-definition id="MV_TV_PG"
- displayName="@string/display_name_mvtv_pg"
- description="@string/description_mvtv_pg"
- ageHint="0" />
- <rating-definition id="MV_TV_PG-12"
- displayName="@string/display_name_mvtv_pg-12"
- description="@string/description_mvtv_pg-12"
- ageHint="12" />
- <rating-definition id="MV_TV_12"
- displayName="@string/display_name_mvtv_12"
- description="@string/description_mvtv_12"
- ageHint="12" />
- <rating-definition id="MV_TV_15"
- displayName="@string/display_name_mvtv_15"
- description="@string/description_mvtv_15"
- ageHint="15" />
- <rating-definition id="MV_TV_18"
- displayName="@string/display_name_mvtv_18"
- description="@string/description_mvtv_18"
- ageHint="18" />
- <rating-definition id="MV_TV_21"
- displayName="@string/display_name_mvtv_21"
- description="@string/description_mvtv_21"
- ageHint="21" />
- <rating-definition id="MV_TV_X"
- displayName="@string/display_name_mvtv_x"
- description="@string/description_mvtv_x"
- ageHint="25" />
- <order>
- <rating id="MV_TV_Y" />
- <rating id="MV_TV_G" />
- <rating id="MV_TV_PG" />
- <rating id="MV_TV_PG-12" />
- <rating id="MV_TV_12" />
- <rating id="MV_TV_15" />
- <rating id="MV_TV_18" />
- <rating id="MV_TV_21" />
- <rating id="MV_TV_X" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for MX TV -->
- <rating-system-definition id="MX_TV"
- displayName="@string/display_name_mxtv"
- country="MX">
- <rating-definition id="MX_TV_A"
- displayName="@string/display_name_mxtv_a"
- description="@string/description_mxtv_a"
- ageHint="7" />
- <rating-definition id="MX_TV_B"
- displayName="@string/display_name_mxtv_b"
- description="@string/description_mxtv_b"
- ageHint="12" />
- <rating-definition id="MX_TV_B-15"
- displayName="@string/display_name_mxtv_b-15"
- description="@string/description_mxtv_b-15"
- ageHint="15" />
- <rating-definition id="MX_TV_C"
- displayName="@string/display_name_mxtv_c"
- description="@string/description_mxtv_c"
- ageHint="18" />
- <rating-definition id="MX_TV_D"
- displayName="@string/display_name_mxtv_d"
- description="@string/description_mxtv_d"
- ageHint="21" />
- <rating-definition id="MX_TV_RC"
- displayName="@string/display_name_mxtv_rc"
- description="@string/description_mxtv_rc"
- ageHint="0" />
- <order>
- <rating id="MX_TV_A" />
- <rating id="MX_TV_B" />
- <rating id="MX_TV_B-15" />
- <rating id="MX_TV_C" />
- <rating id="MX_TV_D" />
- <rating id="MX_TV_RC" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for MY TV -->
- <rating-system-definition id="MY_TV"
- displayName="@string/display_name_mytv"
- country="MY">
- <rating-definition id="MY_TV_U"
- displayName="@string/display_name_mytv_u"
- description="@string/description_mytv_u"
- ageHint="0" />
- <rating-definition id="MY_TV_P13"
- displayName="@string/display_name_mytv_p13"
- description="@string/description_mytv_p13"
- ageHint="13" />
- <rating-definition id="MY_TV_18"
- displayName="@string/display_name_mytv_18"
- description="@string/description_mytv_18"
- ageHint="18" />
- <order>
- <rating id="MY_TV_U" />
- <rating id="MY_TV_P13" />
- <rating id="MY_TV_18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for NL TV -->
- <rating-system-definition id="NL_TV"
- displayName="@string/display_name_nltv"
- country="NL">
- <sub-rating-definition id="NL_TV_V"
- displayName="@string/display_name_nltv_v"
- description="@string/description_nltv_v" />
- <sub-rating-definition id="NL_TV_F"
- displayName="@string/display_name_nltv_f"
- description="@string/description_nltv_f" />
- <sub-rating-definition id="NL_TV_S"
- displayName="@string/display_name_nltv_s"
- description="@string/description_nltv_s" />
- <sub-rating-definition id="NL_TV_D"
- displayName="@string/display_name_nltv_d"
- description="@string/description_nltv_d" />
- <sub-rating-definition id="NL_TV_DA"
- displayName="@string/display_name_nltv_da"
- description="@string/description_nltv_da" />
- <sub-rating-definition id="NL_TV_L"
- displayName="@string/display_name_nltv_l"
- description="@string/description_nltv_l" />
-
- <rating-definition id="NL_TV_AL"
- displayName="@string/display_name_nltv_al"
- description="@string/description_nltv_al"
- ageHint="0">
- <sub-rating id="NL_TV_V" />
- <sub-rating id="NL_TV_F" />
- <sub-rating id="NL_TV_S" />
- <sub-rating id="NL_TV_D" />
- <sub-rating id="NL_TV_DA" />
- <sub-rating id="NL_TV_L" />
- </rating-definition>
- <rating-definition id="NL_TV_6"
- displayName="@string/display_name_nltv_6"
- description="@string/description_nltv_6"
- ageHint="6">
- <sub-rating id="NL_TV_V" />
- <sub-rating id="NL_TV_F" />
- <sub-rating id="NL_TV_S" />
- <sub-rating id="NL_TV_D" />
- <sub-rating id="NL_TV_DA" />
- <sub-rating id="NL_TV_L" />
- </rating-definition>
- <rating-definition id="NL_TV_9"
- displayName="@string/display_name_nltv_9"
- description="@string/description_nltv_9"
- ageHint="9">
- <sub-rating id="NL_TV_V" />
- <sub-rating id="NL_TV_F" />
- <sub-rating id="NL_TV_S" />
- <sub-rating id="NL_TV_D" />
- <sub-rating id="NL_TV_DA" />
- <sub-rating id="NL_TV_L" />
- </rating-definition>
- <rating-definition id="NL_TV_12"
- displayName="@string/display_name_nltv_12"
- description="@string/description_nltv_12"
- ageHint="12">
- <sub-rating id="NL_TV_V" />
- <sub-rating id="NL_TV_F" />
- <sub-rating id="NL_TV_S" />
- <sub-rating id="NL_TV_D" />
- <sub-rating id="NL_TV_DA" />
- <sub-rating id="NL_TV_L" />
- </rating-definition>
- <rating-definition id="NL_TV_16"
- displayName="@string/display_name_nltv_16"
- description="@string/description_nltv_16"
- ageHint="16">
- <sub-rating id="NL_TV_V" />
- <sub-rating id="NL_TV_F" />
- <sub-rating id="NL_TV_S" />
- <sub-rating id="NL_TV_D" />
- <sub-rating id="NL_TV_DA" />
- <sub-rating id="NL_TV_L" />
- </rating-definition>
- <order>
- <rating id="NL_TV_AL" />
- <rating id="NL_TV_6" />
- <rating id="NL_TV_9" />
- <rating id="NL_TV_12" />
- <rating id="NL_TV_16" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for NZ Free-to-Air TV -->
- <rating-system-definition id="NZ_FTV"
- displayName="@string/display_name_nzftv"
- description="@string/description_nzftv"
- country="NZ">
- <rating-definition id="NZ_FTV_G"
- displayName="@string/display_name_nzftv_g"
- description="@string/description_nzftv_g"
- ageHint="0" />
- <rating-definition id="NZ_FTV_PGR"
- displayName="@string/display_name_nzftv_pgr"
- description="@string/description_nzftv_pgr"
- ageHint="14" />
- <rating-definition id="NZ_FTV_AO"
- displayName="@string/display_name_nzftv_ao"
- description="@string/description_nzftv_ao"
- ageHint="18" />
- <order>
- <rating id="NZ_FTV_G" />
- <rating id="NZ_FTV_PGR" />
- <rating id="NZ_FTV_AO" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for NZ Pay Television -->
- <rating-system-definition id="NZ_PTV"
- displayName="@string/display_name_nzptv"
- description="@string/description_nzptv"
- country="NZ">
- <sub-rating-definition id="NZ_PTV_C"
- displayName="@string/display_name_nzptv_c"
- description="@string/description_nzptv_c" />
- <sub-rating-definition id="NZ_PTV_V"
- displayName="@string/display_name_nzptv_v"
- description="@string/description_nzptv_v" />
- <sub-rating-definition id="NZ_PTV_L"
- displayName="@string/display_name_nzptv_l"
- description="@string/description_nzptv_l" />
- <sub-rating-definition id="NZ_PTV_S"
- displayName="@string/display_name_nzptv_s"
- description="@string/description_nzptv_s" />
- <rating-definition id="NZ_PTV_G"
- displayName="@string/display_name_nzptv_g"
- description="@string/description_nzptv_g"
- ageHint="0" />
- <rating-definition id="NZ_PTV_PG"
- displayName="@string/display_name_nzptv_pg"
- description="@string/description_nzptv_pg"
- ageHint="10">
- <sub-rating id="NZ_PTV_C" />
- <sub-rating id="NZ_PTV_V" />
- <sub-rating id="NZ_PTV_L" />
- <sub-rating id="NZ_PTV_S" />
- </rating-definition>
- <rating-definition id="NZ_PTV_M"
- displayName="@string/display_name_nzptv_m"
- description="@string/description_nzptv_m"
- ageHint="13">
- <sub-rating id="NZ_PTV_C" />
- <sub-rating id="NZ_PTV_V" />
- <sub-rating id="NZ_PTV_L" />
- <sub-rating id="NZ_PTV_S" />
- </rating-definition>
- <rating-definition id="NZ_PTV_16"
- displayName="@string/display_name_nzptv_16"
- description="@string/description_nzptv_16"
- ageHint="16">
- <sub-rating id="NZ_PTV_C" />
- <sub-rating id="NZ_PTV_V" />
- <sub-rating id="NZ_PTV_L" />
- <sub-rating id="NZ_PTV_S" />
- </rating-definition>
- <rating-definition id="NZ_PTV_18"
- displayName="@string/display_name_nzptv_18"
- description="@string/description_nzptv_18"
- ageHint="18">
- <sub-rating id="NZ_PTV_C" />
- <sub-rating id="NZ_PTV_V" />
- <sub-rating id="NZ_PTV_L" />
- <sub-rating id="NZ_PTV_S" />
- </rating-definition>
- <order>
- <rating id="NZ_PTV_G" />
- <rating id="NZ_PTV_PG" />
- <rating id="NZ_PTV_M" />
- <rating id="NZ_PTV_16" />
- <rating id="NZ_PTV_18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for PE TV -->
- <rating-system-definition id="PE_TV"
- displayName="@string/display_name_petv"
- description="@string/description_petv"
- country="PE">
- <rating-definition id="PE_TV_A"
- displayName="@string/display_name_petv_a"
- description="@string/description_petv_a"
- ageHint="0" />
- <rating-definition id="PE_TV_14"
- displayName="@string/display_name_petv_14"
- description="@string/description_petv_14"
- ageHint="14" />
- <rating-definition id="PE_TV_18"
- displayName="@string/display_name_petv_18"
- description="@string/description_petv_18"
- ageHint="18" />
- <order>
- <rating id="PE_TV_A" />
- <rating id="PE_TV_14" />
- <rating id="PE_TV_18" />
- </order>
- </rating-system-definition>
-
- <rating-system-definition id="PE_ATV"
- displayName="@string/display_name_peatv"
- description="@string/description_peatv"
- country="PE">
- <rating-definition id="PE_ATV_GP"
- displayName="@string/display_name_peatv_gp"
- description="@string/description_peatv_gp"
- ageHint="0" />
- <rating-definition id="PE_ATV_PG"
- displayName="@string/display_name_peatv_pg"
- description="@string/description_peatv_pg"
- ageHint="6" />
- <rating-definition id="PE_ATV_14"
- displayName="@string/display_name_peatv_14"
- description="@string/description_peatv_14"
- ageHint="14" />
- <rating-definition id="PE_ATV_18"
- displayName="@string/display_name_peatv_18"
- description="@string/description_peatv_18"
- ageHint="18" />
- <order>
- <rating id="PE_ATV_GP" />
- <rating id="PE_ATV_PG" />
- <rating id="PE_ATV_14" />
- <rating id="PE_ATV_18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for PH TV -->
- <rating-system-definition id="PH_TV"
- displayName="@string/display_name_phtv"
- country="PH">
- <rating-definition id="PH_TV_G"
- displayName="@string/display_name_phtv_g"
- description="@string/description_phtv_g"
- ageHint="0" />
- <rating-definition id="PH_TV_PG"
- displayName="@string/display_name_phtv_pg"
- description="@string/description_phtv_pg"
- ageHint="14" />
- <rating-definition id="PH_TV_SPG"
- displayName="@string/display_name_phtv_spg"
- description="@string/description_phtv_spg"
- ageHint="18" />
- <order>
- <rating id="PH_TV_G" />
- <rating id="PH_TV_PG" />
- <rating id="PH_TV_SPG" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for PL TV -->
- <rating-system-definition id="PL_TV"
- displayName="@string/display_name_pltv"
- country="PL">
- <rating-definition id="PL_TV_G"
- displayName="@string/display_name_pltv_g"
- description="@string/description_pltv_g"
- ageHint="0" />
- <rating-definition id="PL_TV_7"
- displayName="@string/display_name_pltv_7"
- description="@string/description_pltv_7"
- ageHint="7" />
- <rating-definition id="PL_TV_12"
- displayName="@string/display_name_pltv_12"
- description="@string/description_pltv_12"
- ageHint="12" />
- <rating-definition id="PL_TV_16"
- displayName="@string/display_name_pltv_16"
- description="@string/description_pltv_16"
- ageHint="16" />
- <rating-definition id="PL_TV_18"
- displayName="@string/display_name_pltv_18"
- description="@string/description_pltv_18"
- ageHint="18" />
- <order>
- <rating id="PL_TV_G" />
- <rating id="PL_TV_7" />
- <rating id="PL_TV_12" />
- <rating id="PL_TV_16" />
- <rating id="PL_TV_18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for PT TV -->
- <rating-system-definition id="PT_TV"
- displayName="@string/display_name_pttv"
- country="PT">
- <rating-definition id="PT_TV_T"
- displayName="@string/display_name_pttv_t"
- description="@string/description_pttv_t"
- ageHint="0" />
- <rating-definition id="PT_TV_10"
- displayName="@string/display_name_pttv_10"
- description="@string/description_pttv_10"
- ageHint="10" />
- <rating-definition id="PT_TV_12"
- displayName="@string/display_name_pttv_12"
- description="@string/description_pttv_12"
- ageHint="12" />
- <rating-definition id="PT_TV_16"
- displayName="@string/display_name_pttv_16"
- description="@string/description_pttv_16"
- ageHint="16" />
- <order>
- <rating id="PT_TV_T" />
- <rating id="PT_TV_10" />
- <rating id="PT_TV_12" />
- <rating id="PT_TV_16" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for RO TV -->
- <rating-system-definition id="RO_TV"
- displayName="@string/display_name_rotv"
- country="RO">
- <rating-definition id="RO_TV_Y"
- displayName="@string/display_name_rotv_y"
- description="@string/description_rotv_y"
- ageHint="0" />
- <rating-definition id="RO_TV_G"
- displayName="@string/display_name_rotv_g"
- description="@string/description_rotv_g"
- ageHint="0" />
- <rating-definition id="RO_TV_AP"
- displayName="@string/display_name_rotv_ap"
- description="@string/description_rotv_ap"
- ageHint="12" />
- <rating-definition id="RO_TV_12"
- displayName="@string/display_name_rotv_12"
- description="@string/description_rotv_12"
- ageHint="12" />
- <rating-definition id="RO_TV_15"
- displayName="@string/display_name_rotv_15"
- description="@string/description_rotv_15"
- ageHint="15" />
- <rating-definition id="RO_TV_18"
- displayName="@string/display_name_rotv_18"
- description="@string/description_rotv_18"
- ageHint="18" />
- <order>
- <rating id="RO_TV_Y" />
- <rating id="RO_TV_G" />
- <rating id="RO_TV_AP" />
- <rating id="RO_TV_12" />
- <rating id="RO_TV_15" />
- <rating id="RO_TV_18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for RU TV -->
- <rating-system-definition id="RU_TV"
- displayName="@string/display_name_rutv"
- country="RU">
- <rating-definition id="RU_TV_0"
- displayName="@string/display_name_rutv_0"
- description="@string/description_rutv_0"
- ageHint="0" />
- <rating-definition id="RU_TV_6"
- displayName="@string/display_name_rutv_6"
- description="@string/description_rutv_6"
- ageHint="6" />
- <rating-definition id="RU_TV_12"
- displayName="@string/display_name_rutv_12"
- description="@string/description_rutv_12"
- ageHint="12" />
- <rating-definition id="RU_TV_16"
- displayName="@string/display_name_rutv_16"
- description="@string/description_rutv_16"
- ageHint="16" />
- <rating-definition id="RU_TV_18"
- displayName="@string/display_name_rutv_18"
- description="@string/description_rutv_18"
- ageHint="18" />
- <order>
- <rating id="RU_TV_0" />
- <rating id="RU_TV_6" />
- <rating id="RU_TV_12" />
- <rating id="RU_TV_16" />
- <rating id="RU_TV_18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for RS TV -->
- <rating-system-definition id="RS_TV"
- displayName="@string/display_name_rstv"
- country="RS">
- <rating-definition id="RS_TV_G"
- displayName="@string/display_name_rstv_g"
- description="@string/description_rstv_g"
- ageHint="0" />
- <rating-definition id="RS_TV_12"
- displayName="@string/display_name_rstv_12"
- description="@string/description_rstv_12"
- ageHint="12" />
- <rating-definition id="RS_TV_14"
- displayName="@string/display_name_rstv_14"
- description="@string/description_rstv_14"
- ageHint="14" />
- <rating-definition id="RS_TV_15"
- displayName="@string/display_name_rstv_15"
- description="@string/description_rstv_15"
- ageHint="15" />
- <rating-definition id="RS_TV_16"
- displayName="@string/display_name_rstv_16"
- description="@string/description_rstv_16"
- ageHint="16" />
- <rating-definition id="RS_TV_17"
- displayName="@string/display_name_rstv_17"
- description="@string/description_rstv_17"
- ageHint="17" />
- <rating-definition id="RS_TV_18"
- displayName="@string/display_name_rstv_18"
- description="@string/description_rstv_18"
- ageHint="18" />
- <order>
- <rating id="RS_TV_G" />
- <rating id="RS_TV_12" />
- <rating id="RS_TV_14" />
- <rating id="RS_TV_15" />
- <rating id="RS_TV_16" />
- <rating id="RS_TV_17" />
- <rating id="RS_TV_18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for SG Free-to-Air TV -->
- <rating-system-definition id="SG_FTV"
- displayName="@string/display_name_sgftv"
- country="SG">
- <rating-definition id="SG_FTV_PG"
- displayName="@string/display_name_sgftv_pg"
- description="@string/description_sgftv_pg"
- ageHint="0" />
- <rating-definition id="SG_FTV_PG13"
- displayName="@string/display_name_sgftv_pg13"
- description="@string/description_sgftv_pg13"
- ageHint="13" />
- <order>
- <rating id="SG_FTV_PG" />
- <rating id="SG_FTV_PG13" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for SG Pay TV -->
- <rating-system-definition id="SG_PTV"
- displayName="@string/display_name_sgptv"
- country="SG">
- <rating-definition id="SG_PTV_NC16"
- displayName="@string/display_name_sgptv_nc16"
- description="@string/description_sgptv_nc16"
- ageHint="16" />
- <rating-definition id="SG_PTV_M18"
- displayName="@string/display_name_sgptv_m18"
- description="@string/description_sgptv_m18"
- ageHint="18" />
- <order>
- <rating id="SG_PTV_NC16" />
- <rating id="SG_PTV_M18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for SI TV -->
- <rating-system-definition id="SI_TV"
- displayName="@string/display_name_sitv"
- country="SI">
- <rating-definition id="SI_TV_VS"
- displayName="@string/display_name_sitv_vs"
- description="@string/description_sitv_vs"
- ageHint="6" />
- <rating-definition id="SI_TV_12"
- displayName="@string/display_name_sitv_12"
- description="@string/description_sitv_12"
- ageHint="12" />
- <rating-definition id="SI_TV_15"
- displayName="@string/display_name_sitv_15"
- description="@string/description_sitv_15"
- ageHint="15" />
- <rating-definition id="SI_TV_AD"
- displayName="@string/display_name_sitv_ad"
- description="@string/description_sitv_ad"
- ageHint="0" />
- <order>
- <rating id="SI_TV_VS" />
- <rating id="SI_TV_12" />
- <rating id="SI_TV_15" />
- <rating id="SI_TV_AD" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for TH TV -->
- <rating-system-definition id="TH_TV"
- displayName="@string/display_name_thtv"
- country="TH">
- <rating-definition id="TH_TV_P"
- displayName="@string/display_name_thtv_primary"
- description="@string/description_thtv_primary"
- ageHint="0" />
- <rating-definition id="TH_TV_C"
- displayName="@string/display_name_thtv_children"
- description="@string/description_thtv_children"
- ageHint="6" />
- <rating-definition id="TH_TV_G"
- displayName="@string/display_name_thtv_general"
- description="@string/description_thtv_general"
- ageHint="0" />
- <rating-definition id="TH_TV_PG13"
- displayName="@string/display_name_thtv_pg13"
- description="@string/description_thtv_pg13"
- ageHint="13" />
- <rating-definition id="TH_TV_PG18"
- displayName="@string/display_name_thtv_pg18"
- description="@string/description_thtv_pg18"
- ageHint="18" />
- <rating-definition id="TH_TV_A"
- displayName="@string/display_name_thtv_adults"
- description="@string/description_thtv_adults"
- ageHint="18" />
- <order>
- <rating id="TH_TV_P" />
- <rating id="TH_TV_C" />
- </order>
- <order>
- <rating id="TH_TV_G" />
- <rating id="TH_TV_PG13" />
- <rating id="TH_TV_PG18" />
- <rating id="TH_TV_A" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for TR TV -->
- <rating-system-definition id="TR_TV"
- displayName="@string/display_name_trtv"
- country="TR">
- <rating-definition id="TR_TV_G"
- displayName="@string/display_name_trtv_g"
- description="@string/description_trtv_g"
- ageHint="0" />
- <rating-definition id="TR_TV_7"
- displayName="@string/display_name_trtv_7"
- description="@string/description_trtv_7"
- ageHint="7" />
- <rating-definition id="TR_TV_13"
- displayName="@string/display_name_trtv_13"
- description="@string/description_trtv_13"
- ageHint="13" />
- <rating-definition id="TR_TV_18"
- displayName="@string/display_name_trtv_18"
- description="@string/description_trtv_18"
- ageHint="18" />
- <order>
- <rating id="TR_TV_G" />
- <rating id="TR_TV_7" />
- <rating id="TR_TV_13" />
- <rating id="TR_TV_18" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for TW TV -->
- <rating-system-definition id="TW_TV"
- displayName="@string/display_name_twtv"
- country="TW">
- <rating-definition id="TW_TV_G"
- displayName="@string/display_name_twtv_g"
- description="@string/description_twtv_g"
- ageHint="0" />
- <rating-definition id="TW_TV_P"
- displayName="@string/display_name_twtv_p"
- description="@string/description_twtv_p"
- ageHint="6" />
- <rating-definition id="TW_TV_PG"
- displayName="@string/display_name_twtv_pg"
- description="@string/description_twtv_pg"
- ageHint="12" />
- <rating-definition id="TW_TV_R"
- displayName="@string/display_name_twtv_r"
- description="@string/description_twtv_r"
- ageHint="18" />
- <order>
- <rating id="TW_TV_G" />
- <rating id="TW_TV_P" />
- <rating id="TW_TV_PG" />
- <rating id="TW_TV_R" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for UA TV -->
- <rating-system-definition id="UA_TV"
- displayName="@string/display_name_uatv"
- country="UA">
- <rating-definition id="UA_TV_G"
- displayName="@string/display_name_uatv_green circle"
- description="@string/description_uatv_green circle"
- ageHint="0" />
- <rating-definition id="UA_TV_Y"
- displayName="@string/display_name_uatv_yellow triangle"
- description="@string/description_uatv_yellow triangle"
- ageHint="12" />
- <rating-definition id="UA_TV_R"
- displayName="@string/display_name_uatv_red square"
- description="@string/description_uatv_red square"
- ageHint="18" />
- <order>
- <rating id="UA_TV_G" />
- <rating id="UA_TV_Y" />
- <rating id="UA_TV_R" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for US TV -->
- <rating-system-definition id="US_TV"
- displayName="@string/display_name_ustv"
- description="@string/description_ustv"
- country="US">
- <sub-rating-definition id="US_TV_D"
- displayName="@string/display_name_ustv_d"
- description="@string/description_ustv_d" />
- <sub-rating-definition id="US_TV_L"
- displayName="@string/display_name_ustv_l"
- description="@string/description_ustv_l" />
- <sub-rating-definition id="US_TV_S"
- displayName="@string/display_name_ustv_s"
- description="@string/description_ustv_s" />
- <sub-rating-definition id="US_TV_V"
- displayName="@string/display_name_ustv_v"
- description="@string/description_ustv_v" />
- <sub-rating-definition id="US_TV_FV"
- displayName="@string/display_name_ustv_fv"
- description="@string/description_ustv_fv" />
-
- <rating-definition id="US_TV_Y"
- displayName="@string/display_name_ustv_y"
- description="@string/description_ustv_y"
- ageHint="0" />
- <rating-definition id="US_TV_Y7"
- displayName="@string/display_name_ustv_y7"
- description="@string/description_ustv_y7"
- ageHint="7">
- <sub-rating id="US_TV_FV" />
- </rating-definition>
- <rating-definition id="US_TV_G"
- displayName="@string/display_name_ustv_g"
- description="@string/description_ustv_g"
- ageHint="0" />
- <rating-definition id="US_TV_PG"
- displayName="@string/display_name_ustv_pg"
- description="@string/description_ustv_pg"
- ageHint="14">
- <sub-rating id="US_TV_D" />
- <sub-rating id="US_TV_L" />
- <sub-rating id="US_TV_S" />
- <sub-rating id="US_TV_V" />
- </rating-definition>
- <rating-definition id="US_TV_14"
- displayName="@string/display_name_ustv_14"
- description="@string/description_ustv_14"
- ageHint="14">
- <sub-rating id="US_TV_D" />
- <sub-rating id="US_TV_L" />
- <sub-rating id="US_TV_S" />
- <sub-rating id="US_TV_V" />
- </rating-definition>
- <rating-definition id="US_TV_MA"
- displayName="@string/display_name_ustv_ma"
- description="@string/description_ustv_ma"
- ageHint="17">
- <sub-rating id="US_TV_L" />
- <sub-rating id="US_TV_S" />
- <sub-rating id="US_TV_V" />
- </rating-definition>
- <order>
- <rating id="US_TV_Y" />
- <rating id="US_TV_Y7" />
- </order>
- <order>
- <rating id="US_TV_G" />
- <rating id="US_TV_PG" />
- <rating id="US_TV_14" />
- <rating id="US_TV_MA" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for VE TV -->
- <rating-system-definition id="VE_TV"
- displayName="@string/display_name_vetv"
- country="VE">
- <rating-definition id="VE_TV_TU"
- displayName="@string/display_name_vetv_tu"
- description="@string/description_vetv_tu"
- ageHint="0" />
- <rating-definition id="VE_TV_SU"
- displayName="@string/display_name_vetv_su"
- description="@string/description_vetv_su"
- ageHint="15" />
- <rating-definition id="VE_TV_A"
- displayName="@string/display_name_vetv_a"
- description="@string/description_vetv_a"
- ageHint="18" />
- <order>
- <rating id="VE_TV_TU" />
- <rating id="VE_TV_SU" />
- <rating id="VE_TV_A" />
- </order>
- </rating-system-definition>
-
- <!-- TV content rating system for ZA TV -->
- <rating-system-definition id="ZA_TV"
- displayName="@string/display_name_zatv"
- country="ZA">
- <sub-rating-definition id="ZA_TV_D"
- displayName="@string/display_name_zatv_d"
- description="@string/description_zatv_d" />
- <sub-rating-definition id="ZA_TV_V"
- displayName="@string/display_name_zatv_v"
- description="@string/description_zatv_v" />
- <sub-rating-definition id="ZA_TV_N"
- displayName="@string/display_name_zatv_n"
- description="@string/description_zatv_n" />
- <sub-rating-definition id="ZA_TV_P"
- displayName="@string/display_name_zatv_p"
- description="@string/description_zatv_p" />
- <sub-rating-definition id="ZA_TV_S"
- displayName="@string/display_name_zatv_s"
- description="@string/description_zatv_s" />
- <sub-rating-definition id="ZA_TV_L"
- displayName="@string/display_name_zatv_l"
- description="@string/description_zatv_l" />
- <rating-definition id="ZA_TV_F"
- displayName="@string/display_name_zatv_f"
- description="@string/description_zatv_f"
- ageHint="0">
- <sub-rating id="ZA_TV_D" />
- <sub-rating id="ZA_TV_V" />
- <sub-rating id="ZA_TV_N" />
- <sub-rating id="ZA_TV_P" />
- <sub-rating id="ZA_TV_S" />
- <sub-rating id="ZA_TV_L" />
- </rating-definition>
- <rating-definition id="ZA_TV_PG"
- displayName="@string/display_name_zatv_pg"
- description="@string/description_zatv_pg"
- ageHint="0">
- <sub-rating id="ZA_TV_D" />
- <sub-rating id="ZA_TV_V" />
- <sub-rating id="ZA_TV_N" />
- <sub-rating id="ZA_TV_P" />
- <sub-rating id="ZA_TV_S" />
- <sub-rating id="ZA_TV_L" />
- </rating-definition>
- <rating-definition id="ZA_TV_13"
- displayName="@string/display_name_zatv_13"
- description="@string/description_zatv_13"
- ageHint="13">
- <sub-rating id="ZA_TV_D" />
- <sub-rating id="ZA_TV_V" />
- <sub-rating id="ZA_TV_N" />
- <sub-rating id="ZA_TV_P" />
- <sub-rating id="ZA_TV_S" />
- <sub-rating id="ZA_TV_L" />
- </rating-definition>
- <rating-definition id="ZA_TV_16"
- displayName="@string/display_name_zatv_16"
- description="@string/description_zatv_16"
- ageHint="16">
- <sub-rating id="ZA_TV_D" />
- <sub-rating id="ZA_TV_V" />
- <sub-rating id="ZA_TV_N" />
- <sub-rating id="ZA_TV_P" />
- <sub-rating id="ZA_TV_S" />
- <sub-rating id="ZA_TV_L" />
- </rating-definition>
- <rating-definition id="ZA_TV_18"
- displayName="@string/display_name_zatv_18"
- description="@string/description_zatv_18"
- ageHint="18">
- <sub-rating id="ZA_TV_D" />
- <sub-rating id="ZA_TV_V" />
- <sub-rating id="ZA_TV_N" />
- <sub-rating id="ZA_TV_P" />
- <sub-rating id="ZA_TV_S" />
- <sub-rating id="ZA_TV_L" />
- </rating-definition>
- <rating-definition id="ZA_TV_R18"
- displayName="@string/display_name_zatv_r18"
- description="@string/description_zatv_r18"
- ageHint="18">
- <sub-rating id="ZA_TV_D" />
- <sub-rating id="ZA_TV_V" />
- <sub-rating id="ZA_TV_N" />
- <sub-rating id="ZA_TV_P" />
- <sub-rating id="ZA_TV_S" />
- <sub-rating id="ZA_TV_L" />
- </rating-definition>
- <order>
- <rating id="ZA_TV_F" />
- <rating id="ZA_TV_PG" />
- <rating id="ZA_TV_13" />
- <rating id="ZA_TV_16" />
- <rating id="ZA_TV_18" />
- <rating id="ZA_TV_R18" />
- </order>
- </rating-system-definition>
-</rating-system-definitions>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
index 93b16e7..1222c8b 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
@@ -66,7 +66,6 @@
* networkprefixlength.
*/
public class AccessPointParserHelper {
- private static final String TAG = "AccessPointParserHelper";
static final int NONE = 0;
static final int WEP = 1;
static final int PSK = 2;
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java
index 3ec9031..fbaf0f3 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java
@@ -35,14 +35,14 @@
*/
public class ConnectivityManagerStressTestRunner extends InstrumentationTestRunner {
- public int mSoftapIterations = 100;
- public int mScanIterations = 100;
- public int mReconnectIterations = 100;
+ private int mSoftApIterations = 100;
+ private int mScanIterations = 100;
+ private int mReconnectIterations = 100;
// sleep time before restart wifi, default is set to 2 minutes
- public int mSleepTime = 2 * 60 * 1000;
- public String mReconnectSsid = "securenetdhcp";
- public String mReconnectPassword = "androidwifi";
- public boolean mWifiOnlyFlag = false;
+ private long mSleepTime = 2 * 60 * 1000;
+ private String mReconnectSsid = null;
+ private String mReconnectPassword = null;
+ private boolean mWifiOnlyFlag = false;
@Override
public TestSuite getAllTests() {
@@ -60,15 +60,15 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- String valueStr = (String) icicle.get("softap_iterations");
+ String valueStr = icicle.getString("softap_iterations");
if (valueStr != null) {
int iteration = Integer.parseInt(valueStr);
if (iteration > 0) {
- mSoftapIterations = iteration;
+ mSoftApIterations = iteration;
}
}
- String scanIterationStr = (String) icicle.get("scan_iterations");
+ String scanIterationStr = icicle.getString("scan_iterations");
if (scanIterationStr != null) {
int scanIteration = Integer.parseInt(scanIterationStr);
if (scanIteration > 0) {
@@ -76,17 +76,17 @@
}
}
- String ssidStr= (String) icicle.get("reconnect_ssid");
+ String ssidStr= icicle.getString("reconnect_ssid");
if (ssidStr != null) {
mReconnectSsid = ssidStr;
}
- String passwordStr = (String) icicle.get("reconnect_password");
+ String passwordStr = icicle.getString("reconnect_password");
if (passwordStr != null) {
mReconnectPassword = passwordStr;
}
- String reconnectStr = (String) icicle.get("reconnect_iterations");
+ String reconnectStr = icicle.getString("reconnect_iterations");
if (reconnectStr != null) {
int iteration = Integer.parseInt(reconnectStr);
if (iteration > 0) {
@@ -94,7 +94,7 @@
}
}
- String sleepTimeStr = (String) icicle.get("sleep_time");
+ String sleepTimeStr = icicle.getString("sleep_time");
if (sleepTimeStr != null) {
int sleepTime = Integer.parseInt(sleepTimeStr);
if (sleepTime > 0) {
@@ -102,9 +102,37 @@
}
}
- String wifiOnlyFlag = (String) icicle.get("wifi-only");
+ String wifiOnlyFlag = icicle.getString("wifi-only");
if (wifiOnlyFlag != null) {
mWifiOnlyFlag = true;
}
}
+
+ public int getSoftApInterations() {
+ return mSoftApIterations;
+ }
+
+ public int getScanIterations() {
+ return mScanIterations;
+ }
+
+ public int getReconnectIterations() {
+ return mReconnectIterations;
+ }
+
+ public boolean isWifiOnly() {
+ return mWifiOnlyFlag;
+ }
+
+ public long getSleepTime() {
+ return mSleepTime;
+ }
+
+ public String getReconnectSsid() {
+ return mReconnectSsid;
+ }
+
+ public String getReconnectPassword() {
+ return mReconnectPassword;
+ }
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
index 30eda75..0f9d8e9 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
@@ -17,31 +17,28 @@
package com.android.connectivitymanagertest;
import android.app.KeyguardManager;
-import android.content.Context;
import android.content.BroadcastReceiver;
+import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
+import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiManager;
import android.net.wifi.WifiConfiguration.KeyMgmt;
-import android.os.Handler;
-import android.os.Message;
+import android.net.wifi.WifiManager;
import android.os.PowerManager;
import android.os.SystemClock;
import android.test.InstrumentationTestCase;
import android.util.Log;
import android.view.KeyEvent;
-import com.android.internal.util.AsyncChannel;
-
import java.io.IOException;
import java.io.InputStream;
import java.net.UnknownHostException;
-import java.util.ArrayList;
import java.util.List;
+import java.util.regex.Pattern;
/**
@@ -55,51 +52,39 @@
*/
public class ConnectivityManagerTestBase extends InstrumentationTestCase {
- public static final String LOG_TAG = "ConnectivityManagerTestBase";
- public static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; //10 seconds
- public static final int WIFI_SCAN_TIMEOUT = 50 * 1000; // 50 seconds
- public static final int SHORT_TIMEOUT = 5 * 1000; // 5 seconds
- public static final long LONG_TIMEOUT = 50 * 1000; // 50 seconds
- public static final long WIFI_CONNECTION_TIMEOUT = 5 * 60 * 1000; // 5 minutes
- // 2 minutes timer between wifi stop and start
- public static final long WIFI_STOP_START_INTERVAL = 2 * 60 * 1000; // 2 minutes
- // Set ping test timer to be 3 minutes
- public static final long PING_TIMER = 3 * 60 *1000; // 3 minutes
- public static final int SUCCESS = 0; // for Wifi tethering state change
- public static final int FAILURE = 1;
- public static final int INIT = -1;
+ private static final String LOG_TAG = "ConnectivityManagerTestBase";
private static final String ACCESS_POINT_FILE = "accesspoints.xml";
- public ConnectivityReceiver mConnectivityReceiver = null;
- public WifiReceiver mWifiReceiver = null;
+ private static final String PING_IP_ADDR = "8.8.8.8";
+
+ protected static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; //10 seconds
+ protected static final int WIFI_SCAN_TIMEOUT = 50 * 1000; // 50 seconds
+ protected static final int SHORT_TIMEOUT = 5 * 1000; // 5 seconds
+ protected static final long LONG_TIMEOUT = 50 * 1000; // 50 seconds
+ protected static final long WIFI_CONNECTION_TIMEOUT = 5 * 60 * 1000; // 5 minutes
+ // 2 minutes timer between wifi stop and start
+ protected static final long WIFI_STOP_START_INTERVAL = 2 * 60 * 1000; // 2 minutes
+ // Set ping test timer to be 3 minutes
+ protected static final long PING_TIMER = 3 * 60 *1000; // 3 minutes
+ protected static final int SUCCESS = 0; // for Wifi tethering state change
+ protected static final int FAILURE = 1;
+ protected static final int INIT = -1;
+
+ private ConnectivityReceiver mConnectivityReceiver = null;
+ private WifiReceiver mWifiReceiver = null;
private AccessPointParserHelper mParseHelper = null;
- /*
- * Track network connectivity information
- */
- public State mState;
- public NetworkInfo mNetworkInfo;
- public NetworkInfo mOtherNetworkInfo;
- public boolean mIsFailOver;
- public String mReason;
- public boolean mScanResultIsAvailable = false;
- public ConnectivityManager mCM;
- public Object wifiObject = new Object();
- public Object connectivityObject = new Object();
- public int mWifiState;
- public NetworkInfo mWifiNetworkInfo;
- public String mBssid;
- public String mPowerSsid = "opennet"; //Default power SSID
+
+ private long mLastConnectivityChangeTime = -1;
+ protected ConnectivityManager mCm;
private Context mContext;
- public boolean scanResultAvailable = false;
+ protected List<ScanResult> mLastScanResult;
+ protected Object mWifiScanResultLock = new Object();
/* Control Wifi States */
public WifiManager mWifiManager;
- /* Verify connectivity state */
- public static final int NUM_NETWORK_TYPES = ConnectivityManager.MAX_NETWORK_TYPE + 1;
- NetworkState[] connectivityState = new NetworkState[NUM_NETWORK_TYPES];
- // For wifi tethering tests
- private String[] mWifiRegexs;
- public int mWifiTetherResult = INIT; // -1 is initialization state
+ protected long getLastConnectivityChangeTime() {
+ return mLastConnectivityChangeTime;
+ }
/**
* A wrapper of a broadcast receiver which provides network connectivity information
@@ -108,40 +93,12 @@
private class ConnectivityReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- log("ConnectivityReceiver: onReceive() is called with " + intent);
+ mLastConnectivityChangeTime = SystemClock.uptimeMillis();
+ log("ConnectivityReceiver: " + intent);
String action = intent.getAction();
if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
Log.v("ConnectivityReceiver", "onReceive() called with " + intent);
- return;
}
-
- boolean noConnectivity =
- intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
-
- if (noConnectivity) {
- mState = State.DISCONNECTED;
- } else {
- mState = State.CONNECTED;
- }
-
- mNetworkInfo = (NetworkInfo)
- intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
-
- mOtherNetworkInfo = (NetworkInfo)
- intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
-
- mReason = intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
- mIsFailOver = intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);
-
- log("mNetworkInfo: " + mNetworkInfo.toString());
- if (mOtherNetworkInfo != null) {
- log("mOtherNetworkInfo: " + mOtherNetworkInfo.toString());
- }
- recordNetworkState(mNetworkInfo.getType(), mNetworkInfo.getState());
- if (mOtherNetworkInfo != null) {
- recordNetworkState(mOtherNetworkInfo.getType(), mOtherNetworkInfo.getState());
- }
- notifyNetworkConnectivityChange();
}
}
@@ -152,62 +109,21 @@
Log.v("WifiReceiver", "onReceive() is calleld with " + intent);
if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
log("scan results are available");
- notifyScanResult();
- } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
- mWifiNetworkInfo =
- (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
- log("mWifiNetworkInfo: " + mWifiNetworkInfo.toString());
- if (mWifiNetworkInfo.getState() == State.CONNECTED) {
- mBssid = intent.getStringExtra(WifiManager.EXTRA_BSSID);
+ synchronized (mWifiScanResultLock) {
+ mLastScanResult = mWifiManager.getScanResults();
+ mWifiScanResultLock.notifyAll();
}
- notifyWifiState();
- } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
- mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
- WifiManager.WIFI_STATE_UNKNOWN);
- notifyWifiState();
- } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
- notifyWifiAPState();
- } else if (action.equals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED)) {
- ArrayList<String> available = intent.getStringArrayListExtra(
- ConnectivityManager.EXTRA_AVAILABLE_TETHER);
- ArrayList<String> active = intent.getStringArrayListExtra(
- ConnectivityManager.EXTRA_ACTIVE_TETHER);
- ArrayList<String> errored = intent.getStringArrayListExtra(
- ConnectivityManager.EXTRA_ERRORED_TETHER);
- updateTetherState(available.toArray(), active.toArray(), errored.toArray());
- }
- else {
- return;
- }
- }
- }
-
- private class WifiServiceHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
- if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
- //AsyncChannel in msg.obj
- } else {
- log("Failed to establish AsyncChannel connection");
- }
- break;
- default:
- //Ignore
- break;
}
}
}
@Override
- public void setUp() throws Exception {
- mState = State.UNKNOWN;
- scanResultAvailable = false;
+ protected void setUp() throws Exception {
+ mLastScanResult = null;
mContext = getInstrumentation().getContext();
// Get an instance of ConnectivityManager
- mCM = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ mCm = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
// Get an instance of WifiManager
mWifiManager =(WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);
@@ -217,8 +133,6 @@
log("Disable soft ap");
}
- initializeNetworkStates();
-
// register a connectivity receiver for CONNECTIVITY_ACTION;
mConnectivityReceiver = new ConnectivityReceiver();
mContext.registerReceiver(mConnectivityReceiver,
@@ -236,211 +150,73 @@
log("Clear Wifi before we start the test.");
removeConfiguredNetworksAndDisableWifi();
- mWifiRegexs = mCM.getTetherableWifiRegexs();
}
- public List<WifiConfiguration> loadNetworkConfigurations() throws Exception {
+ protected List<WifiConfiguration> loadNetworkConfigurations() throws Exception {
InputStream in = mContext.getAssets().open(ACCESS_POINT_FILE);
mParseHelper = new AccessPointParserHelper(in);
return mParseHelper.getNetworkConfigurations();
}
- // for each network type, initialize network states to UNKNOWN, and no verification flag is set
- public void initializeNetworkStates() {
- for (int networkType = NUM_NETWORK_TYPES - 1; networkType >=0; networkType--) {
- connectivityState[networkType] = new NetworkState();
- log("Initialize network state for " + networkType + ": " +
- connectivityState[networkType].toString());
- }
- }
-
- // deposit a network state
- public void recordNetworkState(int networkType, State networkState) {
- log("record network state for network " + networkType +
- ", state is " + networkState);
- if (connectivityState == null) {
- log("ConnectivityState is null");
- }
- if (connectivityState[networkType] == null) {
- log("connectivityState[networkType] is null");
- }
- connectivityState[networkType].recordState(networkState);
- }
-
- // set the state transition criteria
- public void setStateTransitionCriteria(int networkType, State initState,
- int transitionDir, State targetState) {
- connectivityState[networkType].setStateTransitionCriteria(
- initState, transitionDir, targetState);
- }
-
- // Validate the states recorded
- public boolean validateNetworkStates(int networkType) {
- log("validate network state for " + networkType + ": ");
- return connectivityState[networkType].validateStateTransition();
- }
-
- // return result from network state validation
- public String getTransitionFailureReason(int networkType) {
- log("get network state transition failure reason for " + networkType + ": " +
- connectivityState[networkType].toString());
- return connectivityState[networkType].getReason();
- }
-
- private void notifyNetworkConnectivityChange() {
- synchronized(connectivityObject) {
- log("notify network connectivity changed");
- connectivityObject.notifyAll();
- }
- }
- private void notifyScanResult() {
- synchronized (this) {
- log("notify that scan results are available");
- scanResultAvailable = true;
- this.notify();
- }
- }
-
- private void notifyWifiState() {
- synchronized (wifiObject) {
- log("notify wifi state changed");
- wifiObject.notify();
- }
- }
-
- private void notifyWifiAPState() {
- synchronized (this) {
- log("notify wifi AP state changed");
- this.notify();
- }
- }
-
- // Update wifi tethering state
- private void updateTetherState(Object[] available, Object[] tethered, Object[] errored) {
- boolean wifiTethered = false;
- boolean wifiErrored = false;
-
- synchronized (this) {
- for (Object obj: tethered) {
- String str = (String)obj;
- for (String tethRex: mWifiRegexs) {
- log("str: " + str +"tethRex: " + tethRex);
- if (str.matches(tethRex)) {
- wifiTethered = true;
- }
- }
- }
-
- for (Object obj: errored) {
- String str = (String)obj;
- for (String tethRex: mWifiRegexs) {
- log("error: str: " + str +"tethRex: " + tethRex);
- if (str.matches(tethRex)) {
- wifiErrored = true;
- }
- }
- }
-
- if (wifiTethered) {
- mWifiTetherResult = SUCCESS; // wifi tethering is successful
- } else if (wifiErrored) {
- mWifiTetherResult = FAILURE; // wifi tethering failed
- }
- log("mWifiTetherResult: " + mWifiTetherResult);
- this.notify();
- }
- }
-
-
- // Wait for network connectivity state: CONNECTING, CONNECTED, SUSPENDED,
- // DISCONNECTING, DISCONNECTED, UNKNOWN
- public boolean waitForNetworkState(int networkType, State expectedState, long timeout) {
- long startTime = System.currentTimeMillis();
+ // wait for network connectivity state: CONNECTING, CONNECTED, SUSPENDED, DISCONNECTING,
+ // DISCONNECTED, UNKNOWN
+ protected boolean waitForNetworkState(int networkType, State expectedState, long timeout) {
+ long startTime = SystemClock.uptimeMillis();
while (true) {
- if ((System.currentTimeMillis() - startTime) > timeout) {
- log("waitForNetworkState time out, the state of network type " + networkType +
- " is: " + mCM.getNetworkInfo(networkType).getState());
- if (mCM.getNetworkInfo(networkType).getState() != expectedState) {
- return false;
- } else {
- // the broadcast has been sent out. the state has been changed.
- log("networktype: " + networkType + " state: " +
- mCM.getNetworkInfo(networkType));
- return true;
- }
- }
- log("Wait for the connectivity state for network: " + networkType +
- " to be " + expectedState.toString());
- synchronized (connectivityObject) {
- try {
- connectivityObject.wait(SHORT_TIMEOUT);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if ((mNetworkInfo.getType() != networkType) ||
- (mNetworkInfo.getState() != expectedState)) {
- log("network state for " + mNetworkInfo.getType() +
- "is: " + mNetworkInfo.getState());
- continue;
- }
+ NetworkInfo ni = mCm.getNetworkInfo(networkType);
+ String niString = ni == null ? "null" : ni.toString();
+ if (ni != null && expectedState.equals(ni.getState())) {
+ log("waitForNetworkState success: " + niString);
return true;
}
+ if ((SystemClock.uptimeMillis() - startTime) > timeout) {
+ log("waitForNetworkState timeout: " + niString);
+ return false;
+ }
+ log("waitForNetworkState interim: " + niString);
+ SystemClock.sleep(SHORT_TIMEOUT);
}
}
- // Wait for Wifi state: WIFI_STATE_DISABLED, WIFI_STATE_DISABLING, WIFI_STATE_ENABLED,
+ // wait for Wifi state: WIFI_STATE_DISABLED, WIFI_STATE_DISABLING, WIFI_STATE_ENABLED,
// WIFI_STATE_ENALBING, WIFI_STATE_UNKNOWN
- public boolean waitForWifiState(int expectedState, long timeout) {
- long startTime = System.currentTimeMillis();
+ protected boolean waitForWifiState(int expectedState, long timeout) {
+ long startTime = SystemClock.uptimeMillis();
while (true) {
- if ((System.currentTimeMillis() - startTime) > timeout) {
- if (mWifiState != expectedState) {
- return false;
- } else {
- return true;
- }
- }
- log("Wait for wifi state to be: " + expectedState);
- synchronized (wifiObject) {
- try {
- wifiObject.wait(SHORT_TIMEOUT);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if (mWifiState != expectedState) {
- log("Wifi state is: " + mWifiState);
- continue;
- }
+ int state = mWifiManager.getWifiState();
+ if (state == expectedState) {
+ log("waitForWifiState success: state=" + state);
return true;
}
+ if ((SystemClock.uptimeMillis() - startTime) > timeout) {
+ log(String.format("waitForWifiState timeout: expected=%d, actual=%d",
+ expectedState, state));
+ return false;
+ }
+ log(String.format("waitForWifiState interim: expected=%d, actual=%d",
+ expectedState, state));
+ SystemClock.sleep(SHORT_TIMEOUT);
}
}
// Wait for Wifi AP state: WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING,
// WIFI_AP_STATE_ENABLED, WIFI_STATE_ENALBING, WIFI_STATE_UNKNOWN
- public boolean waitForWifiAPState(int expectedState, long timeout) {
- long startTime = System.currentTimeMillis();
+ protected boolean waitForWifiApState(int expectedState, long timeout) {
+ long startTime = SystemClock.uptimeMillis();
while (true) {
- if ((System.currentTimeMillis() - startTime) > timeout) {
- if (mWifiManager.getWifiApState() != expectedState) {
- return false;
- } else {
- return true;
- }
- }
- log("Wait for wifi AP state to be: " + expectedState);
- synchronized (wifiObject) {
- try {
- wifiObject.wait(SHORT_TIMEOUT);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if (mWifiManager.getWifiApState() != expectedState) {
- log("Wifi state is: " + mWifiManager.getWifiApState());
- continue;
- }
+ int state = mWifiManager.getWifiApState();
+ if (state == expectedState) {
+ log("waitForWifiAPState success: state=" + state);
return true;
}
+ if ((SystemClock.uptimeMillis() - startTime) > timeout) {
+ log(String.format("waitForWifiAPState timeout: expected=%d, actual=%d",
+ expectedState, state));
+ return false;
+ }
+ log(String.format("waitForWifiAPState interim: expected=%d, actual=%d",
+ expectedState, state));
+ SystemClock.sleep(SHORT_TIMEOUT);
}
}
@@ -450,44 +226,49 @@
* @return SUCCESS if tethering result is successful
* FAILURE if tethering result returns error.
*/
- public int waitForTetherStateChange(long timeout) {
- long startTime = System.currentTimeMillis();
+ protected boolean waitForTetherStateChange(long timeout) {
+ long startTime = SystemClock.uptimeMillis();
+ String[] wifiRegexes = mCm.getTetherableWifiRegexs();
while (true) {
- if ((System.currentTimeMillis() - startTime) > timeout) {
- return mWifiTetherResult;
+ if ((SystemClock.uptimeMillis() - startTime) > timeout) {
+ return false;
}
- log("Wait for wifi tethering result.");
- synchronized (this) {
- try {
- this.wait(SHORT_TIMEOUT);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if (mWifiTetherResult == INIT ) {
- continue;
- } else {
- return mWifiTetherResult;
+ String[] active = mCm.getTetheredIfaces();
+ String[] error = mCm.getTetheringErroredIfaces();
+ for (String iface: active) {
+ for (String regex: wifiRegexes) {
+ if (iface.matches(regex)) {
+ return true;
+ }
}
}
+ for (String iface: error) {
+ for (String regex: wifiRegexes) {
+ if (iface.matches(regex)) {
+ return false;
+ }
+ }
+ }
+ SystemClock.sleep(SHORT_TIMEOUT);
}
}
// Return true if device is currently connected to mobile network
- public boolean isConnectedToMobile() {
- return (mNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE);
+ protected boolean isConnectedToMobile() {
+ return (mCm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_MOBILE);
}
// Return true if device is currently connected to Wifi
- public boolean isConnectedToWifi() {
- return (mNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI);
+ protected boolean isConnectedToWifi() {
+ return (mCm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI);
}
- public boolean enableWifi() {
+ protected boolean enableWifi() {
return mWifiManager.setWifiEnabled(true);
}
// Turn screen off
- public void turnScreenOff() {
+ protected void turnScreenOff() {
log("Turn screen off");
PowerManager pm =
(PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
@@ -495,7 +276,7 @@
}
// Turn screen on
- public void turnScreenOn() {
+ protected void turnScreenOn() {
log("Turn screen on");
PowerManager pm =
(PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
@@ -511,7 +292,7 @@
* @param pingServerList a list of servers that can be used for ping test, can be null
* @return true if the ping test is successful, false otherwise.
*/
- public boolean pingTest(String[] pingServerList) {
+ protected boolean pingTest(String[] pingServerList) {
String[] hostList = {"www.google.com", "www.yahoo.com",
"www.bing.com", "www.facebook.com", "www.ask.com"};
if (pingServerList != null) {
@@ -549,7 +330,7 @@
* If the device is already associated with a WiFi, disconnect and forget it,
* We don't verify whether the connection is successful or not, leave this to the test
*/
- public boolean connectToWifi(String knownSSID) {
+ protected boolean connectToWifi(String knownSSID) {
WifiConfiguration config = new WifiConfiguration();
config.SSID = knownSSID;
config.allowedKeyManagement.set(KeyMgmt.NONE);
@@ -562,7 +343,7 @@
* @param config
* @return
*/
- public boolean connectToWifiWithConfiguration(WifiConfiguration config) {
+ protected boolean connectToWifiWithConfiguration(WifiConfiguration config) {
String ssid = config.SSID;
config.SSID = convertToQuotedString(ssid);
@@ -571,7 +352,7 @@
log("Wifi is not enabled, enable it");
mWifiManager.setWifiEnabled(true);
// wait for the wifi state change before start scanning.
- if (!waitForWifiState(WifiManager.WIFI_STATE_ENABLED, 2*SHORT_TIMEOUT)) {
+ if (!waitForWifiState(WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT)) {
log("wait for WIFI_STATE_ENABLED failed");
return false;
}
@@ -592,12 +373,12 @@
/*
* Disconnect from the current AP and remove configured networks.
*/
- public boolean disconnectAP() {
+ protected boolean disconnectAP() {
// remove saved networks
if (!mWifiManager.isWifiEnabled()) {
log("Enabled wifi before remove configured networks");
mWifiManager.setWifiEnabled(true);
- sleep(SHORT_TIMEOUT);
+ SystemClock.sleep(SHORT_TIMEOUT);
}
List<WifiConfiguration> wifiConfigList = mWifiManager.getConfiguredNetworks();
@@ -623,37 +404,81 @@
* Disable Wifi
* @return true if Wifi is disabled successfully
*/
- public boolean disableWifi() {
+ protected boolean disableWifi() {
return mWifiManager.setWifiEnabled(false);
}
/**
* Remove configured networks and disable wifi
*/
- public boolean removeConfiguredNetworksAndDisableWifi() {
+ protected boolean removeConfiguredNetworksAndDisableWifi() {
if (!disconnectAP()) {
return false;
}
- sleep(SHORT_TIMEOUT);
+ SystemClock.sleep(SHORT_TIMEOUT);
if (!mWifiManager.setWifiEnabled(false)) {
return false;
}
- sleep(SHORT_TIMEOUT);
+ SystemClock.sleep(SHORT_TIMEOUT);
return true;
}
- private void sleep(long sleeptime) {
- try {
- Thread.sleep(sleeptime);
- } catch (InterruptedException e) {}
- }
-
protected static String convertToQuotedString(String string) {
return "\"" + string + "\"";
}
+ protected boolean waitForActiveNetworkConnection(long timeout) {
+ long startTime = SystemClock.uptimeMillis();
+ while (true) {
+ NetworkInfo ni = mCm.getActiveNetworkInfo();
+ String niString = ni == null ? "null" : ni.toString();
+ if (ni != null && ni.isConnected()) {
+ return true;
+ }
+ if ((SystemClock.uptimeMillis() - startTime) > timeout) {
+ log("waitForActiveNetworkConnection timeout: " + niString);
+ return false;
+ }
+ log("waitForActiveNetworkConnection interim: " + niString);
+ SystemClock.sleep(SHORT_TIMEOUT);
+ }
+ }
+
+ protected boolean waitUntilNoActiveNetworkConnection(long timeout) {
+ long startTime = SystemClock.uptimeMillis();
+ while (true) {
+ NetworkInfo ni = mCm.getActiveNetworkInfo();
+ if (ni == null) {
+ return true;
+ }
+ String niString = ni.toString();
+ if ((SystemClock.uptimeMillis() - startTime) > timeout) {
+ log("waitForActiveNetworkConnection timeout: " + niString);
+ return false;
+ }
+ log("waitForActiveNetworkConnection interim: " + niString);
+ SystemClock.sleep(SHORT_TIMEOUT);
+ }
+ }
+
+ // use ping request against Google public DNS to verify connectivity
+ protected boolean checkNetworkConnectivity() {
+ assertTrue("no active network connection", waitForActiveNetworkConnection(LONG_TIMEOUT));
+ try {
+ Process proc = Runtime.getRuntime().exec(new String[]{
+ "/system/bin/ping", "-W", "30", "-c", "1", PING_IP_ADDR});
+ int exitCode = proc.waitFor();
+ return exitCode == 0;
+ } catch (InterruptedException ie) {
+ Log.e(LOG_TAG, "InterruptedException while waiting for ping");
+ } catch (IOException ioe) {
+ Log.e(LOG_TAG, "IOException during ping", ioe);
+ }
+ return false;
+ }
+
@Override
- public void tearDown() throws Exception{
+ protected void tearDown() throws Exception{
//Unregister receiver
if (mConnectivityReceiver != null) {
mContext.unregisterReceiver(mConnectivityReceiver);
@@ -667,4 +492,36 @@
private void log(String message) {
Log.v(LOG_TAG, message);
}
+
+ /**
+ * Connect to the provided Wi-Fi network
+ * @param config is the network configuration
+ * @throws AssertionError if fails to associate and connect to wifi ap
+ */
+ protected void connectToWifi(WifiConfiguration config) {
+ // step 1: connect to the test access point
+ assertTrue("failed to associate with " + config.SSID,
+ connectToWifiWithConfiguration(config));
+
+ // step 2: verify Wifi state and network state;
+ assertTrue("wifi state not connected with " + config.SSID,
+ waitForNetworkState(ConnectivityManager.TYPE_WIFI,
+ State.CONNECTED, LONG_TIMEOUT));
+
+ // step 3: verify the current connected network is the given SSID
+ assertNotNull("no active wifi info", mWifiManager.getConnectionInfo());
+ assertEquals("SSID mismatch", config.SSID, mWifiManager.getConnectionInfo().getSSID());
+ }
+
+ /**
+ * checks if the input is a hexadecimal string of given length
+ *
+ * @param input string to be checked
+ * @param length required length of the string
+ * @return
+ */
+ protected static boolean isHex(String input, int length) {
+ Pattern p = Pattern.compile(String.format("[0-9A-Fa-f]{%d}", length));
+ return p.matcher(input).matches();
+ }
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/NetworkState.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/NetworkState.java
deleted file mode 100644
index 9d97ac5..0000000
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/NetworkState.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2010 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.connectivitymanagertest;
-
-import android.net.NetworkInfo.State;
-import android.util.Log;
-
-import java.util.List;
-import java.util.ArrayList;
-
-public class NetworkState {
- public static final int TO_DISCONNECTION = 0; // transition to disconnection
- public static final int TO_CONNECTION = 1; // transition to connection
- public static final int DO_NOTHING = -1; // no state change
- private final String LOG_TAG = "NetworkState";
- private List<State> mStateDepository;
- private State mTransitionTarget;
- private int mTransitionDirection;
- private String mReason = null; // record mReason of state transition failure
-
- public NetworkState() {
- mStateDepository = new ArrayList<State>();
- mTransitionDirection = DO_NOTHING;
- mTransitionTarget = State.UNKNOWN;
- }
-
- public NetworkState(State currentState) {
- mStateDepository = new ArrayList<State>();
- mStateDepository.add(currentState);
- mTransitionDirection = DO_NOTHING;
- mTransitionTarget = State.UNKNOWN;
- }
-
- // Reinitialize the network state
- public void resetNetworkState() {
- mStateDepository.clear();
- mTransitionDirection = DO_NOTHING;
- mTransitionTarget = State.UNKNOWN;
- }
-
- // set the transition criteria, transitionDir could be:
- // DO_NOTHING, TO_CONNECTION, TO_DISCONNECTION
- public void setStateTransitionCriteria(State initState, int transitionDir, State targetState) {
- if (!mStateDepository.isEmpty()) {
- mStateDepository.clear();
- }
- mStateDepository.add(initState);
- mTransitionDirection = transitionDir;
- mTransitionTarget = targetState;
- Log.v(LOG_TAG, "setStateTransitionCriteria: " + printStates());
- }
-
- public void recordState(State currentState) {
- mStateDepository.add(currentState);
- }
-
- // Verify state transition
- public boolean validateStateTransition() {
- Log.v(LOG_TAG, "print state depository: " + printStates());
- if (mTransitionDirection == DO_NOTHING) {
- if (mStateDepository.isEmpty()) {
- Log.v(LOG_TAG, "no state is recorded");
- mReason = "no state is recorded.";
- return false;
- } else if (mStateDepository.size() > 1) {
- for (int i = 0; i < mStateDepository.size(); i++) {
- if (mStateDepository.get(i) != mTransitionTarget) {
- Log.v(LOG_TAG, "state changed.");
- mReason = "Unexpected state change";
- return false;
- }
- }
- } else if (mStateDepository.get(0) != mTransitionTarget) {
- Log.v(LOG_TAG, mTransitionTarget + " is expected, but it is " +
- mStateDepository.get(0));
- mReason = mTransitionTarget + " is expected, but it is " + mStateDepository.get(0);
- return false;
- }
- return true;
- } else if (mTransitionDirection == TO_CONNECTION) {
- Log.v(LOG_TAG, "transition to CONNECTED");
- return transitToConnection();
- } else {
- Log.v(LOG_TAG, "transition to DISCONNECTED");
- return transitToDisconnection();
- }
- }
-
- /*
- * Verifies state transition from CONNECTED->...-> DISCONNECTED.
- *
- * returns false if initial state or target state is not correct, or if there is
- * any transition from DISCONNECTING/DISCONNECTED -> CONNECTED.
- */
- public boolean transitToDisconnection () {
- mReason = "states: " + printStates();
- if (mStateDepository.get(0) != State.CONNECTED) {
- mReason += " initial state should be CONNECTED, but it is " +
- mStateDepository.get(0) + ".";
- return false;
- }
- State lastState = mStateDepository.get(mStateDepository.size() - 1);
- if ( lastState != mTransitionTarget) {
- mReason += " the last state should be DISCONNECTED, but it is " + lastState;
- return false;
- }
- for (int i = 1; i < mStateDepository.size() - 1; i++) {
- State preState = mStateDepository.get(i-1);
- State curState = mStateDepository.get(i);
- if (preState == curState) {
- continue;
- } else if ((preState == State.CONNECTED) && ((curState == State.DISCONNECTING) ||
- (curState == State.DISCONNECTED))) {
- continue;
- } else if ((preState == State.DISCONNECTING) && (curState == State.DISCONNECTED)) {
- continue;
- } else {
- mReason += " Transition state from " + preState.toString() + " to " +
- curState.toString() + " is not valid.";
- return false;
- }
- }
- return true;
- }
-
- /*
- * Verifies state transition from DISCONNECTED->...-> CONNECTED.
- *
- * returns false if initial state or target state is not correct, or if there is
- * any transition from CONNECED -> DISCONNECTED.
- */
- public boolean transitToConnection() {
- mReason = "states: " + printStates();
- if (mStateDepository.get(0) != State.DISCONNECTED) {
- mReason += " initial state should be DISCONNECTED, but it is " +
- mStateDepository.get(0) + ".";
- return false;
- }
- State lastState = mStateDepository.get(mStateDepository.size() - 1);
- if ( lastState != mTransitionTarget) {
- mReason += "The last state should be " + mTransitionTarget + ", but it is " + lastState;
- return false;
- }
- for (int i = 1; i < mStateDepository.size(); i++) {
- State preState = mStateDepository.get(i-1);
- State curState = mStateDepository.get(i);
- if (preState == curState) {
- continue;
- }
- if ((preState == State.DISCONNECTED) && ((curState == State.CONNECTING) ||
- (curState == State.CONNECTED))) {
- continue;
- } else if ((preState == State.CONNECTING) && (curState == State.CONNECTED)) {
- continue;
- } else {
- mReason += " Transition state from " + preState.toString() + " to " +
- curState.toString() + " is not valid.";
- return false;
- }
- }
- return true;
- }
-
- public List<State> getTransitionStates() {
- return mStateDepository;
- }
-
- // return state failure mReason
- public String getReason() {
- return mReason;
- }
-
- public String printStates() {
- StringBuilder stateBuilder = new StringBuilder("");
- for (int i = 0; i < mStateDepository.size(); i++) {
- stateBuilder.append(" ").append(mStateDepository.get(i).toString()).append("->");
- }
- return stateBuilder.toString();
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder(" ");
- builder.append("mTransitionDirection: ").append(Integer.toString(mTransitionDirection)).
- append("; ").append("states:").
- append(printStates()).append("; ");
- return builder.toString();
- }
-}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiAssociationTestRunner.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiAssociationTestRunner.java
index 722df2e..2354484 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiAssociationTestRunner.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiAssociationTestRunner.java
@@ -57,8 +57,7 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- Bundle arguments = icicle;
- String mFrequencyBand = arguments.getString("frequency-band");
+ String mFrequencyBand = icicle.getString("frequency-band");
if (mFrequencyBand != null) {
setFrequencyBand(mFrequencyBand);
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
index 05462b4..b4b0e53 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
@@ -16,27 +16,23 @@
package com.android.connectivitymanagertest.functional;
-import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.net.wifi.WifiManager;
-import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
+import android.os.SystemClock;
import android.provider.Settings;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
import com.android.connectivitymanagertest.ConnectivityManagerTestRunner;
-import com.android.connectivitymanagertest.NetworkState;
public class ConnectivityManagerMobileTest extends
ConnectivityManagerTestBase {
private static final String TAG = "ConnectivityManagerMobileTest";
private String mTestAccessPoint;
- private WakeLock wl;
private boolean mWifiOnlyFlag;
@Override
@@ -47,15 +43,11 @@
mTestAccessPoint = mRunner.mTestSsid;
mWifiOnlyFlag = mRunner.mWifiOnlyFlag;
- PowerManager pm = (PowerManager)getInstrumentation().
- getContext().getSystemService(Context.POWER_SERVICE);
- wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "CMWakeLock");
- wl.acquire();
// Each test case will start with cellular connection
if (Settings.Global.getInt(getInstrumentation().getContext().getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON) == 1) {
log("airplane is not disabled, disable it.");
- mCM.setAirplaneMode(false);
+ mCm.setAirplaneMode(false);
}
if (!mWifiOnlyFlag) {
@@ -72,15 +64,14 @@
@Override
public void tearDown() throws Exception {
- wl.release();
removeConfiguredNetworksAndDisableWifi();
- mCM.setAirplaneMode(false);
+ mCm.setAirplaneMode(false);
super.tearDown();
}
// help function to verify 3G connection
public void verifyCellularConnection() {
- NetworkInfo extraNetInfo = mCM.getActiveNetworkInfo();
+ NetworkInfo extraNetInfo = mCm.getActiveNetworkInfo();
assertEquals("network type is not MOBILE", ConnectivityManager.TYPE_MOBILE,
extraNetInfo.getType());
assertTrue("not connected to cellular network", extraNetInfo.isConnected());
@@ -90,431 +81,262 @@
Log.v(TAG, message);
}
- private void sleep(long sleeptime) {
- try {
- Thread.sleep(sleeptime);
- } catch (InterruptedException e) {}
- }
-
// Test case 1: Test enabling Wifi without associating with any AP, no broadcast on network
// event should be expected.
@LargeTest
public void test3GToWifiNotification() {
if (mWifiOnlyFlag) {
- Log.v(TAG, this.getName() + " is excluded for wifi-only test");
+ Log.v(TAG, getName() + " is excluded for wifi-only test");
return;
}
- // Enable Wi-Fi to avoid initial UNKNOWN state
- enableWifi();
- sleep(2 * SHORT_TIMEOUT);
- // Wi-Fi is disabled
- disableWifi();
+ // disable WiFi
+ assertTrue("failed to disable WiFi", disableWifi());
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI,
- State.DISCONNECTED, LONG_TIMEOUT));
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
- State.CONNECTED, LONG_TIMEOUT));
- // Wait for 10 seconds for broadcasts to be sent out
- sleep(10 * 1000);
+ // wait for mobile
+ assertTrue("failed to wait for mobile connection", waitForNetworkState(
+ ConnectivityManager.TYPE_MOBILE, State.CONNECTED, LONG_TIMEOUT));
- // As Wifi stays in DISCONNETED, Mobile statys in CONNECTED,
- // the connectivity manager will not broadcast any network connectivity event for Wifi
- NetworkInfo networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
- setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
- networkInfo.getState(), NetworkState.DO_NOTHING, State.CONNECTED);
- networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
- setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
- NetworkState.DO_NOTHING, State.DISCONNECTED);
- // Eanble Wifi without associating with any AP
- enableWifi();
- sleep(2 * SHORT_TIMEOUT);
+ // assert that we are indeed using mobile
+ NetworkInfo ni = mCm.getActiveNetworkInfo();
+ assertEquals("active network is not mobile", ConnectivityManager.TYPE_MOBILE, ni.getType());
- // validate state and broadcast
- if (!validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
- log("the state for WIFI is changed");
- log("reason: " +
- getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
- assertTrue("state validation fail", false);
- }
- if (!validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
- log("the state for MOBILE is changed");
- log("reason: " +
- getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
- assertTrue("state validation fail", false);
- }
- // Verify that the device is still connected to MOBILE
+ long timestamp = SystemClock.uptimeMillis();
+ // now enable WiFi
+ assertTrue("failed to enable WiFi", enableWifi());
+ // assert that WiFi state settles at disconnected since no AP should be configured
+ assertTrue("WiFi state is not DISCONNECTED after enabling", waitForWifiState(
+ WifiManager.WIFI_STATE_DISABLED, LONG_TIMEOUT));
+
+ // assert that no connectivity change broadcast was sent since we enable wifi
+ assertTrue("connectivity has changed since wifi enable",
+ timestamp > getLastConnectivityChangeTime());
+
+ // verify that the device is still connected to MOBILE
verifyCellularConnection();
+ // verify that connection actually works
+ assertTrue("no network connectivity at end of test", checkNetworkConnectivity());
}
// Test case 2: test connection to a given AP
@LargeTest
public void testConnectToWifi() {
assertNotNull("SSID is null", mTestAccessPoint);
- NetworkInfo networkInfo;
- if (!mWifiOnlyFlag) {
- //Prepare for connectivity verification
- networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
- setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
- networkInfo.getState(), NetworkState.TO_DISCONNECTION, State.DISCONNECTED);
- }
- networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
- setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
- NetworkState.TO_CONNECTION, State.CONNECTED);
- // Enable Wifi and connect to a test access point
+ // assert that we are able to connect to the ap
assertTrue("failed to connect to " + mTestAccessPoint,
connectToWifi(mTestAccessPoint));
-
+ // assert that WifiManager reports correct state
assertTrue(waitForWifiState(WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
- log("wifi state is enabled");
+ // assert that ConnectivityManager reports correct state for Wifi
assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
WIFI_CONNECTION_TIMEOUT));
- if (!mWifiOnlyFlag) {
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
- State.DISCONNECTED, LONG_TIMEOUT));
- }
-
- // validate states
- if (!validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
- log("Wifi state transition validation failed.");
- log("reason: " +
- getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
- assertTrue(false);
- }
- if (!mWifiOnlyFlag) {
- if (!validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
- log("Mobile state transition validation failed.");
- log("reason: " +
- getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
- assertTrue(false);
- }
- }
+ // below check disbabled since we have bug in what ConnectivityManager returns
+// if (!mWifiOnlyFlag) {
+// // assert that ConnectivityManager reports correct state for mobile
+// assertTrue("mobile not disconnected", waitForNetworkState(
+// ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED, LONG_TIMEOUT));
+// }
+ // verify that connection actually works
+ assertTrue("no network connectivity at end of test", checkNetworkConnectivity());
}
- // Test case 3: connect to Wifi with known AP
+ // Test case 3: connect & reconnect to Wifi with known AP
@LargeTest
public void testConnectToWifWithKnownAP() {
assertNotNull("SSID is null", mTestAccessPoint);
- // Connect to mTestAccessPoint
- assertTrue("failed to connect to " + mTestAccessPoint,
- connectToWifi(mTestAccessPoint));
- assertTrue(waitForWifiState(WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
- WIFI_CONNECTION_TIMEOUT));
+ // enable WiFi
+ assertTrue("failed to enable wifi", enableWifi());
+ // wait for wifi enable
+ assertTrue("wifi not enabled", waitForWifiState(
+ WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
+ // Connect to AP
+ assertTrue("failed to connect to " + mTestAccessPoint, connectToWifi(mTestAccessPoint));
+ // verify wifi connected as reported by ConnectivityManager
+ assertTrue("wifi not connected", waitForNetworkState(
+ ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
- sleep(SHORT_TIMEOUT);
- // Disable Wifi
- log("Disable Wifi");
- if (!disableWifi()) {
- log("disable Wifi failed");
- return;
- }
+ assertTrue("failed to disable wifi", disableWifi());
// Wait for the Wifi state to be DISABLED
- assertTrue(waitForWifiState(WifiManager.WIFI_STATE_DISABLED, LONG_TIMEOUT));
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI,
- State.DISCONNECTED, LONG_TIMEOUT));
+ assertTrue("wifi state not disabled", waitForWifiState(
+ WifiManager.WIFI_STATE_DISABLED, LONG_TIMEOUT));
+ // below check disbabled since we have bug in what ConnectivityManager returns
+// assertTrue("wifi not disconnected", waitForNetworkState(ConnectivityManager.TYPE_WIFI,
+// State.DISCONNECTED, LONG_TIMEOUT));
if (!mWifiOnlyFlag) {
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
- State.CONNECTED, LONG_TIMEOUT));
+ assertTrue("mobile not connected after wifi disable", waitForNetworkState(
+ ConnectivityManager.TYPE_MOBILE, State.CONNECTED, LONG_TIMEOUT));
}
- NetworkInfo networkInfo;
- if (!mWifiOnlyFlag) {
- //Prepare for connectivity state verification
- networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
- setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
- networkInfo.getState(), NetworkState.DO_NOTHING,
- State.DISCONNECTED);
- }
- networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
- setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
- NetworkState.TO_CONNECTION, State.CONNECTED);
+ // wait for 30s before restart wifi
+ SystemClock.sleep(LONG_TIMEOUT);
+ assertTrue("failed to enable wifi after disable", enableWifi());
- // wait for 2 minutes before restart wifi
- sleep(WIFI_STOP_START_INTERVAL);
- // Enable Wifi again
- log("Enable Wifi again");
- enableWifi();
-
+ // wait for wifi enable
+ assertTrue("wifi not enabled after toggle", waitForWifiState(
+ WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
// Wait for Wifi to be connected and mobile to be disconnected
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
- WIFI_CONNECTION_TIMEOUT));
- if (!mWifiOnlyFlag) {
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
- State.DISCONNECTED, LONG_TIMEOUT));
- }
-
- // validate wifi states
- if (!validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
- log("Wifi state transition validation failed.");
- log("reason: " +
- getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
- assertTrue(false);
- }
+ assertTrue("wifi not connected after toggle", waitForNetworkState(
+ ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
+ // below check disbabled since we have bug in what ConnectivityManager returns
+// if (!mWifiOnlyFlag) {
+// assertTrue("mobile not disconnected after wifi toggle", waitForNetworkState(
+// ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED, LONG_TIMEOUT));
+// }
+ // verify that connection actually works
+ assertTrue("no network connectivity at end of test", checkNetworkConnectivity());
}
- // Test case 4: test disconnect Wifi
+ // Test case 4: test disconnect and clear wifi settings
@LargeTest
public void testDisconnectWifi() {
assertNotNull("SSID is null", mTestAccessPoint);
+ // enable WiFi
+ assertTrue("failed to enable wifi", enableWifi());
+ // wait for wifi enable
+ assertTrue("wifi not enabled", waitForWifiState(
+ WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
// connect to Wifi
assertTrue("failed to connect to " + mTestAccessPoint,
connectToWifi(mTestAccessPoint));
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
- WIFI_CONNECTION_TIMEOUT));
-
- // Wait for a few seconds to avoid the state that both Mobile and Wifi is connected
- sleep(SHORT_TIMEOUT);
-
- NetworkInfo networkInfo;
- if (!mWifiOnlyFlag) {
- networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
- setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
- networkInfo.getState(),
- NetworkState.TO_CONNECTION,
- State.CONNECTED);
- }
- networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
- setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
- NetworkState.TO_DISCONNECTION, State.DISCONNECTED);
+ assertTrue("wifi not connected", waitForNetworkState(
+ ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
// clear Wifi
removeConfiguredNetworksAndDisableWifi();
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI,
- State.DISCONNECTED, LONG_TIMEOUT));
+ // assert that wifi has been disabled
+ assertTrue("wifi state not disabled", waitForWifiState(
+ WifiManager.WIFI_STATE_DISABLED, LONG_TIMEOUT));
if (!mWifiOnlyFlag) {
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
+ // assert that mobile is now connected
+ assertTrue("mobile not enabled", waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
State.CONNECTED, LONG_TIMEOUT));
- }
-
- // validate states
- if (!validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
- log("Wifi state transition validation failed.");
- log("reason: " +
- getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
- assertTrue(false);
- }
- if (!mWifiOnlyFlag) {
- if (!validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
- log("Mobile state transition validation failed.");
- log("reason: " +
- getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
- assertTrue(false);
- }
+ // verify that connection actually works
+ assertTrue("no network connectivity at end of test", checkNetworkConnectivity());
}
}
- // Test case 5: test connectivity from 3G to airplane mode, then to 3G again
+ // Test case 5: test connectivity with mobile->airplane mode->mobile
@LargeTest
public void testDataConnectionWith3GToAmTo3G() {
if (mWifiOnlyFlag) {
- Log.v(TAG, this.getName() + " is excluded for wifi-only test");
+ Log.v(TAG, getName() + " is excluded for wifi-only test");
return;
}
- //Prepare for state verification
- NetworkInfo networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
- setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
- networkInfo.getState(),
- NetworkState.TO_DISCONNECTION,
- State.DISCONNECTED);
- networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
- assertEquals(State.DISCONNECTED, networkInfo.getState());
+ // disable wifi
+ assertTrue("failed to disable wifi", disableWifi());
+ assertTrue("wifi state not disabled", waitForWifiState(
+ WifiManager.WIFI_STATE_DISABLED, LONG_TIMEOUT));
+ // assert that we have mobile connection
+ assertTrue("no mobile connection", waitForNetworkState(
+ ConnectivityManager.TYPE_MOBILE, State.CONNECTED, LONG_TIMEOUT));
- // Enable airplane mode
- log("Enable airplane mode");
- mCM.setAirplaneMode(true);
- sleep(SHORT_TIMEOUT);
-
- networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
- assertEquals(State.DISCONNECTED, networkInfo.getState());
- // wait until mobile is turn off
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
- State.DISCONNECTED, LONG_TIMEOUT));
- if (!validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
- log("Mobile state transition validation failed.");
- log("reason: " +
- getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
- assertTrue(false);
- }
-
- // reset state recorder
- networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
- setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
- networkInfo.getState(),
- NetworkState.TO_CONNECTION,
- State.CONNECTED);
- networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
- setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
- NetworkState.DO_NOTHING, State.DISCONNECTED);
+ // enable airplane mode
+ mCm.setAirplaneMode(true);
+ // assert no active network connection after airplane mode enabled
+ assertTrue("still has active network connection",
+ waitUntilNoActiveNetworkConnection(LONG_TIMEOUT));
// disable airplane mode
- mCM.setAirplaneMode(false);
+ mCm.setAirplaneMode(false);
+ // assert there is active network connection after airplane mode disabled
+ assertTrue("no active network connection after airplane mode disable",
+ waitForActiveNetworkConnection(LONG_TIMEOUT));
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
- State.CONNECTED, LONG_TIMEOUT));
-
- // Validate the state transition
- if (!validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
- log("Mobile state transition validation failed.");
- log("reason: " +
- getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
- assertTrue(false);
- }
- if (!validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
- log("Wifi state transition validation failed.");
- log("reason: " +
- getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
- assertTrue(false);
- }
+ // assert that we have mobile connection
+ assertTrue("no mobile connection", waitForNetworkState(
+ ConnectivityManager.TYPE_MOBILE, State.CONNECTED, LONG_TIMEOUT));
+ // verify that connection actually works
+ assertTrue("no network connectivity at end of test", checkNetworkConnectivity());
}
- // Test case 6: test connectivity with airplane mode Wifi connected
+ // Test case 6: test connectivity with airplane mode on but wifi enabled
@LargeTest
public void testDataConnectionOverAMWithWifi() {
- if (mWifiOnlyFlag) {
- Log.v(TAG, this.getName() + " is excluded for wifi-only test");
- return;
- }
assertNotNull("SSID is null", mTestAccessPoint);
- // Eanble airplane mode
- log("Enable airplane mode");
- mCM.setAirplaneMode(true);
+ // enable airplane mode
+ mCm.setAirplaneMode(true);
+ // assert there is active network connection after airplane mode disabled
+ assertTrue("still has active network connection",
+ waitUntilNoActiveNetworkConnection(LONG_TIMEOUT));
- NetworkInfo networkInfo;
- if (!mWifiOnlyFlag) {
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
- State.DISCONNECTED, LONG_TIMEOUT));
- networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
- setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
- networkInfo.getState(),
- NetworkState.DO_NOTHING,
- State.DISCONNECTED);
- }
- networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
- setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
- NetworkState.TO_CONNECTION, State.CONNECTED);
-
- // Connect to Wifi
+ // connect to Wifi
assertTrue("failed to connect to " + mTestAccessPoint,
connectToWifi(mTestAccessPoint));
assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
WIFI_CONNECTION_TIMEOUT));
+ // verify that connection actually works
+ assertTrue("no network connectivity after wifi enable", checkNetworkConnectivity());
- // validate state and broadcast
- if (!validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
- log("state validate for Wifi failed");
- log("reason: " +
- getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
- assertTrue("State validation failed", false);
- }
- if (!mWifiOnlyFlag) {
- if (!validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
- log("state validation for Mobile failed");
- log("reason: " +
- getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
- assertTrue("state validation failed", false);
- }
- }
- mCM.setAirplaneMode(false);
+ // disable airplane mode
+ mCm.setAirplaneMode(false);
}
// Test case 7: test connectivity while transit from Wifi->AM->Wifi
@LargeTest
public void testDataConnectionWithWifiToAMToWifi () {
- if (mWifiOnlyFlag) {
- Log.v(TAG, this.getName() + " is excluded for wifi-only test");
- return;
- }
- // Connect to mTestAccessPoint
+ // connect to mTestAccessPoint
assertNotNull("SSID is null", mTestAccessPoint);
- // Connect to Wifi
+ // enable WiFi
+ assertTrue("failed to enable wifi", enableWifi());
+ // wait for wifi enable
+ assertTrue("wifi not enabled", waitForWifiState(
+ WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
+ // connect to Wifi
assertTrue("failed to connect to " + mTestAccessPoint,
connectToWifi(mTestAccessPoint));
-
assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
WIFI_CONNECTION_TIMEOUT));
- try {
- Thread.sleep(SHORT_TIMEOUT);
- } catch (Exception e) {
- log("exception: " + e.toString());
- }
+ // enable airplane mode without clearing Wifi
+ mCm.setAirplaneMode(true);
+ // assert there is active network connection after airplane mode disabled
+ assertTrue("still has active network connection",
+ waitUntilNoActiveNetworkConnection(LONG_TIMEOUT));
- // Enable airplane mode without clearing Wifi
- mCM.setAirplaneMode(true);
-
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI,
- State.DISCONNECTED, LONG_TIMEOUT));
-
- try {
- Thread.sleep(SHORT_TIMEOUT);
- } catch (Exception e) {
- log("exception: " + e.toString());
- }
-
- // Prepare for state validation
- NetworkInfo networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
- assertEquals(State.DISCONNECTED, networkInfo.getState());
- setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI,
- networkInfo.getState(), NetworkState.TO_CONNECTION, State.CONNECTED);
-
- // Disable airplane mode
- mCM.setAirplaneMode(false);
-
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
- WIFI_CONNECTION_TIMEOUT));
- if (!mWifiOnlyFlag) {
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
- State.DISCONNECTED, LONG_TIMEOUT));
- }
-
- // validate the state transition
- if (!validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
- log("Wifi state transition validation failed.");
- log("reason: " +
- getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
- assertTrue(false);
- }
+ // disable airplane mode
+ mCm.setAirplaneMode(false);
+ // assert there is active network connection after airplane mode disabled
+ assertTrue("no active network connection after airplane mode disable",
+ waitForActiveNetworkConnection(LONG_TIMEOUT));
+ // assert that we have a Wifi connection
+ assertTrue("wifi not connected after airplane mode disable", waitForNetworkState(
+ ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
+ // verify that connection actually works
+ assertTrue("no network connectivity at end of test", checkNetworkConnectivity());
}
// Test case 8: test wifi state change while connecting/disconnecting to/from an AP
@LargeTest
public void testWifiStateChange () {
assertNotNull("SSID is null", mTestAccessPoint);
- //Connect to mTestAccessPoint
+ // enable WiFi
+ assertTrue("failed to enable wifi", enableWifi());
+ // wait for wifi enable
+ assertTrue("wifi not enabled", waitForWifiState(
+ WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
+ // connect to Wifi
assertTrue("failed to connect to " + mTestAccessPoint,
connectToWifi(mTestAccessPoint));
- assertTrue(waitForWifiState(WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
WIFI_CONNECTION_TIMEOUT));
- assertNotNull("Not associated with any AP",
- mWifiManager.getConnectionInfo().getBSSID());
+ assertNotNull("not associated with any AP", mWifiManager.getConnectionInfo().getBSSID());
- try {
- Thread.sleep(SHORT_TIMEOUT);
- } catch (Exception e) {
- log("exception: " + e.toString());
- }
+ // disconnect from the current AP
+ assertTrue("failed to disconnect from AP", disconnectAP());
- // Disconnect from the current AP
- log("disconnect from the AP");
- if (!disconnectAP()) {
- log("failed to disconnect from " + mTestAccessPoint);
- }
-
+ // below check disbabled since we have bug in what ConnectivityManager returns
// Verify the connectivity state for Wifi is DISCONNECTED
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI,
- State.DISCONNECTED, LONG_TIMEOUT));
+// assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI,
+// State.DISCONNECTED, LONG_TIMEOUT));
- if (!disableWifi()) {
- log("disable Wifi failed");
- return;
- }
- assertTrue(waitForWifiState(WifiManager.WIFI_STATE_DISABLED, LONG_TIMEOUT));
+ // disable WiFi
+ assertTrue("failed to disable wifi", disableWifi());
+ assertTrue("wifi state not disabled", waitForWifiState(
+ WifiManager.WIFI_STATE_DISABLED, LONG_TIMEOUT));
}
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java
index 183f2a9..eb75b0d 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java
@@ -16,24 +16,22 @@
package com.android.connectivitymanagertest.functional;
-import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
-import com.android.connectivitymanagertest.WifiAssociationTestRunner;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.net.wifi.WifiInfo;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
-import android.net.wifi.WifiConfiguration.AuthAlgorithm;
-import android.net.wifi.WifiConfiguration.GroupCipher;
-import android.net.wifi.WifiConfiguration.PairwiseCipher;
-import android.net.wifi.WifiConfiguration.Protocol;
-import android.net.wifi.WifiManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo.State;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiConfiguration.GroupCipher;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiConfiguration.PairwiseCipher;
+import android.net.wifi.WifiConfiguration.Protocol;
+import android.net.wifi.WifiInfo;
+import android.os.Bundle;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
+import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
+import com.android.connectivitymanagertest.WifiAssociationTestRunner;
+
/**
* Test Wi-Fi connection with different configuration
* To run this tests:
@@ -41,8 +39,7 @@
* -e security-type [OPEN|WEP64|WEP128|WPA_TKIP|WPA2_AES] -e frequency-band [2.4|5.0|auto]
* -w com.android.connectivitymanagertest/.WifiAssociationTestRunner"
*/
-public class WifiAssociationTest
- extends ConnectivityManagerTestBase {
+public class WifiAssociationTest extends ConnectivityManagerTestBase {
private static final String TAG = "WifiAssociationTest";
private String mSsid = null;
private String mPassword = null;
@@ -55,67 +52,37 @@
}
@Override
- public void setUp() throws Exception {
+ protected void setUp() throws Exception {
super.setUp();
- WifiAssociationTestRunner mRunner = (WifiAssociationTestRunner)getInstrumentation();
- Bundle arguments = mRunner.getArguments();
+ WifiAssociationTestRunner runner = (WifiAssociationTestRunner)getInstrumentation();
+ Bundle arguments = runner.getArguments();
mSecurityType = arguments.getString("security-type");
mSsid = arguments.getString("ssid");
mPassword = arguments.getString("password");
mFrequencyBand = arguments.getString("frequency-band");
- mBand = mRunner.mBand;
- assertNotNull("Security type is empty", mSecurityType);
- assertNotNull("Ssid is empty", mSsid);
+ mBand = runner.mBand;
+ assertNotNull("security type is empty", mSecurityType);
+ assertNotNull("ssid is empty", mSsid);
validateFrequencyBand();
- // enable Wifi and verify wpa_supplicant is started
- assertTrue("enable Wifi failed", enableWifi());
- sleep(2 * SHORT_TIMEOUT, "interrupted while waiting for WPA_SUPPLICANT to start");
- WifiInfo mConnection = mWifiManager.getConnectionInfo();
- assertNotNull(mConnection);
- assertTrue("wpa_supplicant is not started ", mWifiManager.pingSupplicant());
- }
- @Override
- public void tearDown() throws Exception {
- super.tearDown();
+ // enable wifi and verify wpa_supplicant is started
+ assertTrue("enable Wifi failed", enableWifi());
+ assertTrue("wifi not connected", waitForNetworkState(
+ ConnectivityManager.TYPE_WIFI, State.CONNECTED, LONG_TIMEOUT));
+ WifiInfo wi = mWifiManager.getConnectionInfo();
+ assertNotNull("no active wifi info", wi);
+ assertTrue("failed to ping wpa_supplicant ", mWifiManager.pingSupplicant());
}
private void validateFrequencyBand() {
if (mFrequencyBand != null) {
int currentFreq = mWifiManager.getFrequencyBand();
Log.v(TAG, "read frequency band: " + currentFreq);
- assertTrue("device frequency band is not set successfully", (mBand == currentFreq));
+ assertEquals("specified frequency band does not match operational band of WifiManager",
+ currentFreq, mBand);
}
}
- /**
- * Connect to the provided Wi-Fi network
- * @param config is the network configuration
- * @return true if the connection is successful.
- */
- private void connectToWifi(WifiConfiguration config) {
- // step 1: connect to the test access point
- assertTrue("failed to associate with " + config.SSID,
- connectToWifiWithConfiguration(config));
-
- // step 2: verify Wifi state and network state;
- assertTrue("failed to connect with " + config.SSID,
- waitForNetworkState(ConnectivityManager.TYPE_WIFI,
- State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
-
- // step 3: verify the current connected network is the given SSID
- assertNotNull("Wifi connection returns null", mWifiManager.getConnectionInfo());
- assertTrue(config.SSID.contains(mWifiManager.getConnectionInfo().getSSID()));
- }
-
- private void sleep(long sometime, String errorMsg) {
- try {
- Thread.sleep(sometime);
- } catch (InterruptedException e) {
- fail(errorMsg);
- }
- }
-
private void log(String message) {
Log.v(TAG, message);
}
@@ -133,62 +100,57 @@
config.allowedKeyManagement.set(KeyMgmt.NONE);
break;
case WEP64:
- // always use hex pair for WEP-40
- assertTrue("not a WEP64 security type?", mPassword.length() == 10);
+ assertNotNull("password is empty", mPassword);
config.allowedKeyManagement.set(KeyMgmt.NONE);
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
config.allowedGroupCiphers.set(GroupCipher.WEP40);
if (mPassword != null) {
- int length = mPassword.length();
- // WEP-40
- if (mPassword.matches("[0-9A-Fa-f]*")) {
+ // always use hex pair for WEP-40
+ if (isHex(mPassword, 10)) {
config.wepKeys[0] = mPassword;
} else {
- fail("Please type hex pair for the password");
+ fail("password should be 10-character hex");
}
}
break;
case WEP128:
assertNotNull("password is empty", mPassword);
- // always use hex pair for WEP-104
- assertTrue("not a WEP128 security type?", mPassword.length() == 26);
config.allowedKeyManagement.set(KeyMgmt.NONE);
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
config.allowedGroupCiphers.set(GroupCipher.WEP104);
if (mPassword != null) {
- int length = mPassword.length();
- // WEP-40
- if (mPassword.matches("[0-9A-Fa-f]*")) {
+ // always use hex pair for WEP-104
+ if (isHex(mPassword, 26)) {
config.wepKeys[0] = mPassword;
} else {
- fail("Please type hex pair for the password");
+ fail("password should be 26-character hex");
}
}
break;
case WPA_TKIP:
- assertNotNull("missing password", mPassword);
+ assertNotNull("password is empty", mPassword);
config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
config.allowedProtocols.set(Protocol.WPA);
config.allowedPairwiseCiphers.set(PairwiseCipher.TKIP);
config.allowedGroupCiphers.set(GroupCipher.TKIP);
- if (mPassword.matches("[0-9A-Fa-f]{64}")) {
+ if (isHex(mPassword, 64)) {
config.preSharedKey = mPassword;
} else {
config.preSharedKey = '"' + mPassword + '"';
}
break;
case WPA2_AES:
- assertNotNull("missing password", mPassword);
+ assertNotNull("password is empty", mPassword);
config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
config.allowedProtocols.set(Protocol.RSN);
config.allowedPairwiseCiphers.set(PairwiseCipher.CCMP);
config.allowedGroupCiphers.set(GroupCipher.CCMP);
config.allowedProtocols.set(Protocol.RSN);
- if (mPassword.matches("[0-9A-Fa-f]{64}")) {
+ if (isHex(mPassword, 64)) {
config.preSharedKey = mPassword;
} else {
config.preSharedKey = '"' + mPassword + '"';
@@ -200,5 +162,7 @@
}
Log.v(TAG, "network config: " + config.toString());
connectToWifi(config);
+ // verify that connection actually works
+ assertTrue("no network connectivity at end of test", checkNetworkConnectivity());
}
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
index ad73ee1..740ffb8 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
@@ -16,21 +16,17 @@
package com.android.connectivitymanagertest.functional;
-import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
-import com.android.connectivitymanagertest.ConnectivityManagerTestRunner;
-
-import android.content.Context;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiInfo;
-import android.net.wifi.WifiManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo.State;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
+import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
+
import java.util.ArrayList;
import java.util.List;
-import java.util.Set;
/**
* Test Wi-Fi connection with different configuration
@@ -43,28 +39,29 @@
extends ConnectivityManagerTestBase {
private static final String TAG = "WifiConnectionTest";
private static final boolean DEBUG = false;
- private List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
+ private List<WifiConfiguration> mNetworks = new ArrayList<WifiConfiguration>();
@Override
public void setUp() throws Exception {
super.setUp();
- networks = loadNetworkConfigurations();
+ mNetworks = loadNetworkConfigurations();
if (DEBUG) {
printNetworkConfigurations();
}
- // enable Wifi and verify wpa_supplicant is started
+ // enable wifi and verify wpa_supplicant is started
assertTrue("enable Wifi failed", enableWifi());
- sleep(2 * SHORT_TIMEOUT, "interrupted while waiting for WPA_SUPPLICANT to start");
- WifiInfo mConnection = mWifiManager.getConnectionInfo();
- assertNotNull(mConnection);
- assertTrue("wpa_supplicant is not started ", mWifiManager.pingSupplicant());
+ assertTrue("wifi not connected", waitForNetworkState(
+ ConnectivityManager.TYPE_WIFI, State.CONNECTED, LONG_TIMEOUT));
+ WifiInfo wi = mWifiManager.getConnectionInfo();
+ assertNotNull("no active wifi info", wi);
+ assertTrue("failed to ping wpa_supplicant ", mWifiManager.pingSupplicant());
}
private void printNetworkConfigurations() {
log("==== print network configurations parsed from XML file ====");
- log("number of access points: " + networks.size());
- for (WifiConfiguration config : networks) {
+ log("number of access points: " + mNetworks.size());
+ for (WifiConfiguration config : mNetworks) {
log(config.toString());
}
}
@@ -75,51 +72,25 @@
super.tearDown();
}
- /**
- * Connect to the provided Wi-Fi network
- * @param config is the network configuration
- * @return true if the connection is successful.
- */
- private void connectToWifi(WifiConfiguration config) {
- // step 1: connect to the test access point
- assertTrue("failed to connect to " + config.SSID,
- connectToWifiWithConfiguration(config));
-
- // step 2: verify Wifi state and network state;
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI,
- State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
-
- // step 3: verify the current connected network is the given SSID
- assertNotNull("Wifi connection returns null", mWifiManager.getConnectionInfo());
- if (DEBUG) {
- log("config.SSID = " + config.SSID);
- log("mWifiManager.getConnectionInfo.getSSID()" +
- mWifiManager.getConnectionInfo().getSSID());
- }
- assertTrue(config.SSID.contains(mWifiManager.getConnectionInfo().getSSID()));
- }
-
- private void sleep(long sometime, String errorMsg) {
- try {
- Thread.sleep(sometime);
- } catch (InterruptedException e) {
- fail(errorMsg);
- }
- }
-
private void log(String message) {
Log.v(TAG, message);
}
@LargeTest
public void testWifiConnections() {
- for (int i = 0; i < networks.size(); i++) {
- String ssid = networks.get(i).SSID;
+ for (int i = 0; i < mNetworks.size(); i++) {
+ String ssid = mNetworks.get(i).SSID;
log("-- START Wi-Fi connection test to : " + ssid + " --");
- connectToWifi(networks.get(i));
- // wait for 2 minutes between wifi stop and start
- sleep(WIFI_STOP_START_INTERVAL, "interruped while connected to wifi");
+ connectToWifi(mNetworks.get(i));
+ // verify that connection actually works
+ assertTrue("no network connectivity at end of test", checkNetworkConnectivity());
log("-- END Wi-Fi connection test to " + ssid + " -- ");
+ log("pausing for 1 minute");
+ try {
+ Thread.sleep(60 * 1000);
+ } catch (InterruptedException e) {
+ // ignore
+ }
}
}
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
index 790ca38..aead65b 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
@@ -33,7 +33,7 @@
import java.io.FileWriter;
/**
- * Stress the wifi driver as access point.
+ * Stress test setting up device as wifi hotspot
*/
public class WifiApStress
extends ConnectivityManagerTestBase {
@@ -41,27 +41,28 @@
private static String NETWORK_ID = "AndroidAPTest";
private static String PASSWD = "androidwifi";
private final static String OUTPUT_FILE = "WifiStressTestOutput.txt";
- private int iterations;
+ private int mTotalIterations;
private BufferedWriter mOutputWriter = null;
private int mLastIteration = 0;
private boolean mWifiOnlyFlag;
@Override
- public void setUp() throws Exception {
+ protected void setUp() throws Exception {
super.setUp();
ConnectivityManagerStressTestRunner mRunner =
(ConnectivityManagerStressTestRunner)getInstrumentation();
- iterations = mRunner.mSoftapIterations;
- mWifiOnlyFlag = mRunner.mWifiOnlyFlag;
+ mTotalIterations = mRunner.getSoftApInterations();
+ mWifiOnlyFlag = mRunner.isWifiOnly();
turnScreenOn();
}
@Override
- public void tearDown() throws Exception {
+ protected void tearDown() throws Exception {
// write the total number of iterations into output file
mOutputWriter = new BufferedWriter(new FileWriter(new File(
Environment.getExternalStorageDirectory(), OUTPUT_FILE)));
- mOutputWriter.write(String.format("iteration %d out of %d\n", mLastIteration, iterations));
+ mOutputWriter.write(String.format("iteration %d out of %d\n",
+ mLastIteration + 1, mTotalIterations));
mOutputWriter.flush();
mOutputWriter.close();
super.tearDown();
@@ -79,40 +80,44 @@
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
config.preSharedKey = PASSWD;
- // If Wifi is enabled, disable it
+ // if wifiap enabled, disable it
+ assertTrue("failed to disable wifi hotspot",
+ mWifiManager.setWifiApEnabled(config, false));
+ assertTrue("wifi hotspot not enabled", waitForWifiApState(
+ WifiManager.WIFI_AP_STATE_DISABLED, 2 * LONG_TIMEOUT));
+
+ // if Wifi is enabled, disable it
if (mWifiManager.isWifiEnabled()) {
- disableWifi();
+ assertTrue("failed to disable wifi", disableWifi());
+ // wait for the wifi state to be DISABLED
+ assertTrue("wifi state not disabled", waitForWifiState(
+ WifiManager.WIFI_STATE_DISABLED, LONG_TIMEOUT));
}
int i;
- for (i = 0; i < iterations; i++) {
+ for (i = 0; i < mTotalIterations; i++) {
Log.v(TAG, "iteration: " + i);
mLastIteration = i;
// enable Wifi tethering
- assertTrue(mWifiManager.setWifiApEnabled(config, true));
- // Wait for wifi ap state to be ENABLED
- assertTrue(waitForWifiAPState(WifiManager.WIFI_AP_STATE_ENABLED, 2 * LONG_TIMEOUT));
- // Wait for wifi tethering result
- assertEquals(SUCCESS, waitForTetherStateChange(2 * SHORT_TIMEOUT));
- // Allow the wifi tethering to be enabled for 10 seconds
+ assertTrue("failed to enable wifi hotspot",
+ mWifiManager.setWifiApEnabled(config, true));
+ // wait for wifi ap state to be ENABLED
+ assertTrue("wifi hotspot not enabled", waitForWifiApState(
+ WifiManager.WIFI_AP_STATE_ENABLED, 2 * LONG_TIMEOUT));
+ // wait for wifi tethering result
+ assertTrue("tether state not changed", waitForTetherStateChange(LONG_TIMEOUT));
+ // allow the wifi tethering to be enabled for 10 seconds
try {
Thread.sleep(2 * SHORT_TIMEOUT);
} catch (Exception e) {
- fail("thread in sleep is interrupted");
+ // ignore
}
assertTrue("no uplink data connection after Wi-Fi tethering", pingTest(null));
- // Disable soft AP
- assertTrue(mWifiManager.setWifiApEnabled(config, false));
- // Wait for 30 seconds until Wi-Fi tethering is stopped
- try {
- Thread.sleep(30 * 1000);
- Log.v(TAG, "wait for Wi-Fi tethering to be disabled.");
- } catch (Exception e) {
- fail("thread in sleep is interrupted");
- }
- assertFalse("Wi-Fi AP disable failed", mWifiManager.isWifiApEnabled());
- }
- if (i == iterations) {
- mLastIteration = iterations;
+ // disable wifi hotspot
+ assertTrue("failed to disable wifi hotspot",
+ mWifiManager.setWifiApEnabled(config, false));
+ assertTrue("wifi hotspot not enabled", waitForWifiApState(
+ WifiManager.WIFI_AP_STATE_DISABLED, 2 * LONG_TIMEOUT));
+ assertFalse("wifi hotspot still enabled", mWifiManager.isWifiApEnabled());
}
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
index 08618d6..859c30c 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -16,20 +16,22 @@
package com.android.connectivitymanagertest.stress;
+import android.app.Activity;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.IpConfiguration.IpAssignment;
import android.net.IpConfiguration.ProxySettings;
+import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.net.wifi.ScanResult;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiManager;
+import android.os.Bundle;
import android.os.Environment;
import android.os.PowerManager;
import android.os.SystemClock;
import android.provider.Settings;
-import android.view.KeyEvent;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
@@ -49,15 +51,14 @@
* adb shell am instrument -e class com.android.connectivitymanagertest.stress.WifiStressTest
* -w com.android.connectivitymanagertest/.ConnectivityManagerStressTestRunner
*/
-public class WifiStressTest
- extends ConnectivityManagerTestBase {
+public class WifiStressTest extends ConnectivityManagerTestBase {
private final static String TAG = "WifiStressTest";
private final static long SCREEN_OFF_TIMER = 500; //500ms
/**
* Wi-Fi idle time for default sleep policy
*/
- private final static long WIFI_IDLE_MS = 60 * 1000;
+ private final static long WIFI_IDLE_MS = 15 * 1000;
/**
* Delay after issuing wifi shutdown.
@@ -69,7 +70,7 @@
private final static String OUTPUT_FILE = "WifiStressTestOutput.txt";
private int mReconnectIterations;
- private int mWifiSleepTime;
+ private long mWifiSleepTime;
private int mScanIterations;
private String mSsid;
private String mPassword;
@@ -78,16 +79,16 @@
private boolean mWifiOnlyFlag;
@Override
- public void setUp() throws Exception {
+ protected void setUp() throws Exception {
super.setUp();
mRunner = (ConnectivityManagerStressTestRunner) getInstrumentation();
- mReconnectIterations = mRunner.mReconnectIterations;
- mSsid = mRunner.mReconnectSsid;
- mPassword = mRunner.mReconnectPassword;
- mScanIterations = mRunner.mScanIterations;
- mWifiSleepTime = mRunner.mSleepTime;
- mWifiOnlyFlag = mRunner.mWifiOnlyFlag;
+ mReconnectIterations = mRunner.getReconnectIterations();
+ mSsid = mRunner.getReconnectSsid();
+ mPassword = mRunner.getReconnectPassword();
+ mScanIterations = mRunner.getScanIterations();
+ mWifiSleepTime = mRunner.getSleepTime();
+ mWifiOnlyFlag = mRunner.isWifiOnly();
log(String.format("mReconnectIterations(%d), mSsid(%s), mPassword(%s),"
+ "mScanIterations(%d), mWifiSleepTime(%d)", mReconnectIterations, mSsid,
mPassword, mScanIterations, mWifiSleepTime));
@@ -105,7 +106,7 @@
}
@Override
- public void tearDown() throws Exception {
+ protected void tearDown() throws Exception {
log("tearDown()");
if (mOutputWriter != null) {
mOutputWriter.close();
@@ -145,109 +146,90 @@
*/
@LargeTest
public void testWifiScanning() {
- int scanTimeSum = 0;
- int i;
+ long scanTimeSum = 0, i, averageScanTime = -1;
int ssidAppearInScanResultsCount = 0; // count times of given ssid appear in scan results.
- for (i = 0; i < mScanIterations; i++) {
+ for (i = 1; i <= mScanIterations; i++) {
log("testWifiScanning: iteration: " + i);
- int averageScanTime = 0;
- if (i > 0) {
- averageScanTime = scanTimeSum/i;
- }
- writeOutput(String.format("iteration %d out of %d",
- i, mScanIterations));
+ averageScanTime = scanTimeSum / i;
+ writeOutput(String.format("iteration %d out of %d", i, mScanIterations));
writeOutput(String.format("average scanning time is %d", averageScanTime));
writeOutput(String.format("ssid appear %d out of %d scan iterations",
ssidAppearInScanResultsCount, i));
- long startTime = SystemClock.uptimeMillis();
- scanResultAvailable = false;
- assertTrue("start scan failed", mWifiManager.startScan());
- while (true) {
- if ((SystemClock.uptimeMillis() - startTime) >
- WIFI_SCAN_TIMEOUT) {
- fail("Wifi scanning takes more than " + WIFI_SCAN_TIMEOUT + " ms");
+ List<ScanResult> scanResultLocal = null;
+ // wait for a scan result
+ long start = 0;
+ synchronized (mWifiScanResultLock) {
+ start = SystemClock.uptimeMillis();
+ assertTrue("start scan failed", mWifiManager.startScan());
+ try {
+ mWifiScanResultLock.wait(WAIT_FOR_SCAN_RESULT);
+ } catch (InterruptedException e) {
+ // ignore
}
- synchronized(this) {
- try {
- wait(WAIT_FOR_SCAN_RESULT);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if (scanResultAvailable) {
- long scanTime = (SystemClock.uptimeMillis() - startTime);
- scanTimeSum += scanTime;
- break;
- }
- }
+ scanTimeSum += SystemClock.uptimeMillis() - start;
+ // save the scan result while in lock
+ scanResultLocal = mLastScanResult;
}
- if ((mWifiManager.getScanResults() == null) ||
- (mWifiManager.getScanResults().size() <= 0)) {
+ if (scanResultLocal == null || scanResultLocal.isEmpty()) {
fail("Scan results are empty ");
}
-
- List<ScanResult> netList = mWifiManager.getScanResults();
- if (netList != null) {
- log("size of scan result list: " + netList.size());
- for (int s = 0; s < netList.size(); s++) {
- ScanResult sr= netList.get(s);
- log(String.format("scan result for %s is: %s", sr.SSID, sr.toString()));
- log(String.format("signal level for %s is %d ", sr.SSID, sr.level));
- if (sr.SSID.equals(mSsid)) {
- ssidAppearInScanResultsCount += 1;
- log("Number of times " + mSsid + " appear in the scan list: " +
- ssidAppearInScanResultsCount);
- break;
- }
+ log("size of scan result list: " + scanResultLocal.size());
+ for (ScanResult sr : scanResultLocal) {
+ log(String.format("scan result: " + sr.toString()));
+ if (mSsid.equals(sr.SSID)) {
+ ssidAppearInScanResultsCount += 1;
+ break;
}
}
}
- if (i == mScanIterations) {
- writeOutput(String.format("iteration %d out of %d",
- i, mScanIterations));
- writeOutput(String.format("average scanning time is %d", scanTimeSum/mScanIterations));
+ Bundle result = new Bundle();
+ result.putLong("actual-iterations", i - 1);
+ result.putLong("avg-scan-time", averageScanTime);
+ result.putInt("ap-discovered", ssidAppearInScanResultsCount);
+ getInstrumentation().sendStatus(Activity.RESULT_FIRST_USER, result);
+ if (i == mScanIterations + 1) {
+ writeOutput(String.format("iteration %d out of %d", i, mScanIterations));
+ writeOutput(String.format("average scanning time is %d", scanTimeSum / (i - 1)));
writeOutput(String.format("ssid appear %d out of %d scan iterations",
- ssidAppearInScanResultsCount, mScanIterations));
+ ssidAppearInScanResultsCount, i));
}
}
// Stress Wifi reconnection to secure net after sleep
@LargeTest
public void testWifiReconnectionAfterSleep() {
- int value = Settings.Global.getInt(mRunner.getContext().getContentResolver(),
- Settings.Global.WIFI_SLEEP_POLICY, -1);
- log("wifi sleep policy is: " + value);
- if (value != Settings.Global.WIFI_SLEEP_POLICY_DEFAULT) {
- Settings.Global.putInt(mRunner.getContext().getContentResolver(),
- Settings.Global.WIFI_SLEEP_POLICY, Settings.Global.WIFI_SLEEP_POLICY_DEFAULT);
- log("set wifi sleep policy to default value");
- }
+ // set wifi sleep policy to never on while in sleep
+ Settings.Global.putInt(mRunner.getContext().getContentResolver(),
+ Settings.Global.WIFI_SLEEP_POLICY, Settings.Global.WIFI_SLEEP_POLICY_NEVER);
+ // set idle timeout for wifi to 15s
Settings.Global.putLong(mRunner.getContext().getContentResolver(),
Settings.Global.WIFI_IDLE_MS, WIFI_IDLE_MS);
// Connect to a Wi-Fi network
WifiConfiguration config = new WifiConfiguration();
config.SSID = mSsid;
- config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
- if (mPassword.matches("[0-9A-Fa-f]{64}")) {
- config.preSharedKey = mPassword;
+ if (mPassword != null) {
+ config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+ if (isHex(mPassword, 64)) {
+ config.preSharedKey = mPassword;
+ } else {
+ config.preSharedKey = '"' + mPassword + '"';
+ }
} else {
- config.preSharedKey = '"' + mPassword + '"';
+ config.allowedKeyManagement.set(KeyMgmt.NONE);
}
config.setIpAssignment(IpAssignment.DHCP);
config.setProxySettings(ProxySettings.NONE);
assertTrue("Failed to connect to Wi-Fi network: " + mSsid,
connectToWifiWithConfiguration(config));
- assertTrue(waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
- SHORT_TIMEOUT));
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
- WIFI_CONNECTION_TIMEOUT));
+ assertTrue("wifi not connected", waitForNetworkState(ConnectivityManager.TYPE_WIFI,
+ State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
// Run ping test to verify the data connection
assertTrue("Wi-Fi is connected, but no data connection.", pingTest(null));
- int i;
- long sum = 0;
- for (i = 0; i < mReconnectIterations; i++) {
+ long i, sum = 0, avgReconnectTime = 0;
+ for (i = 1; i <= mReconnectIterations; i++) {
// 1. Put device into sleep mode
// 2. Wait for the device to sleep for sometime, verify wi-fi is off and mobile is on.
// 3. Maintain the sleep mode for some time,
@@ -261,53 +243,61 @@
long start = SystemClock.uptimeMillis();
PowerManager pm =
(PowerManager)mRunner.getContext().getSystemService(Context.POWER_SERVICE);
- while (pm.isScreenOn() && ((SystemClock.uptimeMillis() - start) < SCREEN_OFF_TIMER)) {
- sleep(100, "wait for screen off");
+ while (pm.isInteractive() &&
+ ((SystemClock.uptimeMillis() - start) < SCREEN_OFF_TIMER)) {
+ SystemClock.sleep(100);
}
- assertFalse(pm.isScreenOn());
- sleep(WIFI_IDLE_MS + WIFI_SHUTDOWN_DELAY, "Interruped while wait for wifi to be idle");
- assertTrue("Wait for Wi-Fi to idle timeout",
- waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
- 6 * SHORT_TIMEOUT));
- if (!mWifiOnlyFlag) {
+ assertFalse("screen still on", pm.isInteractive());
+ // wait for WiFi timeout
+ SystemClock.sleep(WIFI_IDLE_MS + WIFI_SHUTDOWN_DELAY);
+ // below check temporarily disabled due to bug in ConnectivityManager return
+// assertTrue("Wait for Wi-Fi to idle timeout",
+// waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
+// 6 * SHORT_TIMEOUT));
+ if (mWifiOnlyFlag) {
+ assertTrue("expected wifi disconnect, still has active connection",
+ waitUntilNoActiveNetworkConnection(2 * LONG_TIMEOUT));
+ } else {
// use long timeout as the pppd startup may take several retries.
- assertTrue("Wait for cellular connection timeout",
+ assertTrue("no fallback on mobile or wifi didn't disconnect",
waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
2 * LONG_TIMEOUT));
}
- sleep(mWifiSleepTime, "Interrupted while device is in sleep mode");
- // Verify the wi-fi is still off and data connection is on
- assertEquals("Wi-Fi is reconnected", State.DISCONNECTED,
- mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState());
-
- if (!mWifiOnlyFlag) {
- assertEquals("Cellular connection is down", State.CONNECTED,
- mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState());
- assertTrue("Mobile is connected, but no data connection.", pingTest(null));
+ SystemClock.sleep(mWifiSleepTime);
+ // verify the wi-fi is still off and either we have no connectivity or fallback on mobile
+ if (mWifiOnlyFlag) {
+ NetworkInfo ni = mCm.getActiveNetworkInfo();
+ if (ni != null) {
+ Log.e(TAG, "has active network while in wifi sleep: " + ni.toString());
+ fail("active network detected");
+ }
+ } else {
+ assertEquals("mobile not connected", State.CONNECTED,
+ mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState());
+ assertTrue("no connectivity over mobile", pingTest(null));
}
// Turn screen on again
turnScreenOn();
- // Wait for 2 seconds for the lock screen
- sleep(2 * 1000, "wait 2 seconds for lock screen");
- // Disable lock screen by inject menu key event
- mRunner.sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
-
// Measure the time for Wi-Fi to get connected
long startTime = SystemClock.uptimeMillis();
- assertTrue("Wait for Wi-Fi enable timeout after wake up",
- waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
- SHORT_TIMEOUT));
- assertTrue("Wait for Wi-Fi connection timeout after wake up",
+ assertTrue("screen on: wifi not enabled before timeout",
+ waitForWifiState(WifiManager.WIFI_STATE_ENABLED, SHORT_TIMEOUT));
+ assertTrue("screen on: wifi not connected before timeout",
waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
- WIFI_CONNECTION_TIMEOUT));
+ LONG_TIMEOUT));
long connectionTime = SystemClock.uptimeMillis() - startTime;
sum += connectionTime;
- log("average reconnection time is: " + sum/(i+1));
+ avgReconnectTime = sum / i;
+ log("average reconnection time is: " + avgReconnectTime);
assertTrue("Reconnect to Wi-Fi network, but no data connection.", pingTest(null));
}
- if (i == mReconnectIterations) {
+ Bundle result = new Bundle();
+ result.putLong("actual-iterations", i - 1);
+ result.putLong("avg-reconnect-time", avgReconnectTime);
+ getInstrumentation().sendStatus(Activity.RESULT_FIRST_USER, result);
+ if (i == mReconnectIterations + 1) {
writeOutput(String.format("iteration %d out of %d",
i, mReconnectIterations));
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiClientTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiClientTest.java
index 7a9bc78..5c2f388 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiClientTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiClientTest.java
@@ -38,7 +38,6 @@
public class WifiClientTest extends AndroidTestCase {
private WifiManager mWifiManager;
- private final String TAG = "WifiClientTest";
//10s delay for turning on wifi
private static final int DELAY = 10000;
diff --git a/docs/html/guide/components/intents-common.jd b/docs/html/guide/components/intents-common.jd
index 3b52b0a..af9456d 100644
--- a/docs/html/guide/components/intents-common.jd
+++ b/docs/html/guide/components/intents-common.jd
@@ -1678,7 +1678,7 @@
<p><b>Example intent:</b></p>
<pre>
public void composeMmsMessage(String message, Uri attachment) {
- Intent intent = new Intent(Intent.ACTION_SEND);
+ Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setType(HTTP.PLAIN_TEXT_TYPE);
intent.putExtra("sms_body", message);
intent.putExtra(Intent.EXTRA_STREAM, attachment);
diff --git a/docs/html/guide/topics/ui/declaring-layout.jd b/docs/html/guide/topics/ui/declaring-layout.jd
index cb952a4..ab105fd 100644
--- a/docs/html/guide/topics/ui/declaring-layout.jd
+++ b/docs/html/guide/topics/ui/declaring-layout.jd
@@ -31,7 +31,7 @@
<li>{@link android.view.ViewGroup}</li>
<li>{@link android.view.ViewGroup.LayoutParams}</li>
</ol>
-
+
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}training/basics/firstapp/building-ui.html">Building a Simple User
@@ -43,9 +43,9 @@
href="{@docRoot}guide/topics/appwidgets/index.html">app widget</a>.
You can declare a layout in two ways:</p>
<ul>
-<li><strong>Declare UI elements in XML</strong>. Android provides a straightforward XML
+<li><strong>Declare UI elements in XML</strong>. Android provides a straightforward XML
vocabulary that corresponds to the View classes and subclasses, such as those for widgets and layouts.</li>
-<li><strong>Instantiate layout elements at runtime</strong>. Your
+<li><strong>Instantiate layout elements at runtime</strong>. Your
application can create View and ViewGroup objects (and manipulate their properties) programmatically. </li>
</ul>
@@ -55,12 +55,12 @@
<div class="sidebox">
<ul>
<li>The <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT
- Plugin for Eclipse</a> offers a layout preview of your XML —
+ Plugin for Eclipse</a> offers a layout preview of your XML —
with the XML file opened, select the <strong>Layout</strong> tab.</li>
- <li>You should also try the
- <a href="{@docRoot}tools/debugging/debugging-ui.html#hierarchyViewer">Hierarchy Viewer</a> tool,
- for debugging layouts — it reveals layout property values,
- draws wireframes with padding/margin indicators, and full rendered views while
+ <li>You should also try the
+ <a href="{@docRoot}tools/debugging/debugging-ui.html#hierarchyViewer">Hierarchy Viewer</a> tool,
+ for debugging layouts — it reveals layout property values,
+ draws wireframes with padding/margin indicators, and full rendered views while
you debug on the emulator or device.</li>
<li>The <a href="{@docRoot}tools/debugging/debugging-ui.html#layoutopt">layoutopt</a> tool lets
you quickly analyze your layouts and hierarchies for inefficiencies or other problems.</li>
@@ -68,7 +68,7 @@
</div>
<p>The advantage to declaring your UI in XML is that it enables you to better separate the presentation of your application from the code that controls its behavior. Your UI descriptions are external to your application code, which means that you can modify or adapt it without having to modify your source code and recompile. For example, you can create XML layouts for different screen orientations, different device screen sizes, and different languages. Additionally, declaring the layout in XML makes it easier to visualize the structure of your UI, so it's easier to debug problems. As such, this document focuses on teaching you how to declare your layout in XML. If you're
-interested in instantiating View objects at runtime, refer to the {@link android.view.ViewGroup} and
+interested in instantiating View objects at runtime, refer to the {@link android.view.ViewGroup} and
{@link android.view.View} class references.</p>
<p>In general, the XML vocabulary for declaring UI elements closely follows the structure and naming of the classes and methods, where element names correspond to class names and attribute names correspond to methods. In fact, the correspondence is often so direct that you can guess what XML attribute corresponds to a class method, or guess what class corresponds to a given XML element. However, note that not all vocabulary is identical. In some cases, there are slight naming differences. For
@@ -102,7 +102,7 @@
</LinearLayout>
</pre>
-<p>After you've declared your layout in XML, save the file with the <code>.xml</code> extension,
+<p>After you've declared your layout in XML, save the file with the <code>.xml</code> extension,
in your Android project's <code>res/layout/</code> directory, so it will properly compile. </p>
<p>More information about the syntax for a layout XML file is available in the <a
@@ -111,11 +111,11 @@
<h2 id="load">Load the XML Resource</h2>
<p>When you compile your application, each XML layout file is compiled into a
-{@link android.view.View} resource. You should load the layout resource from your application code, in your
+{@link android.view.View} resource. You should load the layout resource from your application code, in your
{@link android.app.Activity#onCreate(android.os.Bundle) Activity.onCreate()} callback implementation.
-Do so by calling <code>{@link android.app.Activity#setContentView(int) setContentView()}</code>,
-passing it the reference to your layout resource in the form of:
-<code>R.layout.<em>layout_file_name</em></code>.
+Do so by calling <code>{@link android.app.Activity#setContentView(int) setContentView()}</code>,
+passing it the reference to your layout resource in the form of:
+<code>R.layout.<em>layout_file_name</em></code>.
For example, if your XML layout is saved as <code>main_layout.xml</code>, you would load it
for your Activity like so:</p>
<pre>
@@ -126,7 +126,7 @@
</pre>
<p>The <code>onCreate()</code> callback method in your Activity is called by the Android framework when
-your Activity is launched (see the discussion about lifecycles, in the
+your Activity is launched (see the discussion about lifecycles, in the
<a href="{@docRoot}guide/components/activities.html#Lifecycle">Activities</a>
document).</p>
@@ -136,18 +136,18 @@
<p>Every View and ViewGroup object supports their own variety of XML attributes.
Some attributes are specific to a View object (for example, TextView supports the <code>textSize</code>
attribute), but these attributes are also inherited by any View objects that may extend this class.
-Some are common to all View objects, because they are inherited from the root View class (like
-the <code>id</code> attribute). And, other attributes are considered "layout parameters," which are
+Some are common to all View objects, because they are inherited from the root View class (like
+the <code>id</code> attribute). And, other attributes are considered "layout parameters," which are
attributes that describe certain layout orientations of the View object, as defined by that object's
parent ViewGroup object.</p>
<h3 id="id">ID</h3>
<p>Any View object may have an integer ID associated with it, to uniquely identify the View within the tree.
-When the application is compiled, this ID is referenced as an integer, but the ID is typically
+When the application is compiled, this ID is referenced as an integer, but the ID is typically
assigned in the layout XML file as a string, in the <code>id</code> attribute.
This is an XML attribute common to all View objects
-(defined by the {@link android.view.View} class) and you will use it very often.
+(defined by the {@link android.view.View} class) and you will use it very often.
The syntax for an ID, inside an XML tag is:</p>
<pre>android:id="@+id/my_button"</pre>
@@ -170,7 +170,7 @@
android:text="@string/my_button_text"/>
</pre>
</li>
- <li>Then create an instance of the view object and capture it from the layout
+ <li>Then create an instance of the view object and capture it from the layout
(typically in the <code>{@link android.app.Activity#onCreate(Bundle) onCreate()}</code> method):
<pre>
Button myButton = (Button) findViewById(R.id.my_button);
@@ -178,16 +178,16 @@
</li>
</ol>
<p>Defining IDs for view objects is important when creating a {@link android.widget.RelativeLayout}.
-In a relative layout, sibling views can define their layout relative to another sibling view,
+In a relative layout, sibling views can define their layout relative to another sibling view,
which is referenced by the unique ID.</p>
<p>An ID need not be unique throughout the entire tree, but it should be
-unique within the part of the tree you are searching (which may often be the entire tree, so it's best
+unique within the part of the tree you are searching (which may often be the entire tree, so it's best
to be completely unique when possible).</p>
<h3 id="layout-params">Layout Parameters</h3>
-<p>XML layout attributes named <code>layout_<em>something</em></code> define
+<p>XML layout attributes named <code>layout_<em>something</em></code> define
layout parameters for the View that are appropriate for the ViewGroup in which it resides.</p>
<p>Every ViewGroup class implements a nested class that extends {@link
@@ -201,7 +201,7 @@
parameters associated with each view.</p>
<p>Note that every LayoutParams subclass has its own syntax for setting
-values. Each child element must define LayoutParams that are appropriate for its parent,
+values. Each child element must define LayoutParams that are appropriate for its parent,
though it may also define different LayoutParams for its own children. </p>
<p>All view groups include a width and height (<code>layout_width</code> and
@@ -236,7 +236,7 @@
two dimensions, expressed as a width and a height. The unit for location
and dimensions is the pixel.
</p>
-
+
<p>
It is possible to retrieve the location of a view by invoking the methods
{@link android.view.View#getLeft()} and {@link android.view.View#getTop()}. The former returns the left, or X,
@@ -246,7 +246,7 @@
when <code>getLeft()</code> returns 20, that means the view is located 20 pixels to the
right of the left edge of its direct parent.
</p>
-
+
<p>
In addition, several convenience methods are offered to avoid unnecessary
computations, namely {@link android.view.View#getRight()} and {@link android.view.View#getBottom()}.
@@ -254,14 +254,14 @@
rectangle representing the view. For instance, calling {@link android.view.View#getRight()}
is similar to the following computation: <code>getLeft() + getWidth()</code>.
</p>
-
+
<h2 id="SizePaddingMargins">Size, Padding and Margins</h2>
<p>
The size of a view is expressed with a width and a height. A view actually
possess two pairs of width and height values.
</p>
-
+
<p>
The first pair is known as <em>measured width</em> and
<em>measured height</em>. These dimensions define how big a view wants to be
@@ -269,16 +269,16 @@
measured dimensions can be obtained by calling {@link android.view.View#getMeasuredWidth()}
and {@link android.view.View#getMeasuredHeight()}.
</p>
-
+
<p>
The second pair is simply known as <em>width</em> and <em>height</em>, or
sometimes <em>drawing width</em> and <em>drawing height</em>. These
dimensions define the actual size of the view on screen, at drawing time and
after layout. These values may, but do not have to, be different from the
measured width and height. The width and height can be obtained by calling
- {@link android.view.View#getWidth()} and {@link android.view.View#getHeight()}.
+ {@link android.view.View#getWidth()} and {@link android.view.View#getHeight()}.
</p>
-
+
<p>
To measure its dimensions, a view takes into account its padding. The padding
is expressed in pixels for the left, top, right and bottom parts of the view.
@@ -287,9 +287,9 @@
2 pixels to the right of the left edge. Padding can be set using the
{@link android.view.View#setPadding(int, int, int, int)} method and queried by calling
{@link android.view.View#getPaddingLeft()}, {@link android.view.View#getPaddingTop()},
- {@link android.view.View#getPaddingRight()} and {@link android.view.View#getPaddingBottom()}.
+ {@link android.view.View#getPaddingRight()} and {@link android.view.View#getPaddingBottom()}.
</p>
-
+
<p>
Even though a view can define a padding, it does not provide any support for
margins. However, view groups provide such a support. Refer to
@@ -297,13 +297,13 @@
{@link android.view.ViewGroup.MarginLayoutParams} for further information.
</p>
- <p>For more information about dimensions, see
+ <p>For more information about dimensions, see
<a href="{@docRoot}guide/topics/resources/more-resources.html#Dimension">Dimension Values</a>.
</p>
-
-
-
+
+
+
<style type="text/css">
@@ -332,7 +332,7 @@
possible. Your layout draws faster if it has fewer nested layouts (a wide view hierarchy is
better than a deep view hierarchy).</p>
-<!--
+<!--
<h2 id="framelayout">FrameLayout</h2>
<p>{@link android.widget.FrameLayout FrameLayout} is the simplest type of layout
object. It's basically a blank space on your screen that you can
@@ -417,7 +417,7 @@
android.widget.ListView}, initialize a new {@link android.widget.ArrayAdapter} using a
constructor to specify the layout for each string and the string array:</p>
<pre>
-ArrayAdapter adapter = new ArrayAdapter<String>(this,
+ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, myStringArray);
</pre>
<p>The arguments for this constructor are:</p>
@@ -453,14 +453,14 @@
android.database.Cursor} you want in the layout for each result and an integer array specifying the
corresponding views that each column should be placed:</p>
<pre>
-String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,
+String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER};
int[] toViews = {R.id.display_name, R.id.phone_number};
</pre>
<p>When you instantiate the {@link android.widget.SimpleCursorAdapter}, pass the layout to use for
each result, the {@link android.database.Cursor} containing the results, and these two arrays:</p>
<pre>
-SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
+SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);
ListView listView = getListView();
listView.setAdapter(adapter);
@@ -490,7 +490,7 @@
}
};
-listView.setOnItemClickListener(mMessageClickedHandler);
+listView.setOnItemClickListener(mMessageClickedHandler);
</pre>
diff --git a/docs/html/sdk/installing/create-project.jd b/docs/html/sdk/installing/create-project.jd
index c0d523a..a7c12d4 100644
--- a/docs/html/sdk/installing/create-project.jd
+++ b/docs/html/sdk/installing/create-project.jd
@@ -76,7 +76,7 @@
<img src="{@docRoot}images/tools/wizard7.png" alt="" width="750" height="509">
<p class="img-caption"><strong>Figure 7.</strong> The default project structure for a mobile app.</p>
-<p>Now you are ready to develop your app. Fore more information, see the following links:</p>
+<p>Now you are ready to develop your app. For more information, see the following links:</p>
<ul>
<li><a href="{@docRoot}training/">Training Lessons</a></li>
diff --git a/docs/html/training/wearables/data-layer/assets.jd b/docs/html/training/wearables/data-layer/assets.jd
index 52ccbb0..5dc11cb 100644
--- a/docs/html/training/wearables/data-layer/assets.jd
+++ b/docs/html/training/wearables/data-layer/assets.jd
@@ -91,7 +91,7 @@
for (DataEvent event : dataEvents) {
if (event.getType() == DataEvent.TYPE_CHANGED &&
event.getDataItem().getUri().getPath().equals("/image")) {
- DataMapItem dataMapItem = DataMapItem.fromDataItem(dataItem);
+ DataMapItem dataMapItem = DataMapItem.fromDataItem(event.getDataItem());
Asset profileAsset = dataMapItem.getDataMap().getAsset("profileImage");
Bitmap bitmap = loadBitmapFromAsset(profileAsset);
// Do something with the bitmap
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index 265a564..6934955 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -28,8 +28,6 @@
*/
private long native_instance;
- private long native_with_local_matrix;
-
/**
* Initialization step that should be called by subclasses in their
* constructors. Calling again may result in memory leaks.
@@ -80,24 +78,18 @@
* Set the shader's local matrix. Passing null will reset the shader's
* matrix to identity.
*
- * Starting with {@link android.os.Build.VERSION_CODES#L}, this does not
- * modify any Paints which use this Shader. In order to modify the Paint,
- * you need to call {@link Paint#setShader} again. Further, any {@link ComposeShader}s
- * created with this Shader will be unaffected.
- *
* @param localM The shader's new local matrix, or null to specify identity
*/
public void setLocalMatrix(Matrix localM) {
mLocalMatrix = localM;
- native_with_local_matrix = nativeSetLocalMatrix(native_instance,
- native_with_local_matrix, localM == null ? 0 : localM.native_instance);
+ nativeSetLocalMatrix(native_instance, localM == null ? 0 : localM.native_instance);
}
protected void finalize() throws Throwable {
try {
super.finalize();
} finally {
- nativeDestructor(native_instance, native_with_local_matrix);
+ nativeDestructor(native_instance);
}
}
@@ -124,13 +116,9 @@
}
/* package */ long getNativeInstance() {
- if (native_with_local_matrix != 0) {
- return native_with_local_matrix;
- }
return native_instance;
}
- private static native void nativeDestructor(long native_shader, long native_with_local_matrix);
- private static native long nativeSetLocalMatrix(long native_shader,
- long native_with_local_matrix, long matrix_instance);
+ private static native void nativeDestructor(long native_shader);
+ private static native void nativeSetLocalMatrix(long native_shader, long matrix_instance);
}
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 06586ca..568d3f2 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -188,7 +188,7 @@
return createFromFamiliesWithDefault(families);
}
}
- return null;
+ throw new RuntimeException("Font asset not found " + path);
}
/**
@@ -215,7 +215,7 @@
return createFromFamiliesWithDefault(families);
}
}
- return null;
+ throw new RuntimeException("Font not found " + path);
}
/**
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index a9ebf21..ba22550 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -17,11 +17,15 @@
import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.ValueAnimator;
+import android.annotation.NonNull;
+import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
+import android.graphics.Outline;
+import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
@@ -129,7 +133,6 @@
private final AnimatedVectorDrawableState mAnimatedVectorState;
-
public AnimatedVectorDrawable() {
mAnimatedVectorState = new AnimatedVectorDrawableState(
new AnimatedVectorDrawableState(null));
@@ -163,6 +166,16 @@
}
@Override
+ protected boolean onStateChange(int[] state) {
+ return mAnimatedVectorState.mVectorDrawable.setState(state);
+ }
+
+ @Override
+ protected boolean onLevelChange(int level) {
+ return mAnimatedVectorState.mVectorDrawable.setLevel(level);
+ }
+
+ @Override
public int getAlpha() {
return mAnimatedVectorState.mVectorDrawable.getAlpha();
}
@@ -178,6 +191,43 @@
}
@Override
+ public void setTintList(ColorStateList tint) {
+ mAnimatedVectorState.mVectorDrawable.setTintList(tint);
+ }
+
+ @Override
+ public void setHotspot(float x, float y) {
+ mAnimatedVectorState.mVectorDrawable.setHotspot(x, y);
+ }
+
+ @Override
+ public void setHotspotBounds(int left, int top, int right, int bottom) {
+ mAnimatedVectorState.mVectorDrawable.setHotspotBounds(left, top, right, bottom);
+ }
+
+ @Override
+ public void setTintMode(PorterDuff.Mode tintMode) {
+ mAnimatedVectorState.mVectorDrawable.setTintMode(tintMode);
+ }
+
+ @Override
+ public boolean setVisible(boolean visible, boolean restart) {
+ mAnimatedVectorState.mVectorDrawable.setVisible(visible, restart);
+ return super.setVisible(visible, restart);
+ }
+
+ /** {@hide} */
+ @Override
+ public void setLayoutDirection(int layoutDirection) {
+ mAnimatedVectorState.mVectorDrawable.setLayoutDirection(layoutDirection);
+ }
+
+ @Override
+ public boolean isStateful() {
+ return mAnimatedVectorState.mVectorDrawable.isStateful();
+ }
+
+ @Override
public int getOpacity() {
return mAnimatedVectorState.mVectorDrawable.getOpacity();
}
@@ -193,6 +243,11 @@
}
@Override
+ public void getOutline(@NonNull Outline outline) {
+ mAnimatedVectorState.mVectorDrawable.getOutline(outline);
+ }
+
+ @Override
public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index e52d778..715da7e 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -81,14 +81,14 @@
private static final int TILE_MODE_REPEAT = 1;
private static final int TILE_MODE_MIRROR = 2;
- private final Rect mDstRect = new Rect(); // Gravity.apply() sets this
+ private final Rect mDstRect = new Rect(); // #updateDstRectAndInsetsIfDirty() sets this
private BitmapState mBitmapState;
private PorterDuffColorFilter mTintFilter;
private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
- private boolean mApplyGravity;
+ private boolean mDstRectAndInsetsDirty = true;
private boolean mMutated;
// These are scaled to match the target density.
@@ -96,7 +96,7 @@
private int mBitmapHeight;
/** Optical insets due to gravity. */
- private Insets mOpticalInsets = null;
+ private Insets mOpticalInsets = Insets.NONE;
// Mirroring matrix for using with Shaders
private Matrix mMirrorMatrix;
@@ -285,7 +285,7 @@
public void setGravity(int gravity) {
if (mBitmapState.mGravity != gravity) {
mBitmapState.mGravity = gravity;
- mApplyGravity = true;
+ mDstRectAndInsetsDirty = true;
invalidateSelf();
}
}
@@ -428,6 +428,7 @@
state.mTileModeX = xmode;
state.mTileModeY = ymode;
state.mRebuildShader = true;
+ mDstRectAndInsetsDirty = true;
invalidateSelf();
}
}
@@ -464,7 +465,7 @@
@Override
protected void onBoundsChange(Rect bounds) {
- mApplyGravity = true;
+ mDstRectAndInsetsDirty = true;
final Shader shader = mBitmapState.mPaint.getShader();
if (shader != null) {
@@ -503,7 +504,6 @@
}
state.mRebuildShader = false;
- copyBounds(mDstRect);
}
final int restoreAlpha;
@@ -523,14 +523,10 @@
clearColorFilter = false;
}
+ updateDstRectAndInsetsIfDirty();
final Shader shader = paint.getShader();
final boolean needMirroring = needMirroring();
if (shader == null) {
- if (mApplyGravity) {
- applyGravity();
- mApplyGravity = false;
- }
-
if (needMirroring) {
canvas.save();
// Mirror the bitmap
@@ -544,11 +540,6 @@
canvas.restore();
}
} else {
- if (mApplyGravity) {
- copyBounds(mDstRect);
- mApplyGravity = false;
- }
-
if (needMirroring) {
// Mirror the bitmap
updateMirrorMatrix(mDstRect.right - mDstRect.left);
@@ -574,39 +565,46 @@
}
}
+ private void updateDstRectAndInsetsIfDirty() {
+ if (mDstRectAndInsetsDirty) {
+ if (mBitmapState.mTileModeX == null && mBitmapState.mTileModeY == null) {
+ final Rect bounds = getBounds();
+ final int layoutDirection = getLayoutDirection();
+ Gravity.apply(mBitmapState.mGravity, mBitmapWidth, mBitmapHeight,
+ bounds, mDstRect, layoutDirection);
+
+ final int left = mDstRect.left - bounds.left;
+ final int top = mDstRect.top - bounds.top;
+ final int right = bounds.right - mDstRect.right;
+ final int bottom = bounds.bottom - mDstRect.bottom;
+ mOpticalInsets = Insets.of(left, top, right, bottom);
+ } else {
+ copyBounds(mDstRect);
+ mOpticalInsets = Insets.NONE;
+ }
+ }
+ mDstRectAndInsetsDirty = false;
+ }
+
/**
* @hide
*/
@Override
public Insets getOpticalInsets() {
- if (mApplyGravity && mBitmapState.mPaint.getShader() == null) {
- applyGravity();
- mApplyGravity = false;
- }
- return mOpticalInsets == null ? Insets.NONE : mOpticalInsets;
- }
-
- private void applyGravity() {
- final Rect bounds = getBounds();
- final int layoutDirection = getLayoutDirection();
- Gravity.apply(mBitmapState.mGravity, mBitmapWidth, mBitmapHeight,
- bounds, mDstRect, layoutDirection);
-
- final int left = mDstRect.left - bounds.left;
- final int top = mDstRect.top - bounds.top;
- final int right = bounds.right - mDstRect.right;
- final int bottom = bounds.bottom - mDstRect.bottom;
- mOpticalInsets = Insets.of(left, top, right, bottom);
+ updateDstRectAndInsetsIfDirty();
+ return mOpticalInsets;
}
@Override
public void getOutline(@NonNull Outline outline) {
- super.getOutline(outline);
- if (mBitmapState.mBitmap == null || mBitmapState.mBitmap.hasAlpha()) {
- // Only opaque Bitmaps can report a non-0 alpha,
- // since only they are guaranteed to fill their bounds
- outline.setAlpha(0.0f);
- }
+ updateDstRectAndInsetsIfDirty();
+ outline.setRect(mDstRect);
+
+ // Only opaque Bitmaps can report a non-0 alpha,
+ // since only they are guaranteed to fill their bounds
+ boolean opaqueOverShape = mBitmapState.mBitmap != null
+ && !mBitmapState.mBitmap.hasAlpha();
+ outline.setAlpha(opaqueOverShape ? getAlpha() / 255.0f : 0.0f);
}
@Override
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 29b9141..2c8611e 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -811,6 +811,11 @@
}
@Override
+ public ColorFilter getColorFilter() {
+ return mColorFilter;
+ }
+
+ @Override
public void setColorFilter(ColorFilter cf) {
if (cf != mColorFilter) {
mColorFilter = cf;
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index be2241b..063ac09 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -211,7 +211,7 @@
final boolean canUseHardware = c.isHardwareAccelerated();
if (mCanUseHardware != canUseHardware && mCanUseHardware) {
// We've switched from hardware to non-hardware mode. Panic.
- cancelHardwareAnimations();
+ cancelHardwareAnimations(true);
}
mCanUseHardware = canUseHardware;
@@ -231,7 +231,7 @@
final ArrayList<RenderNodeAnimator> pendingAnimations = mPendingAnimations;
final int N = pendingAnimations.size();
if (N > 0) {
- cancelHardwareAnimations();
+ cancelHardwareAnimations(false);
for (int i = 0; i < N; i++) {
pendingAnimations.get(i).setTarget(c);
@@ -399,6 +399,45 @@
invalidateSelf();
}
+ public void jump() {
+ endSoftwareAnimations();
+ endHardwareAnimations();
+ }
+
+ private void endSoftwareAnimations() {
+ if (mAnimRadius != null) {
+ mAnimRadius.end();
+ }
+
+ if (mAnimOpacity != null) {
+ mAnimOpacity.end();
+ }
+
+ if (mAnimX != null) {
+ mAnimX.end();
+ }
+
+ if (mAnimY != null) {
+ mAnimY.end();
+ }
+ }
+
+ private void endHardwareAnimations() {
+ final ArrayList<RenderNodeAnimator> runningAnimations = mRunningAnimations;
+ final int N = runningAnimations.size();
+ for (int i = 0; i < N; i++) {
+ runningAnimations.get(i).end();
+ }
+ runningAnimations.clear();
+
+ // Abort any pending animations. Since we always have a completion
+ // listener on a pending animation, we also need to remove ourselves.
+ if (!mPendingAnimations.isEmpty()) {
+ mPendingAnimations.clear();
+ removeSelf();
+ }
+ }
+
private Paint getTempPaint() {
if (mTempPaint == null) {
mTempPaint = new Paint();
@@ -444,7 +483,7 @@
*/
public void cancel() {
cancelSoftwareAnimations();
- cancelHardwareAnimations();
+ cancelHardwareAnimations(true);
}
private void cancelSoftwareAnimations() {
@@ -468,14 +507,18 @@
/**
* Cancels any running hardware animations.
*/
- private void cancelHardwareAnimations() {
+ private void cancelHardwareAnimations(boolean cancelPending) {
final ArrayList<RenderNodeAnimator> runningAnimations = mRunningAnimations;
final int N = runningAnimations.size();
for (int i = 0; i < N; i++) {
runningAnimations.get(i).cancel();
}
-
runningAnimations.clear();
+
+ if (cancelPending && !mPendingAnimations.isEmpty()) {
+ mPendingAnimations.clear();
+ removeSelf();
+ }
}
private void removeSelf() {
diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java
index 93df648..49862bc 100644
--- a/graphics/java/android/graphics/drawable/RippleBackground.java
+++ b/graphics/java/android/graphics/drawable/RippleBackground.java
@@ -203,7 +203,7 @@
final boolean canUseHardware = c.isHardwareAccelerated();
if (mCanUseHardware != canUseHardware && mCanUseHardware) {
// We've switched from hardware to non-hardware mode. Panic.
- cancelHardwareAnimations();
+ cancelHardwareAnimations(true);
}
mCanUseHardware = canUseHardware;
@@ -223,7 +223,7 @@
final ArrayList<RenderNodeAnimator> pendingAnimations = mPendingAnimations;
final int N = pendingAnimations.size();
if (N > 0) {
- cancelHardwareAnimations();
+ cancelHardwareAnimations(false);
for (int i = 0; i < N; i++) {
pendingAnimations.get(i).setTarget(c);
@@ -403,6 +403,41 @@
invalidateSelf();
}
+ public void jump() {
+ endSoftwareAnimations();
+ endHardwareAnimations();
+ }
+
+ private void endSoftwareAnimations() {
+ if (mAnimOuterOpacity != null) {
+ mAnimOuterOpacity.end();
+ }
+
+ if (mAnimX != null) {
+ mAnimX.end();
+ }
+
+ if (mAnimY != null) {
+ mAnimY.end();
+ }
+ }
+
+ private void endHardwareAnimations() {
+ final ArrayList<RenderNodeAnimator> runningAnimations = mRunningAnimations;
+ final int N = runningAnimations.size();
+ for (int i = 0; i < N; i++) {
+ runningAnimations.get(i).end();
+ }
+ runningAnimations.clear();
+
+ // Abort any pending animations. Since we always have a completion
+ // listener on a pending animation, we also need to remove ourselves.
+ if (!mPendingAnimations.isEmpty()) {
+ mPendingAnimations.clear();
+ removeSelf();
+ }
+ }
+
private Paint getTempPaint() {
if (mTempPaint == null) {
mTempPaint = new Paint();
@@ -477,7 +512,7 @@
*/
public void cancel() {
cancelSoftwareAnimations();
- cancelHardwareAnimations();
+ cancelHardwareAnimations(true);
}
private void cancelSoftwareAnimations() {
@@ -497,7 +532,7 @@
/**
* Cancels any running hardware animations.
*/
- private void cancelHardwareAnimations() {
+ private void cancelHardwareAnimations(boolean cancelPending) {
final ArrayList<RenderNodeAnimator> runningAnimations = mRunningAnimations;
final int N = runningAnimations.size();
for (int i = 0; i < N; i++) {
@@ -505,6 +540,11 @@
}
runningAnimations.clear();
+
+ if (cancelPending && !mPendingAnimations.isEmpty()) {
+ mPendingAnimations.clear();
+ removeSelf();
+ }
}
private void removeSelf() {
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 0447e17..ca32751f 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -199,6 +199,29 @@
}
@Override
+ public void jumpToCurrentState() {
+ super.jumpToCurrentState();
+
+ if (mRipple != null) {
+ mRipple.jump();
+ }
+
+ if (mBackground != null) {
+ mBackground.jump();
+ }
+
+ mClearingHotspots = true;
+ final int count = mAnimatingRipplesCount;
+ final Ripple[] ripples = mAnimatingRipples;
+ for (int i = 0; i < count; i++) {
+ ripples[i].jump();
+ ripples[i] = null;
+ }
+ mAnimatingRipplesCount = 0;
+ mClearingHotspots = false;
+ }
+
+ @Override
public void setAlpha(int alpha) {
super.setAlpha(alpha);
@@ -534,18 +557,6 @@
}
private void clearHotspots() {
- mClearingHotspots = true;
-
- final int count = mAnimatingRipplesCount;
- final Ripple[] ripples = mAnimatingRipples;
- for (int i = 0; i < count; i++) {
- // Calling cancel may remove the ripple from the animating ripple
- // array, so cache the reference before nulling it out.
- final Ripple ripple = ripples[i];
- ripples[i] = null;
- ripple.cancel();
- }
-
if (mRipple != null) {
mRipple.cancel();
mRipple = null;
@@ -556,8 +567,16 @@
mBackground = null;
}
- mClearingHotspots = false;
+ mClearingHotspots = true;
+ final int count = mAnimatingRipplesCount;
+ final Ripple[] ripples = mAnimatingRipples;
+ for (int i = 0; i < count; i++) {
+ ripples[i].cancel();
+ ripples[i] = null;
+ }
mAnimatingRipplesCount = 0;
+ mClearingHotspots = false;
+
invalidateSelf();
}
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index b56829d..1af497c 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -1459,6 +1459,9 @@
// Loads an unmapped reference table from the package.
status_t load(const ResTable_lib_header* const header);
+ // Adds mappings from the other DynamicRefTable
+ status_t addMappings(const DynamicRefTable& other);
+
// Creates a mapping from build-time package ID to run-time package ID for
// the given package.
status_t addMapping(const String16& packageName, uint8_t packageId);
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 2a4dec0..239d682 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -3346,6 +3346,7 @@
TypeList& typeList = pg->types.editItemAt(j);
typeList.appendVector(srcPg->types[j]);
}
+ pg->dynamicRefTable.addMappings(srcPg->dynamicRefTable);
pg->largestTypeId = max(pg->largestTypeId, srcPg->largestTypeId);
mPackageGroups.add(pg);
}
@@ -5604,7 +5605,6 @@
return (mError=NO_MEMORY);
}
- //printf("Adding new package id %d at index %d\n", id, idx);
err = mPackageGroups.add(group);
if (err < NO_ERROR) {
return (mError=err);
@@ -5844,6 +5844,37 @@
return NO_ERROR;
}
+status_t DynamicRefTable::addMappings(const DynamicRefTable& other) {
+ if (mAssignedPackageId != other.mAssignedPackageId) {
+ return UNKNOWN_ERROR;
+ }
+
+ const size_t entryCount = other.mEntries.size();
+ for (size_t i = 0; i < entryCount; i++) {
+ ssize_t index = mEntries.indexOfKey(other.mEntries.keyAt(i));
+ if (index < 0) {
+ mEntries.add(other.mEntries.keyAt(i), other.mEntries[i]);
+ } else {
+ if (other.mEntries[i] != mEntries[index]) {
+ return UNKNOWN_ERROR;
+ }
+ }
+ }
+
+ // Merge the lookup table. No entry can conflict
+ // (value of 0 means not set).
+ for (size_t i = 0; i < 256; i++) {
+ if (mLookupTable[i] != other.mLookupTable[i]) {
+ if (mLookupTable[i] == 0) {
+ mLookupTable[i] = other.mLookupTable[i];
+ } else if (other.mLookupTable[i] != 0) {
+ return UNKNOWN_ERROR;
+ }
+ }
+ }
+ return NO_ERROR;
+}
+
status_t DynamicRefTable::addMapping(const String16& packageName, uint8_t packageId)
{
ssize_t index = mEntries.indexOfKey(packageName);
@@ -6216,21 +6247,36 @@
printf("Package Groups (%d)\n", (int)pgCount);
for (size_t pgIndex=0; pgIndex<pgCount; pgIndex++) {
const PackageGroup* pg = mPackageGroups[pgIndex];
- printf("Package Group %d id=%d packageCount=%d name=%s\n",
+ printf("Package Group %d id=0x%02x packageCount=%d name=%s\n",
(int)pgIndex, pg->id, (int)pg->packages.size(),
String8(pg->name).string());
+ const KeyedVector<String16, uint8_t>& refEntries = pg->dynamicRefTable.entries();
+ const size_t refEntryCount = refEntries.size();
+ if (refEntryCount > 0) {
+ printf(" DynamicRefTable entryCount=%d:\n", (int) refEntryCount);
+ for (size_t refIndex = 0; refIndex < refEntryCount; refIndex++) {
+ printf(" 0x%02x -> %s\n",
+ refEntries.valueAt(refIndex),
+ String8(refEntries.keyAt(refIndex)).string());
+ }
+ printf("\n");
+ }
+
+ int packageId = pg->id;
size_t pkgCount = pg->packages.size();
for (size_t pkgIndex=0; pkgIndex<pkgCount; pkgIndex++) {
const Package* pkg = pg->packages[pkgIndex];
- printf(" Package %d id=%d name=%s\n", (int)pkgIndex,
+ // Use a package's real ID, since the ID may have been assigned
+ // if this package is a shared library.
+ packageId = pkg->package->id;
+ printf(" Package %d id=0x%02x name=%s\n", (int)pkgIndex,
pkg->package->id, String8(String16(pkg->package->name)).string());
}
for (size_t typeIndex=0; typeIndex < pg->types.size(); typeIndex++) {
const TypeList& typeList = pg->types[typeIndex];
if (typeList.isEmpty()) {
- //printf(" type %d NULL\n", (int)typeIndex);
continue;
}
const Type* typeConfigs = typeList[0];
@@ -6239,13 +6285,15 @@
(int)typeIndex, (int)NTC, (int)typeConfigs->entryCount);
if (typeConfigs->typeSpecFlags != NULL) {
for (size_t entryIndex=0; entryIndex<typeConfigs->entryCount; entryIndex++) {
- uint32_t resID = (0xff000000 & ((pg->id)<<24))
+ uint32_t resID = (0xff000000 & ((packageId)<<24))
| (0x00ff0000 & ((typeIndex+1)<<16))
| (0x0000ffff & (entryIndex));
// Since we are creating resID without actually
// iterating over them, we have no idea which is a
// dynamic reference. We must check.
- pg->dynamicRefTable.lookupResourceId(&resID);
+ if (packageId == 0) {
+ pg->dynamicRefTable.lookupResourceId(&resID);
+ }
resource_name resName;
if (this->getResourceName(resID, true, &resName)) {
@@ -6303,10 +6351,12 @@
continue;
}
- uint32_t resID = (0xff000000 & ((pg->id)<<24))
+ uint32_t resID = (0xff000000 & ((packageId)<<24))
| (0x00ff0000 & ((typeIndex+1)<<16))
| (0x0000ffff & (entryIndex));
- pg->dynamicRefTable.lookupResourceId(&resID);
+ if (packageId == 0) {
+ pg->dynamicRefTable.lookupResourceId(&resID);
+ }
resource_name resName;
if (this->getResourceName(resID, true, &resName)) {
String8 type8;
@@ -6387,9 +6437,11 @@
const ResTable_map* mapPtr = (ResTable_map*)(baseMapPtr+mapOffset);
const uint32_t parent = dtohl(bagPtr->parent.ident);
uint32_t resolvedParent = parent;
- status_t err = pg->dynamicRefTable.lookupResourceId(&resolvedParent);
- if (err != NO_ERROR) {
- resolvedParent = 0;
+ if (Res_GETPACKAGE(resolvedParent) + 1 == 0) {
+ status_t err = pg->dynamicRefTable.lookupResourceId(&resolvedParent);
+ if (err != NO_ERROR) {
+ resolvedParent = 0;
+ }
}
printf(" Parent=0x%08x(Resolved=0x%08x), Count=%d\n",
parent, resolvedParent, N);
diff --git a/libs/hwui/DamageAccumulator.cpp b/libs/hwui/DamageAccumulator.cpp
index 054a164..420e331 100644
--- a/libs/hwui/DamageAccumulator.cpp
+++ b/libs/hwui/DamageAccumulator.cpp
@@ -214,7 +214,7 @@
mHead->pendingDirty.join(left, top, right, bottom);
}
-void DamageAccumulator::peekAtDirty(SkRect* dest) {
+void DamageAccumulator::peekAtDirty(SkRect* dest) const {
*dest = mHead->pendingDirty;
}
diff --git a/libs/hwui/DamageAccumulator.h b/libs/hwui/DamageAccumulator.h
index 6f0bd8c..dd3365a 100644
--- a/libs/hwui/DamageAccumulator.h
+++ b/libs/hwui/DamageAccumulator.h
@@ -50,7 +50,7 @@
void dirty(float left, float top, float right, float bottom);
// Returns the current dirty area, *NOT* transformed by pushed transforms
- void peekAtDirty(SkRect* dest);
+ void peekAtDirty(SkRect* dest) const;
void computeCurrentTransform(Matrix4* outMatrix) const;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 0db6198..977744f 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -179,13 +179,6 @@
transformUpdateNeeded = true;
}
- if (transformUpdateNeeded) {
- // update the transform in window of the layer to reset its origin wrt light source position
- Matrix4 windowTransform;
- info.damageAccumulator->computeCurrentTransform(&windowTransform);
- mLayer->setWindowTransform(windowTransform);
- }
-
SkRect dirty;
info.damageAccumulator->peekAtDirty(&dirty);
@@ -198,6 +191,12 @@
return;
}
+ if (transformUpdateNeeded) {
+ // update the transform in window of the layer to reset its origin wrt light source position
+ Matrix4 windowTransform;
+ info.damageAccumulator->computeCurrentTransform(&windowTransform);
+ mLayer->setWindowTransform(windowTransform);
+ }
if (dirty.intersect(0, 0, getWidth(), getHeight())) {
dirty.roundOut();
@@ -216,7 +215,10 @@
if (info.mode == TreeInfo::MODE_FULL) {
pushStagingPropertiesChanges(info);
}
- uint32_t animatorDirtyMask = mAnimatorManager.animate(info);
+ uint32_t animatorDirtyMask = 0;
+ if (CC_LIKELY(info.runAnimations)) {
+ animatorDirtyMask = mAnimatorManager.animate(info);
+ }
prepareLayer(info, animatorDirtyMask);
if (info.mode == TreeInfo::MODE_FULL) {
pushStagingDisplayListChanges(info);
@@ -231,7 +233,9 @@
// Push the animators first so that setupStartValueIfNecessary() is called
// before properties() is trampled by stagingProperties(), as they are
// required by some animators.
- mAnimatorManager.pushStaging(info);
+ if (CC_LIKELY(info.runAnimations)) {
+ mAnimatorManager.pushStaging(info);
+ }
if (mDirtyPropertyFields) {
mDirtyPropertyFields = 0;
damageSelf(info);
diff --git a/libs/hwui/StatefulBaseRenderer.cpp b/libs/hwui/StatefulBaseRenderer.cpp
index 06c5ab4..bdac47b 100644
--- a/libs/hwui/StatefulBaseRenderer.cpp
+++ b/libs/hwui/StatefulBaseRenderer.cpp
@@ -196,12 +196,14 @@
float radius;
if (!outline->getAsRoundRect(&bounds, &radius)) return; // only RR supported
- if (!MathUtils::isPositive(radius)) {
+ bool outlineIsRounded = MathUtils::isPositive(radius);
+ if (!outlineIsRounded || currentTransform()->isSimple()) {
// TODO: consider storing this rect separately, so that this can't be replaced with clip ops
clipRect(bounds.left, bounds.top, bounds.right, bounds.bottom, SkRegion::kIntersect_Op);
- return;
}
- setClippingRoundRect(allocator, bounds, radius);
+ if (outlineIsRounded) {
+ setClippingRoundRect(allocator, bounds, radius);
+ }
}
void StatefulBaseRenderer::setClippingRoundRect(LinearAllocator& allocator,
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 331f157..74d52a3 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -65,6 +65,7 @@
, frameTimeMs(0)
, animationHook(NULL)
, prepareTextures(mode == MODE_FULL)
+ , runAnimations(true)
, damageAccumulator(NULL)
, renderState(renderState)
, renderer(NULL)
@@ -76,6 +77,7 @@
, frameTimeMs(clone.frameTimeMs)
, animationHook(clone.animationHook)
, prepareTextures(mode == MODE_FULL)
+ , runAnimations(clone.runAnimations)
, damageAccumulator(clone.damageAccumulator)
, renderState(clone.renderState)
, renderer(clone.renderer)
@@ -88,6 +90,12 @@
// TODO: Remove this? Currently this is used to signal to stop preparing
// textures if we run out of cache space.
bool prepareTextures;
+ // TODO: buildLayer uses this to suppress running any animations, but this
+ // should probably be refactored somehow. The reason this is done is
+ // because buildLayer is not setup for injecting the animationHook, as well
+ // as this being otherwise wasted work as all the animators will be
+ // re-evaluated when the frame is actually drawn
+ bool runAnimations;
// Must not be null during actual usage
DamageAccumulator* damageAccumulator;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index e673b0d..4bf5a8a 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -244,6 +244,30 @@
thread.renderState().invokeFunctor(functor, mode, NULL);
}
+void CanvasContext::buildLayer(RenderNode* node) {
+ ATRACE_CALL();
+ if (!mEglManager.hasEglContext() || !mCanvas) {
+ return;
+ }
+ requireGlContext();
+ // buildLayer() will leave the tree in an unknown state, so we must stop drawing
+ stopDrawing();
+
+ TreeInfo info(TreeInfo::MODE_FULL, mRenderThread.renderState());
+ info.frameTimeMs = mRenderThread.timeLord().frameTimeMs();
+ info.damageAccumulator = &mDamageAccumulator;
+ info.renderer = mCanvas;
+ info.runAnimations = false;
+ node->prepareTree(info);
+ SkRect ignore;
+ mDamageAccumulator.finish(&ignore);
+ // Tickle the GENERIC property on node to mark it as dirty for damaging
+ // purposes when the frame is actually drawn
+ node->setPropertyFieldsDirty(RenderNode::GENERIC);
+
+ mCanvas->flushLayerUpdates();
+}
+
bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
requireGlContext();
layer->apply();
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 2a01027..0cbed6f 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -65,6 +65,7 @@
// IFrameCallback, Chroreographer-driven frame callback entry point
virtual void doFrame();
+ void buildLayer(RenderNode* node);
bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
void destroyHardwareResources();
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index d9b96f6c..405ce24 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -284,6 +284,18 @@
return layer;
}
+CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) {
+ args->context->buildLayer(args->node);
+ return NULL;
+}
+
+void RenderProxy::buildLayer(RenderNode* node) {
+ SETUP_TASK(buildLayer);
+ args->context = mContext;
+ args->node = node;
+ postAndWait(task);
+}
+
CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer,
SkBitmap* bitmap) {
bool success = args->context->copyLayerInto(args->layer, args->bitmap);
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 28d0173..eea3674 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -81,6 +81,7 @@
static void enqueueDestroyLayer(Layer* layer);
ANDROID_API DeferredLayerUpdater* createDisplayListLayer(int width, int height);
ANDROID_API DeferredLayerUpdater* createTextureLayer();
+ ANDROID_API void buildLayer(RenderNode* node);
ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
ANDROID_API void pushLayerUpdate(DeferredLayerUpdater* layer);
ANDROID_API void cancelLayerUpdate(DeferredLayerUpdater* layer);
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 7bf9e98..96e6ab9 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -94,9 +94,17 @@
* and {@link #dequeueOutputBuffer} then transfer ownership from the codec
* to the client.<p>
* The client is not required to resubmit/release buffers immediately
- * to the codec, the sample code above simply does this for simplicity's sake.<p>
+ * to the codec, the sample code above simply does this for simplicity's sake.
+ * Nonetheless, it is possible that a codec may hold off on generating
+ * output buffers until all outstanding buffers have been
+ * released/resubmitted.
+ * <p>
* Once the client has an input buffer available it can fill it with data
- * and submit it it to the codec via a call to {@link #queueInputBuffer}.<p>
+ * and submit it it to the codec via a call to {@link #queueInputBuffer}.
+ * Do not submit multiple input buffers with the same timestamp (unless
+ * it is codec-specific data marked as such using the flag
+ * {@link #BUFFER_FLAG_CODEC_CONFIG}).
+ * <p>
* The codec in turn will return an output buffer to the client in response
* to {@link #dequeueOutputBuffer}. After the output buffer has been processed
* a call to {@link #releaseOutputBuffer} will return it to the codec.
@@ -128,18 +136,64 @@
* {@link #queueInputBuffer}. The codec will continue to return output buffers
* until it eventually signals the end of the output stream by specifying
* the same flag ({@link #BUFFER_FLAG_END_OF_STREAM}) on the BufferInfo returned in
- * {@link #dequeueOutputBuffer}.
+ * {@link #dequeueOutputBuffer}. Do not submit additional input buffers after
+ * signaling the end of the input stream, unless the codec has been flushed,
+ * or stopped and restarted.
* <p>
+ * <h3>Seeking & Adaptive Playback Support</h3>
+ *
+ * You can check if a decoder supports adaptive playback via {@link
+ * MediaCodecInfo.CodecCapabilities#isFeatureSupported}. Adaptive playback
+ * is only supported if you configure the codec to decode onto a {@link
+ * android.view.Surface}.
+ *
+ * <h4>For decoders that do not support adaptive playback (including
+ * when not decoding onto a Surface)</h4>
+ *
* In order to start decoding data that's not adjacent to previously submitted
- * data (i.e. after a seek) it is necessary to {@link #flush} the decoder.
+ * data (i.e. after a seek) <em>one must</em> {@link #flush} the decoder.
* Any input or output buffers the client may own at the point of the flush are
* immediately revoked, i.e. after a call to {@link #flush} the client does not
* own any buffers anymore.
+ * <p>
+ * It is important that the input data after a flush starts at a suitable
+ * stream boundary. The first frame must be able to be decoded completely on
+ * its own (for most codecs this means an I-frame), and that no frames should
+ * refer to frames before that first new frame.
* Note that the format of the data submitted after a flush must not change,
* flush does not support format discontinuities,
- * for this a full {@link #stop}, {@link #configure}, {@link #start}
+ * for this a full {@link #stop}, {@link #configure configure()}, {@link #start}
* cycle is necessary.
*
+ * <h4>For decoders that support adaptive playback</h4>
+ *
+ * In order to start decoding data that's not adjacent to previously submitted
+ * data (i.e. after a seek) it is <em>not necessary</em> to {@link #flush} the
+ * decoder.
+ * <p>
+ * It is still important that the input data after the discontinuity starts
+ * at a suitable stream boundary (e.g. I-frame), and that no new frames refer
+ * to frames before the first frame of the new input data segment.
+ * <p>
+ * For some video formats it is also possible to change the picture size
+ * mid-stream. To do this for H.264, the new Sequence Parameter Set (SPS) and
+ * Picture Parameter Set (PPS) values must be packaged together with an
+ * Instantaneous Decoder Refresh (IDR) frame in a single buffer, which then
+ * can be enqueued as a regular input buffer.
+ * The client will receive an {@link #INFO_OUTPUT_FORMAT_CHANGED} return
+ * value from {@link #dequeueOutputBuffer dequeueOutputBuffer()} or
+ * {@link Callback#onOutputBufferAvailable onOutputBufferAvailable()}
+ * just after the picture-size change takes place and before any
+ * frames with the new size have been returned.
+ * <p>
+ * Be careful when calling {@link #flush} shortly after you have changed
+ * the picture size. If you have not received confirmation of the picture
+ * size change, you will need to repeat the request for the new picture size.
+ * E.g. for H.264 you will need to prepend the PPS/SPS to the new IDR
+ * frame to ensure that the codec receives the picture size change request.
+ *
+ * <h3>States and error handling</h3>
+ *
* <p> During its life, a codec conceptually exists in one of the following states:
* Initialized, Configured, Executing, Error, Uninitialized, (omitting transitory states
* between them). When created by one of the factory methods,
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index ae2d024..acb2186 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -959,6 +959,23 @@
}
}
}
+ // for now this just means using the smaller max size as 2nd
+ // upper limit.
+ // for now we are keeping the profile specific "width/height
+ // in macroblocks" limits.
+ if (Integer.valueOf(1).equals(map.get("feature-can-swap-width-height"))) {
+ if (widths != null) {
+ mSmallerDimensionUpperLimit =
+ Math.min(widths.getUpper(), heights.getUpper());
+ widths = heights = widths.extend(heights);
+ } else {
+ Log.w(TAG, "feature can-swap-width-height is best used with size-range");
+ mSmallerDimensionUpperLimit =
+ Math.min(mWidthRange.getUpper(), mHeightRange.getUpper());
+ mWidthRange = mHeightRange = mWidthRange.extend(mHeightRange);
+ }
+ }
+
ratios = Utils.parseRationalRange(
map.get("block-aspect-ratio-range"), null);
blockRatios = Utils.parseRationalRange(
@@ -1124,9 +1141,17 @@
private void updateLimits() {
// pixels -> blocks <- counts
mHorizontalBlockRange = mHorizontalBlockRange.intersect(
- Utils.factorRange(mWidthRange, mBlockWidth)).intersect(mBlockCountRange);
+ Utils.factorRange(mWidthRange, mBlockWidth));
+ mHorizontalBlockRange = mHorizontalBlockRange.intersect(
+ Range.create(
+ mBlockCountRange.getLower() / mVerticalBlockRange.getUpper(),
+ mBlockCountRange.getUpper() / mVerticalBlockRange.getLower()));
mVerticalBlockRange = mVerticalBlockRange.intersect(
- Utils.factorRange(mHeightRange, mBlockHeight)).intersect(mBlockCountRange);
+ Utils.factorRange(mHeightRange, mBlockHeight));
+ mVerticalBlockRange = mVerticalBlockRange.intersect(
+ Range.create(
+ mBlockCountRange.getLower() / mHorizontalBlockRange.getUpper(),
+ mBlockCountRange.getUpper() / mHorizontalBlockRange.getLower()));
mBlockCountRange = mBlockCountRange.intersect(
Range.create(
mHorizontalBlockRange.getLower()
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index d3b1520..05acf90 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -47,6 +47,7 @@
private InputStream mInputStream = null;
private boolean mAllowCrossDomainRedirect = true;
+ private boolean mAllowCrossProtocolRedirect = true;
// from com.squareup.okhttp.internal.http
private final static int HTTP_TEMP_REDIRECT = 307;
@@ -91,6 +92,8 @@
private boolean filterOutInternalHeaders(String key, String val) {
if ("android-allow-cross-domain-redirect".equalsIgnoreCase(key)) {
mAllowCrossDomainRedirect = parseBoolean(val);
+ // cross-protocol redirects are also controlled by this flag
+ mAllowCrossProtocolRedirect = mAllowCrossDomainRedirect;
} else {
return false;
}
@@ -190,8 +193,12 @@
!url.getProtocol().equals("http")) {
throw new NoRouteToHostException("Unsupported protocol redirect");
}
+ boolean sameProtocol = mURL.getProtocol().equals(url.getProtocol());
+ if (!mAllowCrossProtocolRedirect && !sameProtocol) {
+ throw new NoRouteToHostException("Cross-protocol redirects are disallowed");
+ }
boolean sameHost = mURL.getHost().equals(url.getHost());
- if (!sameHost) {
+ if (!mAllowCrossDomainRedirect && !sameHost) {
throw new NoRouteToHostException("Cross-domain redirects are disallowed");
}
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 7cda961..6a4bf07 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -190,14 +190,6 @@
final int mainType = mCurAudioRoutesInfo.mMainType;
- boolean a2dpEnabled;
- try {
- a2dpEnabled = mAudioService.isBluetoothA2dpOn();
- } catch (RemoteException e) {
- Log.e(TAG, "Error querying Bluetooth A2DP state", e);
- a2dpEnabled = false;
- }
-
if (!TextUtils.equals(newRoutes.mBluetoothName, mCurAudioRoutesInfo.mBluetoothName)) {
mCurAudioRoutesInfo.mBluetoothName = newRoutes.mBluetoothName;
if (mCurAudioRoutesInfo.mBluetoothName != null) {
@@ -220,6 +212,7 @@
}
if (mBluetoothA2dpRoute != null) {
+ final boolean a2dpEnabled = isBluetoothA2dpOn();
if (mainType != AudioRoutesInfo.MAIN_SPEAKER &&
mSelectedRoute == mBluetoothA2dpRoute && !a2dpEnabled) {
selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo, false);
@@ -230,6 +223,15 @@
}
}
+ boolean isBluetoothA2dpOn() {
+ try {
+ return mAudioService.isBluetoothA2dpOn();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error querying Bluetooth A2DP state", e);
+ return false;
+ }
+ }
+
void updateDiscoveryRequest() {
// What are we looking for today?
int routeTypes = 0;
@@ -950,7 +952,7 @@
static void selectDefaultRouteStatic() {
// TODO: Be smarter about the route types here; this selects for all valid.
if (sStatic.mSelectedRoute != sStatic.mBluetoothA2dpRoute
- && sStatic.mBluetoothA2dpRoute != null) {
+ && sStatic.mBluetoothA2dpRoute != null && sStatic.isBluetoothA2dpOn()) {
selectRouteStatic(ROUTE_TYPE_ANY, sStatic.mBluetoothA2dpRoute, false);
} else {
selectRouteStatic(ROUTE_TYPE_ANY, sStatic.mDefaultAudioVideo, false);
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index 2a0fd83..3c2ad0e 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -389,6 +389,7 @@
public void registerWithSession(MediaSessionLegacyHelper helper) {
helper.addRccListener(mRcMediaIntent, mTransportListener);
mSession = helper.getSession(mRcMediaIntent);
+ setTransportControlFlags(mTransportControlFlags);
}
/**
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 2ec0293..d7baaa9 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -247,14 +247,14 @@
}
/**
- * Get the current audio info for this session.
+ * Get the current playback info for this session.
*
- * @return The current audio info or null.
+ * @return The current playback info or null.
*/
- public @Nullable AudioInfo getAudioInfo() {
+ public @Nullable PlaybackInfo getPlaybackInfo() {
try {
ParcelableVolumeInfo result = mSessionBinder.getVolumeAttributes();
- return new AudioInfo(result.volumeType, result.audioAttrs, result.controlType,
+ return new PlaybackInfo(result.volumeType, result.audioAttrs, result.controlType,
result.maxVolume, result.currentVolume);
} catch (RemoteException e) {
@@ -269,7 +269,7 @@
*
* @return A {@link PendingIntent} to launch UI or null.
*/
- public @Nullable PendingIntent getLaunchActivity() {
+ public @Nullable PendingIntent getSessionActivity() {
try {
return mSessionBinder.getLaunchPendingIntent();
} catch (RemoteException e) {
@@ -293,9 +293,10 @@
* {@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}. The flags in
* {@link AudioManager} may be used to affect the handling.
*
- * @see #getAudioInfo()
+ * @see #getPlaybackInfo()
* @param value The value to set it to, between 0 and the reported max.
- * @param flags Any flags to pass with the command.
+ * @param flags Flags from {@link AudioManager} to include with the volume
+ * request.
*/
public void setVolumeTo(int value, int flags) {
try {
@@ -314,7 +315,7 @@
* {@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}. The flags in
* {@link AudioManager} may be used to affect the handling.
*
- * @see #getAudioInfo()
+ * @see #getPlaybackInfo()
* @param direction The direction to adjust the volume in.
* @param flags Any flags to pass with the command.
*/
@@ -565,7 +566,7 @@
*
* @param info The current audio info for this session.
*/
- public void onAudioInfoChanged(AudioInfo info) {
+ public void onAudioInfoChanged(PlaybackInfo info) {
}
}
@@ -773,9 +774,19 @@
}
/**
- * Holds information about the way audio is handled for this session.
+ * Holds information about the current playback and how audio is handled for
+ * this session.
*/
- public static final class AudioInfo {
+ public static final class PlaybackInfo {
+ /**
+ * The session uses remote playback.
+ */
+ public static final int PLAYBACK_TYPE_REMOTE = 2;
+ /**
+ * The session uses local playback.
+ */
+ public static final int PLAYBACK_TYPE_LOCAL = 1;
+
private final int mVolumeType;
private final int mVolumeControl;
private final int mMaxVolume;
@@ -785,7 +796,7 @@
/**
* @hide
*/
- public AudioInfo(int type, AudioAttributes attrs, int control, int max, int current) {
+ public PlaybackInfo(int type, AudioAttributes attrs, int control, int max, int current) {
mVolumeType = type;
mAudioAttrs = attrs;
mVolumeControl = control;
@@ -794,22 +805,22 @@
}
/**
- * Get the type of volume handling, either local or remote. One of:
+ * Get the type of playback which affects volume handling. One of:
* <ul>
- * <li>{@link MediaSession#PLAYBACK_TYPE_LOCAL}</li>
- * <li>{@link MediaSession#PLAYBACK_TYPE_REMOTE}</li>
+ * <li>{@link #PLAYBACK_TYPE_LOCAL}</li>
+ * <li>{@link #PLAYBACK_TYPE_REMOTE}</li>
* </ul>
*
- * @return The type of volume handling this session is using.
+ * @return The type of playback this session is using.
*/
- public int getVolumeType() {
+ public int getPlaybackType() {
return mVolumeType;
}
/**
* Get the audio attributes for this session. The attributes will affect
* volume handling for the session. When the volume type is
- * {@link MediaSession#PLAYBACK_TYPE_REMOTE} these may be ignored by the
+ * {@link PlaybackInfo#PLAYBACK_TYPE_REMOTE} these may be ignored by the
* remote volume handler.
*
* @return The attributes for this session.
@@ -920,7 +931,7 @@
public void onVolumeInfoChanged(ParcelableVolumeInfo pvi) {
MediaController controller = mController.get();
if (controller != null) {
- AudioInfo info = new AudioInfo(pvi.volumeType, pvi.audioAttrs, pvi.controlType,
+ PlaybackInfo info = new PlaybackInfo(pvi.volumeType, pvi.audioAttrs, pvi.controlType,
pvi.maxVolume, pvi.currentVolume);
controller.postMessage(MSG_UPDATE_VOLUME, info, null);
}
@@ -958,7 +969,7 @@
mCallback.onExtrasChanged((Bundle) msg.obj);
break;
case MSG_UPDATE_VOLUME:
- mCallback.onAudioInfoChanged((AudioInfo) msg.obj);
+ mCallback.onAudioInfoChanged((PlaybackInfo) msg.obj);
break;
case MSG_DESTROYED:
mCallback.onSessionDestroyed();
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index de725fc..eac6809 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -101,16 +101,6 @@
FLAG_EXCLUSIVE_GLOBAL_PRIORITY })
public @interface SessionFlags { }
- /**
- * The session uses local playback.
- */
- public static final int PLAYBACK_TYPE_LOCAL = 1;
-
- /**
- * The session uses remote playback.
- */
- public static final int PLAYBACK_TYPE_REMOTE = 2;
-
private final Object mLock = new Object();
private final MediaSession.Token mSessionToken;
@@ -215,7 +205,7 @@
*
* @param pi The intent to launch to show UI for this Session.
*/
- public void setLaunchActivity(@Nullable PendingIntent pi) {
+ public void setSessionActivity(@Nullable PendingIntent pi) {
try {
mBinder.setLaunchPendingIntent(pi);
} catch (RemoteException e) {
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 8a1e076..185c6d8 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -148,8 +148,29 @@
public void addOnActiveSessionsChangedListener(
@NonNull OnActiveSessionsChangedListener sessionListener,
@Nullable ComponentName notificationListener) {
+ addOnActiveSessionsChangedListener(sessionListener, notificationListener, null);
+ }
+
+ /**
+ * Add a listener to be notified when the list of active sessions
+ * changes.This requires the
+ * android.Manifest.permission.MEDIA_CONTENT_CONTROL permission be held by
+ * the calling app. You may also retrieve this list if your app is an
+ * enabled notification listener using the
+ * {@link NotificationListenerService} APIs, in which case you must pass the
+ * {@link ComponentName} of your enabled listener. Updates will be posted to
+ * the handler specified or to the caller's thread if the handler is null.
+ *
+ * @param sessionListener The listener to add.
+ * @param notificationListener The enabled notification listener component.
+ * May be null.
+ * @param handler The handler to post events to.
+ */
+ public void addOnActiveSessionsChangedListener(
+ @NonNull OnActiveSessionsChangedListener sessionListener,
+ @Nullable ComponentName notificationListener, @Nullable Handler handler) {
addOnActiveSessionsChangedListener(sessionListener, notificationListener,
- UserHandle.myUserId(), null);
+ UserHandle.myUserId(), handler);
}
/**
diff --git a/media/java/android/media/session/ParcelableVolumeInfo.java b/media/java/android/media/session/ParcelableVolumeInfo.java
index 96a45d9b..f59c975 100644
--- a/media/java/android/media/session/ParcelableVolumeInfo.java
+++ b/media/java/android/media/session/ParcelableVolumeInfo.java
@@ -21,7 +21,7 @@
/**
* Convenience class for passing information about the audio configuration of a
- * session. The public implementation is {@link MediaController.AudioInfo}.
+ * session. The public implementation is {@link MediaController.PlaybackInfo}.
*
* @hide
*/
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 566e218..2ca97dd 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -217,7 +217,7 @@
private final int mState;
private final long mPosition;
- private final long mBufferPosition;
+ private final long mBufferedPosition;
private final float mSpeed;
private final long mActions;
private List<PlaybackState.CustomAction> mCustomActions;
@@ -226,14 +226,14 @@
private final long mActiveItemId;
private PlaybackState(int state, long position, long updateTime, float speed,
- long bufferPosition, long transportControls,
+ long bufferedPosition, long transportControls,
List<PlaybackState.CustomAction> customActions, long activeItemId,
CharSequence error) {
mState = state;
mPosition = position;
mSpeed = speed;
mUpdateTime = updateTime;
- mBufferPosition = bufferPosition;
+ mBufferedPosition = bufferedPosition;
mActions = transportControls;
mCustomActions = new ArrayList<>(customActions);
mActiveItemId = activeItemId;
@@ -245,7 +245,7 @@
mPosition = in.readLong();
mSpeed = in.readFloat();
mUpdateTime = in.readLong();
- mBufferPosition = in.readLong();
+ mBufferedPosition = in.readLong();
mActions = in.readLong();
mCustomActions = in.createTypedArrayList(CustomAction.CREATOR);
mActiveItemId = in.readLong();
@@ -258,7 +258,7 @@
StringBuilder bob = new StringBuilder("PlaybackState {");
bob.append("state=").append(mState);
bob.append(", position=").append(mPosition);
- bob.append(", buffered position=").append(mBufferPosition);
+ bob.append(", buffered position=").append(mBufferedPosition);
bob.append(", speed=").append(mSpeed);
bob.append(", updated=").append(mUpdateTime);
bob.append(", actions=").append(mActions);
@@ -280,7 +280,7 @@
dest.writeLong(mPosition);
dest.writeFloat(mSpeed);
dest.writeLong(mUpdateTime);
- dest.writeLong(mBufferPosition);
+ dest.writeLong(mBufferedPosition);
dest.writeLong(mActions);
dest.writeTypedList(mCustomActions);
dest.writeLong(mActiveItemId);
@@ -310,12 +310,12 @@
}
/**
- * Get the current buffer position in ms. This is the farthest playback
+ * Get the current buffered position in ms. This is the farthest playback
* point that can be reached from the current position using only buffered
* content.
*/
- public long getBufferPosition() {
- return mBufferPosition;
+ public long getBufferedPosition() {
+ return mBufferedPosition;
}
/**
@@ -711,7 +711,7 @@
private int mState;
private long mPosition;
- private long mBufferPosition;
+ private long mBufferedPosition;
private float mSpeed;
private long mActions;
private CharSequence mErrorMessage;
@@ -736,7 +736,7 @@
}
mState = from.mState;
mPosition = from.mPosition;
- mBufferPosition = from.mBufferPosition;
+ mBufferedPosition = from.mBufferedPosition;
mSpeed = from.mSpeed;
mActions = from.mActions;
if (from.mCustomActions != null) {
@@ -889,15 +889,16 @@
}
/**
- * Set the current buffer position in ms. This is the farthest playback
- * point that can be reached from the current position using only
- * buffered content.
+ * Set the current buffered position in ms. This is the farthest
+ * playback point that can be reached from the current position using
+ * only buffered content.
*
- * @param bufferPosition The position in ms that playback is buffered to.
+ * @param bufferedPosition The position in ms that playback is buffered
+ * to.
* @return this
*/
- public Builder setBufferPosition(long bufferPosition) {
- mBufferPosition = bufferPosition;
+ public Builder setBufferedPosition(long bufferedPosition) {
+ mBufferedPosition = bufferedPosition;
return this;
}
@@ -931,7 +932,7 @@
* @return A new state instance.
*/
public PlaybackState build() {
- return new PlaybackState(mState, mPosition, mUpdateTime, mSpeed, mBufferPosition,
+ return new PlaybackState(mState, mPosition, mUpdateTime, mSpeed, mBufferedPosition,
mActions, mCustomActions, mActiveItemId, mErrorMessage);
}
}
diff --git a/media/java/android/media/tv/TvContentRating.java b/media/java/android/media/tv/TvContentRating.java
index 405ef22..93622ab 100644
--- a/media/java/android/media/tv/TvContentRating.java
+++ b/media/java/android/media/tv/TvContentRating.java
@@ -17,7 +17,6 @@
package android.media.tv;
import android.annotation.SystemApi;
-import android.net.Uri;
import android.text.TextUtils;
import java.util.Arrays;
@@ -26,115 +25,131 @@
import java.util.Objects;
/**
- * A class representing a TV content rating.
- * When a TV input service provides the content rating information of a program into TV provider,
- * TvContentRating class will be used for generating the value of {@link
- * TvContract.Programs#COLUMN_CONTENT_RATING}. To create an object of {@link TvContentRating}, use
- * the {@link #createRating} method with valid arguments. The arguments could be a system defined
- * strings, or a TV input service defined strings.
- * TV input service defined strings are in an xml file defined in <code><{@link
- * android.R.styleable#TvInputService tv-input}></code> with the {@link
- * android.R.attr#tvContentRatingDescription tvContentRatingDescription} attribute by the TV input
- * service.
- *
+ * A class representing a TV content rating. When a TV input service inserts the content rating
+ * information on a program into the database, this class can be used to generate the formatted
+ * string for
+ * {@link TvContract.Programs#COLUMN_CONTENT_RATING TvContract.Programs.COLUMN_CONTENT_RATING}.
+ * To create a {@code TvContentRating} object, use the
+ * {@link #createRating TvContentRating.createRating} method with valid rating system string
+ * constants.
+ * <p>
+ * It is possible for a TV input to define its own content rating system by supplying a content
+ * rating system definition XML resource (see example below) and having the
+ * {@link android.R.attr#tvContentRatingDescription tvContentRatingDescription} attribute in
+ * {@link TvInputService#SERVICE_META_DATA} of the TV input point to it.
+ * </p>
* <h3> Example: Rating system definition for the TV Parental Guidelines</h3>
- * The following XML example shows how the TV Parental Guidelines in United States can be defined:
+ * The following XML example shows how the TV Parental Guidelines in the United States can be
+ * defined:
* <p><pre class="prettyprint">
* {@literal
- * <?xml version="1.0" encoding="UTF-8"?>
- * <rating-system-definitions version="1.0">
- * <rating-system-definition id="US_TV"
- * displayName="US-TV"
- * description="The TV Parental Guidelines"
- * country="US">
- * <sub-rating-definition id="US_TV_D"
- * displayName="D"
- * description="Suggestive dialogue (Usually means talks about sex)" />
- * <sub-rating-definition id="US_TV_L"
- * displayName="L"
- * description="Coarse language" />
- * <sub-rating-definition id="US_TV_S"
- * displayName="S"
- * description="Sexual content" />
- * <sub-rating-definition id="US_TV_V"
- * displayName="V"
- * description="Violence" />
- * <sub-rating-definition id="US_TV_FV"
- * displayName="FV"
- * description="Fantasy violence (Children\'s programming only)" />
+ * <rating-system-definitions xmlns:android="http://schemas.android.com/apk/res/android"
+ * android:versionCode="1">
+ * <!-- TV content rating system for US TV -->
+ * <rating-system-definition android:name="US_TV"
+ * android:title="US-TV"
+ * android:description="@string/description_ustv"
+ * android:country="US">
+ * <sub-rating-definition android:name="US_TV_D"
+ * android:title="D"
+ * android:description="@string/description_ustv_d" />
+ * <sub-rating-definition android:name="US_TV_L"
+ * android:title="L"
+ * android:description="@string/description_ustv_l" />
+ * <sub-rating-definition android:name="US_TV_S"
+ * android:title="S"
+ * android:description="@string/description_ustv_s" />
+ * <sub-rating-definition android:name="US_TV_V"
+ * android:title="V"
+ * android:description="@string/description_ustv_v" />
+ * <sub-rating-definition android:name="US_TV_FV"
+ * android:title="FV"
+ * android:description="@string/description_ustv_fv" />
*
- * <rating-definition id="US_TV_Y"
- * displayName="TV-Y"
- * description="This program is designed to be appropriate for all children"
- * ageHint="0" />
- * <rating-definition id="US_TV_Y7"
- * displayName="TV-Y7"
- * description="This program is designed for children age 7 and above"
- * ageHint="7">
- * <sub-rating id="US_TV_FV" />
+ * <rating-definition android:name="US_TV_Y"
+ * android:title="TV-Y"
+ * android:description="@string/description_ustv_y"
+ * android:ageHint="0" />
+ * <rating-definition android:name="US_TV_Y7"
+ * android:title="TV-Y7"
+ * android:description="@string/description_ustv_y7"
+ * android:ageHint="7">
+ * <sub-rating android:name="US_TV_FV" />
* </rating-definition>
- * <rating-definition id="US_TV_G"
- * displayName="TV-G"
- * description="Most parents would find this program suitable for all ages"
- * ageHint="0" />
- * <rating-definition id="US_TV_PG"
- * displayName="TV-PG"
- * description="This program contains material that parents may find unsuitable for younger children"
- * ageHint="14">
- * <sub-rating id="US_TV_D" />
- * <sub-rating id="US_TV_L" />
- * <sub-rating id="US_TV_S" />
- * <sub-rating id="US_TV_V" />
+ * <rating-definition android:name="US_TV_G"
+ * android:title="TV-G"
+ * android:description="@string/description_ustv_g"
+ * android:ageHint="0" />
+ * <rating-definition android:name="US_TV_PG"
+ * android:title="TV-PG"
+ * android:description="@string/description_ustv_pg"
+ * android:ageHint="14">
+ * <sub-rating android:name="US_TV_D" />
+ * <sub-rating android:name="US_TV_L" />
+ * <sub-rating android:name="US_TV_S" />
+ * <sub-rating android:name="US_TV_V" />
* </rating-definition>
- * <rating-definition id="US_TV_14"
- * displayName="TV-14"
- * description="This program contains some material that many parents would find unsuitable for children under 14 years of age"
- * ageHint="14">
- * <sub-rating id="US_TV_D" />
- * <sub-rating id="US_TV_L" />
- * <sub-rating id="US_TV_S" />
- * <sub-rating id="US_TV_V" />
+ * <rating-definition android:name="US_TV_14"
+ * android:title="TV-14"
+ * android:description="@string/description_ustv_14"
+ * android:ageHint="14">
+ * <sub-rating android:name="US_TV_D" />
+ * <sub-rating android:name="US_TV_L" />
+ * <sub-rating android:name="US_TV_S" />
+ * <sub-rating android:name="US_TV_V" />
* </rating-definition>
- * <rating-definition id="US_TV_MA"
- * displayName="TV-MA"
- * description="This program is specifically designed to be viewed by adults and therefore may be unsuitable for children under 17"
- * ageHint="17">
- * <sub-rating id="US_TV_L" />
- * <sub-rating id="US_TV_S" />
- * <sub-rating id="US_TV_V" />
+ * <rating-definition android:name="US_TV_MA"
+ * android:title="TV-MA"
+ * android:description="@string/description_ustv_ma"
+ * android:ageHint="17">
+ * <sub-rating android:name="US_TV_L" />
+ * <sub-rating android:name="US_TV_S" />
+ * <sub-rating android:name="US_TV_V" />
* </rating-definition>
- * <order>
- * <rating id="US_TV_Y" />
- * <rating id="US_TV_Y7" />
- * </order>
- * <order>
- * <rating id="US_TV_G" />
- * <rating id="US_TV_PG" />
- * <rating id="US_TV_14" />
- * <rating id="US_TV_MA" />
- * </order>
+ * <rating-order>
+ * <rating android:name="US_TV_Y" />
+ * <rating android:name="US_TV_Y7" />
+ * </rating-order>
+ * <rating-order>
+ * <rating android:name="US_TV_G" />
+ * <rating android:name="US_TV_PG" />
+ * <rating android:name="US_TV_14" />
+ * <rating android:name="US_TV_MA" />
+ * </rating-order>
* </rating-system-definition>
* </rating-system-definitions>}</pre></p>
*
* <h3>System defined rating strings</h3>
- *
- * <u>System defined string for {@code domain}</u>
- * <table border="0" cellspacing="0" cellpadding="0">
+ * The following strings are defined by the system to provide a standard way to create
+ * {@code TvContentRating} objects.
+ * <p>For example, to create an object that represents TV-PG rating with suggestive dialogue and
+ * coarse language from the TV Parental Guidelines in the United States, one can use the following
+ * code snippet:
+ * </p>
+ * <pre>
+ * String rating = TvContentRating.createRating(
+ * "com.android.tv",
+ * "US_TV",
+ * "US_TV_PG",
+ * "US_TV_D", "US_TV_L");
+ * </pre>
+ * <h4>System defined string for domains</h4>
+ * <table>
* <tr>
- * <td width=10%>String value</td>
- * <td>Comments</td>
+ * <th>Constant Value</th>
+ * <th>Comment</th>
* </tr>
* <tr>
- * <td>android.media.tv</td>
+ * <td>com.android.tv</td>
* <td>Used for creating system defined content ratings</td>
* </tr>
* </table>
*
- * <u>System defined string for {@code ratingSystem}</u>
- * <table border="1" cellspacing="0" cellpadding="0">
+ * <h4>System defined strings for rating systems</h4>
+ * <table>
* <tr>
- * <td width="10%">String value</td>
- * <td>Comments</td>
+ * <th>Constant Value</th>
+ * <th>Comment</th>
* </tr>
* <tr>
* <td>AM_TV_RS</td>
@@ -315,7 +330,7 @@
* </tr>
* <tr>
* <td>US_TV</td>
- * <td>TV content rating system for United States</td>
+ * <td>TV content rating system for the United States</td>
* </tr>
* <tr>
* <td>VE_TV</td>
@@ -327,12 +342,12 @@
* </tr>
* </table>
*
- * <u>System defined string for {@code rating}</u>
- * <table border="1" cellspacing="0" cellpadding="0">
+ * <h4>System defined strings for ratings</h4>
+ * <table>
* <tr>
- * <td width="10%">RatingSystem code</td>
- * <td width="10%">Rating string value</td>
- * <td>Comments</td>
+ * <th>Rating System</th>
+ * <th>Constant Value</th>
+ * <th>Comment</th>
* </tr>
* <tr>
* <td valign="top" rowspan="6">AM_TV_RS</td>
@@ -1400,12 +1415,12 @@
* </tr>
* </table>
*
- * <u>System defined string for {@code subRating}</u>
- * <table border="1" cellspacing="0" cellpadding="0">
+ * <h4>System defined strings for sub-ratings</h4>
+ * <table>
* <tr>
- * <td width="10%">RatingSystem code</td>
- * <td width="10%">Rating string value</td>
- * <td>Comments</td>
+ * <th>Rating System</th>
+ * <th>Constant Value</th>
+ * <th>Comment</th>
* </tr>
* <tr>
* <td valign="top" rowspan="6">NL_TV</td>
@@ -1506,10 +1521,6 @@
* </table>
*/
public final class TvContentRating {
- /** @hide */
- public static final Uri SYSTEM_CONTENT_RATING_SYSTEM_XML = Uri.parse(
- "android.resource://system/" + com.android.internal.R.xml.tv_content_rating_systems);
-
// TODO: Consider to use other DELIMITER. In some countries such as India may use this delimiter
// in the main ratings.
private static final String DELIMITER = "/";
@@ -1521,13 +1532,15 @@
private final int mHashCode;
/**
- * Creates a TvContentRating object.
+ * Creates a {@code TvContentRating} object with predefined content rating strings.
*
- * @param domain The domain name.
- * @param ratingSystem The rating system id.
- * @param rating The content rating string.
- * @param subRatings The string array of sub-ratings.
- * @return A TvContentRating object, or null if creation failed.
+ * @param domain The domain string. For example, "com.android.tv".
+ * @param ratingSystem The rating system string. For example, "US_TV".
+ * @param rating The content rating string. For example, "US_TV_PG".
+ * @param subRatings The sub-rating strings. For example, "US_TV_D" and "US_TV_L".
+ * @return A {@code TvContentRating} object.
+ * @throws IllegalArgumentException If {@code domain}, {@code ratingSystem} or {@code rating} is
+ * {@code null}.
*/
public static TvContentRating createRating(String domain, String ratingSystem,
String rating, String... subRatings) {
@@ -1544,12 +1557,12 @@
}
/**
- * Recovers a TvContentRating from a String that was previously created with
+ * Recovers a {@code TvContentRating} object from the string that was previously created from
* {@link #flattenToString}.
*
- * @param ratingString The String that was returned by flattenToString().
- * @return a new TvContentRating containing the domain, rating system, rating and
- * sub-ratings information was encoded in {@code ratingString}.
+ * @param ratingString The string returned by {@link #flattenToString}.
+ * @return the {@code TvContentRating} object containing the domain, rating system, rating and
+ * sub-ratings information encoded in {@code ratingString}.
* @see #flattenToString
*/
public static TvContentRating unflattenFromString(String ratingString) {
@@ -1571,10 +1584,10 @@
/**
* Constructs a TvContentRating object from a given rating and sub-rating constants.
*
- * @param domain The domain name.
- * @param ratingSystem The rating system id.
- * @param rating The content rating string.
- * @param subRatings The String array of sub-rating constants defined in this class.
+ * @param domain The string for domain of the content rating system such as "com.android.tv".
+ * @param ratingSystem The rating system string such as "US_TV".
+ * @param rating The content rating string such as "US_TV_PG".
+ * @param subRatings The sub-rating strings such as "US_TV_D" and "US_TV_L".
*/
private TvContentRating(
String domain, String ratingSystem, String rating, String[] subRatings) {
@@ -1591,28 +1604,29 @@
}
/**
- * Returns the domain.
+ * Returns the domain of this {@code TvContentRating} object.
*/
public String getDomain() {
return mDomain;
}
/**
- * Returns the rating system id.
+ * Returns the rating system of this {@code TvContentRating} object.
*/
public String getRatingSystem() {
return mRatingSystem;
}
/**
- * Returns the main rating.
+ * Returns the main rating of this {@code TvContentRating} object.
*/
public String getMainRating() {
return mRating;
}
/**
- * Returns the unmodifiable {@code List} of sub-rating strings.
+ * Returns the unmodifiable sub-rating string {@link List} of this {@code TvContentRating}
+ * object.
*/
public List<String> getSubRatings() {
if (mSubRatings == null) {
@@ -1622,12 +1636,12 @@
}
/**
- * Returns a String that unambiguously describes both the rating and sub-rating information
- * contained in the TvContentRating. You can later recover the TvContentRating from this string
- * through {@link #unflattenFromString}.
+ * Returns a string that unambiguously describes the rating information contained in a
+ * {@code TvContentRating} object. One can later recover the object from this string through
+ * {@link #unflattenFromString}.
*
- * @return a new String holding rating/sub-rating information, which can later be stored in the
- * database and settings.
+ * @return a string containing the rating information, which can later be stored in the
+ * database.
* @see #unflattenFromString
*/
public String flattenToString() {
@@ -1647,11 +1661,11 @@
}
/**
- * Returns true if this rating has the same main rating as the specified rating and when this
- * rating's sub-ratings contain the other's.
+ * Returns {@code true} if this rating has the same main rating as the specified rating and when
+ * this rating's sub-ratings contain the other's.
* <p>
- * For example, a TvContentRating object that represents TV-PG with S(Sexual content) and
- * V(Violence) contains TV-PG, TV-PG/S, TV-PG/V and itself.
+ * For example, a {@code TvContentRating} object that represents TV-PG with S(Sexual content)
+ * and V(Violence) contains TV-PG, TV-PG/S, TV-PG/V and itself.
* </p>
*
* @param rating The {@link TvContentRating} to check.
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 3f5697f..106e1dc 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -46,7 +46,6 @@
import java.io.IOException;
import java.io.InputStream;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -616,11 +615,15 @@
public static Set<String> getHiddenTvInputIds(Context context, int userId) {
String hiddenIdsString = Settings.Secure.getStringForUser(
context.getContentResolver(), Settings.Secure.TV_INPUT_HIDDEN_INPUTS, userId);
+ Set<String> set = new HashSet<String>();
if (TextUtils.isEmpty(hiddenIdsString)) {
- return new HashSet<String>();
+ return set;
}
String[] ids = hiddenIdsString.split(TV_INPUT_SEPARATOR);
- return new HashSet<>(Arrays.asList(ids));
+ for (String id : ids) {
+ set.add(Uri.decode(id));
+ }
+ return set;
}
/**
@@ -641,7 +644,7 @@
String[] pairs = labelsString.split(TV_INPUT_SEPARATOR);
for (String pairString : pairs) {
String[] pair = pairString.split(CUSTOM_NAME_SEPARATOR);
- map.put(pair[0], pair[1]);
+ map.put(Uri.decode(pair[0]), Uri.decode(pair[1]));
}
return map;
}
@@ -667,7 +670,7 @@
} else {
builder.append(TV_INPUT_SEPARATOR);
}
- builder.append(inputId);
+ builder.append(Uri.encode(inputId));
}
Settings.Secure.putStringForUser(context.getContentResolver(),
Settings.Secure.TV_INPUT_HIDDEN_INPUTS, builder.toString(), userId);
@@ -695,9 +698,9 @@
} else {
builder.append(TV_INPUT_SEPARATOR);
}
- builder.append(entry.getKey());
+ builder.append(Uri.encode(entry.getKey()));
builder.append(CUSTOM_NAME_SEPARATOR);
- builder.append(entry.getValue());
+ builder.append(Uri.encode(entry.getValue()));
}
Settings.Secure.putStringForUser(context.getContentResolver(),
Settings.Secure.TV_INPUT_CUSTOM_LABELS, builder.toString(), userId);
@@ -707,14 +710,6 @@
if (TextUtils.isEmpty(value)) {
throw new IllegalArgumentException(value + " should not empty ");
}
- if (value.contains(TV_INPUT_SEPARATOR)) {
- throw new IllegalArgumentException(value + " should not include "
- + TV_INPUT_SEPARATOR);
- }
- if (value.contains(CUSTOM_NAME_SEPARATOR)) {
- throw new IllegalArgumentException(value + " should not include "
- + CUSTOM_NAME_SEPARATOR);
- }
}
}
}
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index e3292b6..4efbc30 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -300,7 +300,7 @@
if (eventType == null) {
throw new IllegalArgumentException("eventType should not be null.");
}
- mHandler.post(new Runnable() {
+ runOnMainThread(new Runnable() {
@Override
public void run() {
try {
@@ -319,7 +319,7 @@
* @param channelUri The URI of a channel.
*/
public void notifyChannelRetuned(final Uri channelUri) {
- mHandler.post(new Runnable() {
+ runOnMainThread(new Runnable() {
@Override
public void run() {
try {
@@ -351,7 +351,7 @@
trackIdSet.clear();
// TODO: Validate the track list.
- mHandler.post(new Runnable() {
+ runOnMainThread(new Runnable() {
@Override
public void run() {
try {
@@ -375,7 +375,7 @@
* @see #onSelectTrack
*/
public void notifyTrackSelected(final int type, final String trackId) {
- mHandler.post(new Runnable() {
+ runOnMainThread(new Runnable() {
@Override
public void run() {
try {
@@ -393,7 +393,7 @@
* been started.
*/
public void notifyVideoAvailable() {
- mHandler.post(new Runnable() {
+ runOnMainThread(new Runnable() {
@Override
public void run() {
try {
@@ -423,7 +423,7 @@
|| reason > TvInputManager.VIDEO_UNAVAILABLE_REASON_END) {
throw new IllegalArgumentException("Unknown reason: " + reason);
}
- mHandler.post(new Runnable() {
+ runOnMainThread(new Runnable() {
@Override
public void run() {
try {
@@ -462,7 +462,7 @@
* @see TvInputManager
*/
public void notifyContentAllowed() {
- mHandler.post(new Runnable() {
+ runOnMainThread(new Runnable() {
@Override
public void run() {
try {
@@ -502,7 +502,7 @@
* @see TvInputManager
*/
public void notifyContentBlocked(final TvContentRating rating) {
- mHandler.post(new Runnable() {
+ runOnMainThread(new Runnable() {
@Override
public void run() {
try {
@@ -531,7 +531,7 @@
if (left > right || top > bottm) {
throw new IllegalArgumentException("Invalid parameter");
}
- mHandler.post(new Runnable() {
+ runOnMainThread(new Runnable() {
@Override
public void run() {
try {
@@ -1049,6 +1049,14 @@
private void setSessionCallback(ITvInputSessionCallback callback) {
mSessionCallback = callback;
}
+
+ private final void runOnMainThread(Runnable action) {
+ if (mHandler.getLooper().isCurrentThread()) {
+ action.run();
+ } else {
+ mHandler.post(action);
+ }
+ }
}
/**
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index f348b9b..7110db9 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -38,6 +38,7 @@
import android.view.ViewGroup;
import android.view.ViewRootImpl;
+import java.lang.ref.WeakReference;
import java.util.List;
/**
@@ -69,8 +70,10 @@
private static final int CAPTION_ENABLED = 1;
private static final int CAPTION_DISABLED = 2;
+ private static final WeakReference<TvView> NULL_TV_VIEW = new WeakReference(null);
+
private static final Object sMainTvViewLock = new Object();
- private static TvView sMainTvView;
+ private static WeakReference<TvView> sMainTvView = NULL_TV_VIEW;
private final Handler mHandler = new Handler();
private Session mSession;
@@ -186,16 +189,16 @@
* (including the tuner, composite, S-Video, etc.), the internal device (= TV itself) becomes
* the active source.
* </p><p>
- * First tuned {@link TvView} becomes main automatically, and keeps to be main until {@link
- * #setMain} is called for other {@link TvView}. Note that main {@link TvView} won't be reset
- * even when current main {@link TvView} is removed from view hierarchy.
+ * First tuned {@link TvView} becomes main automatically, and keeps to be main until either
+ * {@link #reset} is called for the main {@link TvView} or {@link #setMain} is called for other
+ * {@link TvView}.
* </p>
* @hide
*/
@SystemApi
public void setMain() {
synchronized (sMainTvViewLock) {
- sMainTvView = this;
+ sMainTvView = new WeakReference(this);
if (hasWindowFocus() && mSession != null) {
mSession.setMain();
}
@@ -288,8 +291,8 @@
throw new IllegalArgumentException("inputId cannot be null or an empty string");
}
synchronized (sMainTvViewLock) {
- if (sMainTvView == null) {
- sMainTvView = this;
+ if (sMainTvView.get() == null) {
+ sMainTvView = new WeakReference(this);
}
}
if (mSessionCallback != null && mSessionCallback.mInputId.equals(inputId)) {
@@ -320,6 +323,11 @@
*/
public void reset() {
if (DEBUG) Log.d(TAG, "reset()");
+ synchronized (sMainTvViewLock) {
+ if (this == sMainTvView.get()) {
+ sMainTvView = NULL_TV_VIEW;
+ }
+ }
if (mSession != null) {
release();
resetSurfaceView();
@@ -530,7 +538,7 @@
// Other app may have shown its own main TvView.
// Set main again to regain main session.
synchronized (sMainTvViewLock) {
- if (hasFocus && this == sMainTvView && mSession != null) {
+ if (hasFocus && this == sMainTvView.get() && mSession != null) {
mSession.setMain();
}
}
@@ -828,7 +836,7 @@
mSession = session;
if (session != null) {
synchronized (sMainTvViewLock) {
- if (hasWindowFocus() && TvView.this == sMainTvView) {
+ if (hasWindowFocus() && TvView.this == sMainTvView.get()) {
mSession.setMain();
}
}
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 4c225c1..fae30e5 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -30,7 +30,6 @@
import android.content.pm.PackageParser.PackageParserException;
import android.content.res.ObbInfo;
import android.content.res.ObbScanner;
-import android.os.Build;
import android.os.Environment;
import android.os.Environment.UserEnvironment;
import android.os.FileUtils;
@@ -67,7 +66,6 @@
*/
public class DefaultContainerService extends IntentService {
private static final String TAG = "DefContainer";
- private static final boolean localLOGV = false;
private static final String LIB_DIR_NAME = "lib";
@@ -112,7 +110,7 @@
return copyPackageToContainerInner(pkg, handle, containerId, key, isExternal,
isForwardLocked, abiOverride);
} catch (PackageParserException | IOException e) {
- Slog.w(TAG, "Failed to parse package at " + packagePath);
+ Slog.w(TAG, "Failed to copy package at " + packagePath, e);
return null;
} finally {
IoUtils.closeQuietly(handle);
@@ -188,7 +186,7 @@
ret.installLocation = pkg.installLocation;
ret.verifiers = pkg.verifiers;
ret.recommendedInstallLocation = PackageHelper.resolveInstallLocation(context,
- pkg.installLocation, sizeBytes, flags);
+ pkg.packageName, pkg.installLocation, sizeBytes, flags);
ret.multiArch = pkg.multiArch;
return ret;
@@ -313,161 +311,73 @@
private String copyPackageToContainerInner(PackageLite pkg, NativeLibraryHelper.Handle handle,
String newCid, String key, boolean isExternal, boolean isForwardLocked,
- String abiOverride) {
- // TODO: extend to support copying all split APKs
- if (!ArrayUtils.isEmpty(pkg.splitNames)) {
- throw new UnsupportedOperationException("Copying split APKs not yet supported");
- }
+ String abiOverride) throws IOException {
- final String resFileName = "pkg.apk";
- final String publicResFileName = "res.zip";
-
- if (pkg.multiArch) {
- // TODO: Support multiArch installs on ASEC.
- throw new IllegalArgumentException("multiArch not supported on ASEC installs.");
- }
-
- // The .apk file
- final String codePath = pkg.baseCodePath;
- final File codeFile = new File(codePath);
- final String[] abis;
- try {
- abis = calculateAbiList(handle, abiOverride, pkg.multiArch);
- } catch (IOException ioe) {
- Slog.w(TAG, "Problem determining app ABIS: " + ioe);
- return null;
- }
-
- // Calculate size of container needed to hold base APK. Round up to
- // nearest MB, and tack on an extra MB for filesystem overhead.
- final int sizeMb;
- try {
- final long sizeBytes = calculateInstalledSizeInner(pkg, handle, isForwardLocked, abis);
- sizeMb = ((int) ((sizeBytes + MB_IN_BYTES) / MB_IN_BYTES)) + 1;
- } catch (IOException e) {
- Slog.w(TAG, "Problem when trying to copy " + codeFile.getPath());
- return null;
- }
+ // Calculate container size, rounding up to nearest MB and adding an
+ // extra MB for filesystem overhead
+ final long sizeBytes = calculateInstalledSizeInner(pkg, handle, isForwardLocked,
+ abiOverride);
+ final int sizeMb = ((int) ((sizeBytes + MB_IN_BYTES) / MB_IN_BYTES)) + 1;
// Create new container
- final String newCachePath = PackageHelper.createSdDir(sizeMb, newCid, key, Process.myUid(),
+ final String newMountPath = PackageHelper.createSdDir(sizeMb, newCid, key, Process.myUid(),
isExternal);
- if (newCachePath == null) {
- Slog.e(TAG, "Failed to create container " + newCid);
- return null;
+ if (newMountPath == null) {
+ throw new IOException("Failed to create container " + newCid);
}
-
- if (localLOGV) {
- Slog.i(TAG, "Created container for " + newCid + " at path : " + newCachePath);
- }
-
- final File resFile = new File(newCachePath, resFileName);
- if (FileUtils.copyFile(new File(codePath), resFile)) {
- if (localLOGV) {
- Slog.i(TAG, "Copied " + codePath + " to " + resFile);
- }
- } else {
- Slog.e(TAG, "Failed to copy " + codePath + " to " + resFile);
- // Clean up container
- PackageHelper.destroySdDir(newCid);
- return null;
- }
+ final File targetDir = new File(newMountPath);
try {
- Os.chmod(resFile.getAbsolutePath(), 0640);
+ // Copy all APKs
+ copyFile(pkg.baseCodePath, targetDir, "base.apk", isForwardLocked);
+ if (!ArrayUtils.isEmpty(pkg.splitNames)) {
+ for (int i = 0; i < pkg.splitNames.length; i++) {
+ copyFile(pkg.splitCodePaths[i], targetDir,
+ "split_" + pkg.splitNames[i] + ".apk", isForwardLocked);
+ }
+ }
+
+ // Extract native code
+ final File libraryRoot = new File(targetDir, LIB_DIR_NAME);
+ final int res = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, libraryRoot,
+ abiOverride, pkg.multiArch);
+ if (res != PackageManager.INSTALL_SUCCEEDED) {
+ throw new IOException("Failed to extract native code, res=" + res);
+ }
+
+ if (!PackageHelper.finalizeSdDir(newCid)) {
+ throw new IOException("Failed to finalize " + newCid);
+ }
+
+ if (PackageHelper.isContainerMounted(newCid)) {
+ PackageHelper.unMountSdDir(newCid);
+ }
+
} catch (ErrnoException e) {
- Slog.e(TAG, "Could not chown APK: " + e.getMessage());
PackageHelper.destroySdDir(newCid);
- return null;
- }
-
- if (isForwardLocked) {
- File publicZipFile = new File(newCachePath, publicResFileName);
- try {
- PackageHelper.extractPublicFiles(resFile.getAbsolutePath(), publicZipFile);
- if (localLOGV) {
- Slog.i(TAG, "Copied resources to " + publicZipFile);
- }
- } catch (IOException e) {
- Slog.e(TAG, "Could not chown public APK " + publicZipFile.getAbsolutePath() + ": "
- + e.getMessage());
- PackageHelper.destroySdDir(newCid);
- return null;
- }
-
- try {
- Os.chmod(publicZipFile.getAbsolutePath(), 0644);
- } catch (ErrnoException e) {
- Slog.e(TAG, "Could not chown public resource file: " + e.getMessage());
- PackageHelper.destroySdDir(newCid);
- return null;
- }
- }
-
- final File sharedLibraryDir = new File(newCachePath, LIB_DIR_NAME);
- if (sharedLibraryDir.mkdir()) {
- int ret = PackageManager.INSTALL_SUCCEEDED;
- if (abis != null) {
- // TODO(multiArch): Support multi-arch installs on asecs. Note that we are NOT
- // using an ISA specific subdir here for now.
- final String abi = abis[0];
- ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
- sharedLibraryDir, abi);
-
- if (ret != PackageManager.INSTALL_SUCCEEDED) {
- Slog.e(TAG, "Could not copy native libraries to " + sharedLibraryDir.getPath());
- PackageHelper.destroySdDir(newCid);
- return null;
- }
- }
- } else {
- Slog.e(TAG, "Could not create native lib directory: " + sharedLibraryDir.getPath());
+ throw e.rethrowAsIOException();
+ } catch (IOException e) {
PackageHelper.destroySdDir(newCid);
- return null;
+ throw e;
}
- if (!PackageHelper.finalizeSdDir(newCid)) {
- Slog.e(TAG, "Failed to finalize " + newCid + " at path " + newCachePath);
- // Clean up container
- PackageHelper.destroySdDir(newCid);
- return null;
- }
-
- if (localLOGV) {
- Slog.i(TAG, "Finalized container " + newCid);
- }
-
- if (PackageHelper.isContainerMounted(newCid)) {
- if (localLOGV) {
- Slog.i(TAG, "Unmounting " + newCid + " at path " + newCachePath);
- }
-
- // Force a gc to avoid being killed.
- Runtime.getRuntime().gc();
- PackageHelper.unMountSdDir(newCid);
- } else {
- if (localLOGV) {
- Slog.i(TAG, "Container " + newCid + " not mounted");
- }
- }
-
- return newCachePath;
+ return newMountPath;
}
private int copyPackageInner(PackageLite pkg, IParcelFileDescriptorFactory target)
throws IOException, RemoteException {
- copyFile(pkg.baseCodePath, "base.apk", target);
+ copyFile(pkg.baseCodePath, target, "base.apk");
if (!ArrayUtils.isEmpty(pkg.splitNames)) {
for (int i = 0; i < pkg.splitNames.length; i++) {
- copyFile(pkg.splitCodePaths[i], "split_" + pkg.splitNames[i] + ".apk", target);
+ copyFile(pkg.splitCodePaths[i], target, "split_" + pkg.splitNames[i] + ".apk");
}
}
return PackageManager.INSTALL_SUCCEEDED;
}
- private void copyFile(String sourcePath, String targetName,
- IParcelFileDescriptorFactory target) throws IOException, RemoteException {
+ private void copyFile(String sourcePath, IParcelFileDescriptorFactory target, String targetName)
+ throws IOException, RemoteException {
Slog.d(TAG, "Copying " + sourcePath + " to " + targetName);
InputStream in = null;
OutputStream out = null;
@@ -482,76 +392,58 @@
}
}
+ private void copyFile(String sourcePath, File targetDir, String targetName,
+ boolean isForwardLocked) throws IOException, ErrnoException {
+ final File sourceFile = new File(sourcePath);
+ final File targetFile = new File(targetDir, targetName);
+
+ Slog.d(TAG, "Copying " + sourceFile + " to " + targetFile);
+ if (!FileUtils.copyFile(sourceFile, targetFile)) {
+ throw new IOException("Failed to copy " + sourceFile + " to " + targetFile);
+ }
+
+ if (isForwardLocked) {
+ final String publicTargetName = PackageHelper.replaceEnd(targetName,
+ ".apk", ".zip");
+ final File publicTargetFile = new File(targetDir, publicTargetName);
+
+ PackageHelper.extractPublicFiles(sourceFile, publicTargetFile);
+
+ Os.chmod(targetFile.getAbsolutePath(), 0640);
+ Os.chmod(publicTargetFile.getAbsolutePath(), 0644);
+ } else {
+ Os.chmod(targetFile.getAbsolutePath(), 0644);
+ }
+ }
+
private long calculateInstalledSizeInner(PackageLite pkg, boolean isForwardLocked,
String abiOverride) throws IOException {
NativeLibraryHelper.Handle handle = null;
try {
handle = NativeLibraryHelper.Handle.create(pkg);
- return calculateInstalledSizeInner(pkg, handle, isForwardLocked,
- calculateAbiList(handle, abiOverride, pkg.multiArch));
+ return calculateInstalledSizeInner(pkg, handle, isForwardLocked, abiOverride);
} finally {
IoUtils.closeQuietly(handle);
}
}
private long calculateInstalledSizeInner(PackageLite pkg, NativeLibraryHelper.Handle handle,
- boolean isForwardLocked, String[] abis) throws IOException {
+ boolean isForwardLocked, String abiOverride) throws IOException {
long sizeBytes = 0;
// Include raw APKs, and possibly unpacked resources
for (String codePath : pkg.getAllCodePaths()) {
- sizeBytes += new File(codePath).length();
+ final File codeFile = new File(codePath);
+ sizeBytes += codeFile.length();
if (isForwardLocked) {
- sizeBytes += PackageHelper.extractPublicFiles(codePath, null);
+ sizeBytes += PackageHelper.extractPublicFiles(codeFile, null);
}
}
// Include all relevant native code
- if (!ArrayUtils.isEmpty(abis)) {
- sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(handle, abis);
- }
+ sizeBytes += NativeLibraryHelper.sumNativeBinaries(handle, abiOverride, pkg.multiArch);
return sizeBytes;
}
-
- private String[] calculateAbiList(NativeLibraryHelper.Handle handle, String abiOverride,
- boolean isMultiArch) throws IOException {
- if (isMultiArch) {
- final int abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
- final int abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
-
- if (abi32 >= 0 && abi64 >= 0) {
- return new String[] { Build.SUPPORTED_64_BIT_ABIS[abi64], Build.SUPPORTED_32_BIT_ABIS[abi32] };
- } else if (abi64 >= 0) {
- return new String[] { Build.SUPPORTED_64_BIT_ABIS[abi64] };
- } else if (abi32 >= 0) {
- return new String[] { Build.SUPPORTED_32_BIT_ABIS[abi32] };
- }
-
- if (abi64 != PackageManager.NO_NATIVE_LIBRARIES || abi32 != PackageManager.NO_NATIVE_LIBRARIES) {
- throw new IOException("Error determining ABI list: errorCode=[" + abi32 + "," + abi64 + "]");
- }
-
- } else {
- String[] abiList = Build.SUPPORTED_ABIS;
- if (abiOverride != null) {
- abiList = new String[] { abiOverride };
- } else if (Build.SUPPORTED_64_BIT_ABIS.length > 0 &&
- NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
- abiList = Build.SUPPORTED_32_BIT_ABIS;
- }
-
- final int abi = NativeLibraryHelper.findSupportedAbi(handle,abiList);
- if (abi >= 0) {
- return new String[]{Build.SUPPORTED_ABIS[abi]};
- }
-
- if (abi != PackageManager.NO_NATIVE_LIBRARIES) {
- throw new IOException("Error determining ABI list: errorCode=" + abi);
- }
- }
-
- return null;
- }
}
diff --git a/packages/Keyguard/res/layout/keyguard_status_view.xml b/packages/Keyguard/res/layout/keyguard_status_view.xml
index 006b1ee..1858261 100644
--- a/packages/Keyguard/res/layout/keyguard_status_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_status_view.xml
@@ -27,14 +27,13 @@
android:layout_height="wrap_content"
androidprv:layout_maxWidth="@dimen/keyguard_security_width"
androidprv:layout_maxHeight="@dimen/keyguard_security_height"
- android:gravity="center_horizontal|top"
- android:contentDescription="@string/keyguard_accessibility_status">
+ android:gravity="center_horizontal|top">
<LinearLayout
+ android:id="@+id/keyguard_clock_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top"
- android:orientation="vertical"
- android:focusable="true">
+ android:orientation="vertical" >
<TextClock
android:id="@+id/clock_view"
android:layout_width="wrap_content"
diff --git a/packages/Keyguard/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml
index 55d8d81..a136acf 100644
--- a/packages/Keyguard/res/values/strings.xml
+++ b/packages/Keyguard/res/values/strings.xml
@@ -115,8 +115,6 @@
<string name="keyguard_accessibility_widget"><xliff:g id="widget_index">%1$s</xliff:g> widget.</string>
<!-- Accessibility description of the lock screen user selector widget. [CHAR_LIMIT=none] -->
<string name="keyguard_accessibility_user_selector">User selector</string>
- <!-- Accessibility description of the lock screen status widget. [CHAR_LIMIT=none] -->
- <string name="keyguard_accessibility_status">Status</string>
<!-- Accessibility description of the camera widget. [CHAR_LIMIT=none] -->
<string name="keyguard_accessibility_camera">Camera</string>
<!-- Accessibility description of the lock media control widget. [CHAR_LIMIT=none] -->
@@ -176,6 +174,9 @@
<!-- Accessibility description announced when user drags widget away from delete drop target [CHAR LIMIT=NONE] -->
<string name="keyguard_accessibility_delete_widget_end"><xliff:g id="widget_index">%1$s</xliff:g> will not be deleted.</string>
+ <!-- Accessibility description for the text view that indicates when the next alarm is set (not shown on screen). [CHAR_LIMIT=none] -->
+ <string name="keyguard_accessibility_next_alarm">Next alarm set for <xliff:g id="alarm" example="Fri 8:30 AM">%1$s</xliff:g></string>
+
<!-- Password keyboard strings. Used by LockScreen and Settings --><skip />
<!-- Label for "switch to symbols" key. Must be short to fit on key! -->
<string name="password_keyboard_label_symbol_key">\?123</string>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
index 51a276e..a0fab42 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
@@ -143,7 +143,10 @@
void refreshAlarmStatus(AlarmManager.AlarmClockInfo nextAlarm) {
if (nextAlarm != null) {
- mAlarmStatusView.setText(formatNextAlarm(mContext, nextAlarm));
+ String alarm = formatNextAlarm(mContext, nextAlarm);
+ mAlarmStatusView.setText(alarm);
+ mAlarmStatusView.setContentDescription(
+ getResources().getString(R.string.keyguard_accessibility_next_alarm, alarm));
mAlarmStatusView.setVisibility(View.VISIBLE);
} else {
mAlarmStatusView.setVisibility(View.GONE);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 0d79ee2..dc12cc7 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -218,7 +218,7 @@
handleFingerprintProcessed(msg.arg1);
break;
case MSG_FACE_UNLOCK_STATE_CHANGED:
- handleFaceUnlockStateChanged(msg.arg1 != 0);
+ handleFaceUnlockStateChanged(msg.arg1 != 0, msg.arg2);
break;
}
}
@@ -227,6 +227,7 @@
private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray();
private SparseBooleanArray mUserFingerprintRecognized = new SparseBooleanArray();
+ private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray();
@Override
public void onTrustChanged(boolean enabled, int userId, boolean initiatedByUser) {
@@ -297,15 +298,20 @@
}
}
- private void handleFaceUnlockStateChanged(boolean running) {
+ private void handleFaceUnlockStateChanged(boolean running, int userId) {
+ mUserFaceUnlockRunning.put(userId, running);
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
- cb.onFaceUnlockStateChanged(running);
+ cb.onFaceUnlockStateChanged(running, userId);
}
}
}
+ public boolean isFaceUnlockRunning(int userId) {
+ return mUserFaceUnlockRunning.get(userId);
+ }
+
private boolean isTrustDisabled(int userId) {
final DevicePolicyManager dpm =
(DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
@@ -398,9 +404,11 @@
} else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
dispatchBootCompleted();
} else if (ACTION_FACE_UNLOCK_STARTED.equals(action)) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 1, 0));
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 1,
+ getSendingUserId()));
} else if (ACTION_FACE_UNLOCK_STOPPED.equals(action)) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 0, 0));
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 0,
+ getSendingUserId()));
}
}
};
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 0acb9d0..33cab8f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -197,5 +197,5 @@
/**
* Called when the state of face unlock changed.
*/
- public void onFaceUnlockStateChanged(boolean running) { }
+ public void onFaceUnlockStateChanged(boolean running, int userId) { }
}
diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index 055587a..540a2f3 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -45,8 +45,7 @@
android:allowClearUserData="true"
android:label="@string/app_label"
android:allowBackup= "false"
- android:supportsRtl="true"
- android:icon="@drawable/ic_print">
+ android:supportsRtl="true">
<service
android:name=".model.PrintSpoolerService"
diff --git a/packages/PrintSpooler/res/layout/print_activity_controls.xml b/packages/PrintSpooler/res/layout/print_activity_controls.xml
index 31bda7e..0629481 100644
--- a/packages/PrintSpooler/res/layout/print_activity_controls.xml
+++ b/packages/PrintSpooler/res/layout/print_activity_controls.xml
@@ -24,241 +24,215 @@
android:elevation="@dimen/preview_controls_elevation"
android:background="?android:attr/colorPrimary">
- <LinearLayout
- android:id="@+id/draggable_content"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
+ <LinearLayout
+ android:id="@+id/draggable_content"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
- <com.android.printspooler.widget.PrintOptionsLayout
- android:id="@+id/options_container"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- printspooler:columnCount="@integer/print_option_column_count">
+ <com.android.printspooler.widget.PrintOptionsLayout
+ android:id="@+id/options_container"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ printspooler:columnCount="@integer/print_option_column_count">
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dip"
- android:layout_marginEnd="16dip"
- android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dip"
+ android:layout_marginEnd="16dip"
+ android:orientation="vertical">
- <!-- Copies -->
+ <!-- Copies -->
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dip"
- android:layout_marginStart="12dip"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:labelFor="@+id/copies_edittext"
- android:text="@string/label_copies">
- </TextView>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:layout_marginStart="12dip"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:labelFor="@+id/copies_edittext"
+ android:text="@string/label_copies">
+ </TextView>
- <view
- class="com.android.printspooler.widget.FirstFocusableEditText"
- android:id="@+id/copies_edittext"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- style="?android:attr/editTextStyle"
- android:singleLine="true"
- android:ellipsize="end"
- android:inputType="numberDecimal">
- </view>
+ <view
+ class="com.android.printspooler.widget.FirstFocusableEditText"
+ android:id="@+id/copies_edittext"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ style="?android:attr/editTextStyle"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:inputType="numberDecimal">
+ </view>
- </LinearLayout>
+ </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dip"
- android:layout_marginEnd="16dip"
- android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dip"
+ android:layout_marginEnd="16dip"
+ android:orientation="vertical">
- <!-- Paper size -->
+ <!-- Paper size -->
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dip"
- android:layout_marginStart="12dip"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:labelFor="@+id/paper_size_spinner"
- android:text="@string/label_paper_size">
- </TextView>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:layout_marginStart="12dip"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:labelFor="@+id/paper_size_spinner"
+ android:text="@string/label_paper_size">
+ </TextView>
- <Spinner
- android:id="@+id/paper_size_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- </Spinner>
+ <Spinner
+ android:id="@+id/paper_size_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ </Spinner>
- </LinearLayout>
+ </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dip"
- android:layout_marginEnd="16dip"
- android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dip"
+ android:layout_marginEnd="16dip"
+ android:orientation="vertical">
- <!-- Color -->
+ <!-- Color -->
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dip"
- android:layout_marginStart="12dip"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:labelFor="@+id/color_spinner"
- android:text="@string/label_color">
- </TextView>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:layout_marginStart="12dip"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:labelFor="@+id/color_spinner"
+ android:text="@string/label_color">
+ </TextView>
- <Spinner
- android:id="@+id/color_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- </Spinner>
+ <Spinner
+ android:id="@+id/color_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ </Spinner>
- </LinearLayout>
+ </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dip"
- android:layout_marginEnd="16dip"
- android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dip"
+ android:layout_marginEnd="16dip"
+ android:orientation="vertical">
- <!-- Orientation -->
+ <!-- Orientation -->
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dip"
- android:layout_marginStart="12dip"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:labelFor="@+id/orientation_spinner"
- android:text="@string/label_orientation">
- </TextView>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:layout_marginStart="12dip"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:labelFor="@+id/orientation_spinner"
+ android:text="@string/label_orientation">
+ </TextView>
- <Spinner
- android:id="@+id/orientation_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- </Spinner>
+ <Spinner
+ android:id="@+id/orientation_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ </Spinner>
- </LinearLayout>
+ </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dip"
- android:layout_marginEnd="16dip"
- android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dip"
+ android:layout_marginEnd="16dip"
+ android:orientation="vertical">
- <!-- Range options -->
+ <!-- Range options -->
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dip"
- android:layout_marginStart="12dip"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:labelFor="@+id/range_options_spinner"
- android:text="@string/label_pages">
- </TextView>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:layout_marginStart="12dip"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:labelFor="@+id/range_options_spinner"
+ android:text="@string/label_pages">
+ </TextView>
- <Spinner
- android:id="@+id/range_options_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- </Spinner>
+ <Spinner
+ android:id="@+id/range_options_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ </Spinner>
- </LinearLayout>
+ </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dip"
- android:layout_marginEnd="16dip"
- android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dip"
+ android:layout_marginEnd="16dip"
+ android:orientation="vertical">
- <!-- Pages -->
+ <!-- Pages -->
- <TextView
- android:id="@+id/page_range_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dip"
- android:layout_marginStart="12dip"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:text="@string/pages_range_example"
- android:labelFor="@+id/page_range_edittext"
- android:textAllCaps="false"
- android:visibility="visible">
- </TextView>
+ <TextView
+ android:id="@+id/page_range_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:layout_marginStart="12dip"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:text="@string/pages_range_example"
+ android:labelFor="@+id/page_range_edittext"
+ android:textAllCaps="false"
+ android:visibility="visible">
+ </TextView>
- <view
- class="com.android.printspooler.widget.FirstFocusableEditText"
- android:id="@+id/page_range_edittext"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom|fill_horizontal"
- android:singleLine="true"
- android:ellipsize="end"
- android:visibility="visible"
- android:inputType="textNoSuggestions">
- </view>
+ <view
+ class="com.android.printspooler.widget.FirstFocusableEditText"
+ android:id="@+id/page_range_edittext"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|fill_horizontal"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:visibility="visible"
+ android:inputType="textNoSuggestions">
+ </view>
- </LinearLayout>
+ </LinearLayout>
- </com.android.printspooler.widget.PrintOptionsLayout>
+ </com.android.printspooler.widget.PrintOptionsLayout>
- <!-- More options -->
+ <!-- More options -->
- <LinearLayout
- android:id="@+id/more_options_container"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingStart="28dip"
- android:paddingEnd="28dip"
- android:orientation="vertical"
- android:visibility="visible">
+ <Button
+ android:id="@+id/more_options_button"
+ style="?android:attr/borderlessButtonStyle"
+ android:textColor="?android:attr/textColorPrimary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dip"
+ android:layout_marginEnd="16dip"
+ android:text="@string/more_options_button"
+ android:gravity="start|center_vertical">
+ </Button>
- <ImageView
- android:layout_width="fill_parent"
- android:layout_height="1dip"
- android:layout_gravity="fill_horizontal"
- android:background="?android:attr/colorControlNormal"
- android:contentDescription="@null">
- </ImageView>
+ </LinearLayout>
- <Button
- android:id="@+id/more_options_button"
- style="?android:attr/borderlessButtonStyle"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="fill_horizontal"
- android:text="@string/more_options_button"
- android:gravity="start|center_vertical"
- android:textAllCaps="false">
- </Button>
+ <!-- Expand/collapse handle -->
- <ImageView
- android:layout_width="fill_parent"
- android:layout_height="1dip"
- android:layout_gravity="fill_horizontal"
- android:background="?android:attr/colorControlNormal"
- android:contentDescription="@null">
- </ImageView>
-
- </LinearLayout>
-
- </LinearLayout>
-
- <!-- Expand/collapse handle -->
-
- <FrameLayout
+ <FrameLayout
android:id="@+id/expand_collapse_handle"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
diff --git a/packages/PrintSpooler/res/layout/print_error_fragment.xml b/packages/PrintSpooler/res/layout/print_error_fragment.xml
index dc44339..3ea2abd 100644
--- a/packages/PrintSpooler/res/layout/print_error_fragment.xml
+++ b/packages/PrintSpooler/res/layout/print_error_fragment.xml
@@ -33,6 +33,9 @@
android:id="@+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_marginStart="16dip"
+ android:layout_marginEnd="16dip"
+ android:gravity="center_horizontal"
android:text="@string/print_error_default_message"
android:textAppearance="?android:attr/textAppearanceLargeInverse">
</TextView>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 6b29e5f..fe17516 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -180,8 +180,6 @@
private TextView mSummaryCopies;
private TextView mSummaryPaperSize;
- private View mAdvancedPrintOptionsContainer;
-
private Button mMoreOptionsButton;
private ImageView mPrintButton;
@@ -1024,7 +1022,6 @@
mPageRangeEditText.addTextChangedListener(new RangeTextWatcher());
// Advanced options button.
- mAdvancedPrintOptionsContainer = findViewById(R.id.more_options_container);
mMoreOptionsButton = (Button) findViewById(R.id.more_options_button);
mMoreOptionsButton.setOnClickListener(clickListener);
@@ -1294,10 +1291,10 @@
ComponentName serviceName = mCurrentPrinter.getId().getServiceName();
if (!TextUtils.isEmpty(PrintOptionUtils.getAdvancedOptionsActivityName(
this, serviceName))) {
- mAdvancedPrintOptionsContainer.setVisibility(View.VISIBLE);
+ mMoreOptionsButton.setVisibility(View.VISIBLE);
mMoreOptionsButton.setEnabled(true);
} else {
- mAdvancedPrintOptionsContainer.setVisibility(View.GONE);
+ mMoreOptionsButton.setVisibility(View.GONE);
mMoreOptionsButton.setEnabled(false);
}
@@ -1704,7 +1701,7 @@
if (position == 0 && getPdfPrinter() != null) {
PrinterHolder printerHolder = (PrinterHolder) getItem(position);
title = printerHolder.printer.getName();
- icon = getResources().getDrawable(R.drawable.ic_savetopdf);
+ icon = getResources().getDrawable(R.drawable.ic_menu_savetopdf);
} else if (position == 1) {
title = getString(R.string.all_printers);
}
@@ -1712,7 +1709,7 @@
if (position == 1 && getPdfPrinter() != null) {
PrinterHolder printerHolder = (PrinterHolder) getItem(position);
title = printerHolder.printer.getName();
- icon = getResources().getDrawable(R.drawable.ic_savetopdf);
+ icon = getResources().getDrawable(R.drawable.ic_menu_savetopdf);
} else if (position == getCount() - 1) {
title = getString(R.string.all_printers);
} else {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
index efb030e..e428948 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
@@ -53,7 +53,7 @@
private View mDraggableContent;
private View mPrintButton;
- private ViewGroup mMoreOptionsContainer;
+ private View mMoreOptionsButton;
private ViewGroup mOptionsContainer;
private View mEmbeddedContentContainer;
@@ -140,7 +140,7 @@
mDynamicContent = findViewById(R.id.dynamic_content);
mDraggableContent = findViewById(R.id.draggable_content);
mPrintButton = findViewById(R.id.print_button);
- mMoreOptionsContainer = (ViewGroup) findViewById(R.id.more_options_container);
+ mMoreOptionsButton = findViewById(R.id.more_options_button);
mOptionsContainer = (ViewGroup) findViewById(R.id.options_container);
mEmbeddedContentContainer = findViewById(R.id.embedded_content_container);
mEmbeddedContentScrim = findViewById(R.id.embedded_content_scrim);
@@ -301,14 +301,14 @@
|| (mDragProgress == 1.0f && progress < 1.0f)) {
mSummaryContent.setLayerType(View.LAYER_TYPE_HARDWARE, null);
mDraggableContent.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- mMoreOptionsContainer.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ mMoreOptionsButton.setLayerType(View.LAYER_TYPE_HARDWARE, null);
ensureImeClosedAndInputFocusCleared();
}
if ((mDragProgress > 0 && progress == 0)
|| (mDragProgress < 1.0f && progress == 1.0f)) {
mSummaryContent.setLayerType(View.LAYER_TYPE_NONE, null);
mDraggableContent.setLayerType(View.LAYER_TYPE_NONE, null);
- mMoreOptionsContainer.setLayerType(View.LAYER_TYPE_NONE, null);
+ mMoreOptionsButton.setLayerType(View.LAYER_TYPE_NONE, null);
}
mDragProgress = progress;
@@ -317,7 +317,7 @@
final float inverseAlpha = 1.0f - progress;
mOptionsContainer.setAlpha(inverseAlpha);
- mMoreOptionsContainer.setAlpha(inverseAlpha);
+ mMoreOptionsButton.setAlpha(inverseAlpha);
mEmbeddedContentScrim.setBackgroundColor(computeScrimColor());
@@ -336,8 +336,8 @@
if (mOptionsStateChangeListener != null) {
mOptionsStateChangeListener.onOptionsClosed();
}
- if (mMoreOptionsContainer.getVisibility() != View.GONE) {
- mMoreOptionsContainer.setVisibility(View.INVISIBLE);
+ if (mMoreOptionsButton.getVisibility() != View.GONE) {
+ mMoreOptionsButton.setVisibility(View.INVISIBLE);
}
mDraggableContent.setVisibility(View.INVISIBLE);
// If we change the scrim visibility the dimming is lagging
@@ -346,8 +346,8 @@
mEmbeddedContentScrim.setClickable(false);
mExpandCollapseIcon.setBackgroundResource(R.drawable.ic_expand_more);
} else {
- if (mMoreOptionsContainer.getVisibility() != View.GONE) {
- mMoreOptionsContainer.setVisibility(View.VISIBLE);
+ if (mMoreOptionsButton.getVisibility() != View.GONE) {
+ mMoreOptionsButton.setVisibility(View.VISIBLE);
}
mDraggableContent.setVisibility(View.VISIBLE);
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 13301fb..edefb13 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -70,7 +70,7 @@
// database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
// is properly propagated through your change. Not doing so will result in a loss of user
// settings.
- private static final int DATABASE_VERSION = 107;
+ private static final int DATABASE_VERSION = 108;
private Context mContext;
private int mUserHandle;
@@ -1714,6 +1714,25 @@
upgradeVersion = 107;
}
+ if (upgradeVersion < 108) {
+ // Reset the auto-brightness setting to default since the behavior
+ // of the feature is now quite different and is being presented to
+ // the user in a new way as "adaptive brightness".
+ db.beginTransaction();
+ SQLiteStatement stmt = null;
+ try {
+ stmt = db.compileStatement("INSERT OR REPLACE INTO system(name,value)"
+ + " VALUES(?,?);");
+ loadBooleanSetting(stmt, Settings.System.SCREEN_BRIGHTNESS_MODE,
+ R.bool.def_screen_brightness_automatic_mode);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ if (stmt != null) stmt.close();
+ }
+ upgradeVersion = 108;
+ }
+
// *** Remember to update DATABASE_VERSION above!
if (upgradeVersion != currentVersion) {
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png
index b28624f..5be74ec 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png
index 9ce434d..305c9fb 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png
index 51dce69..3e676ab 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
index 3f3e288..d3e1f7a 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png
index 9856cbf..d632600 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png
index 6910456..8984a49d 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png
index e8c6ec6..2e8f8f0 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png
index 06dcd20..ec499d4 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png
index 240f536..13e8a4f 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png
index e464347..c697da7 100644
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_land.png
index f8b59e8..94404df 100644
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png
index 1b578a6..9d0014d 100644
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_land.png
index 80ecaba..9a8b0e9 100644
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back.png
index c7bf2c7..80d60af 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back_land.png
index 278de42..2dfe964 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back.png
index 464831c..fd1cc27 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back_land.png
index c24132c..183aa0d 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back.png
index bc84f22..6f763a4 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back_land.png
index f4e219e..3dc75a3 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back.png
index ece2e37..83040fd 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back_land.png
index d524dcf..9917be4 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png
index 373e84a..c116bbe 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_land.png
index e5a102a..1446850 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png
index 6b19593..83040fd 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_land.png
index a5e0686..9917be4 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png
index f878093..447c655 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png
index 7780b16..d5ca622 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png
index 343d0dd..47985de 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
index 8e9583b..7b5fe8b 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png
index 7d38703..9fcb705 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png
index 6e186a3..23c24ba 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png
index 12b4042..41c1acb 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png
index e2a89c3..11a92f0 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png
index 311720b..7fb14a8 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back.png
index 67e4ee7..eaac305 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_ime.png
index dfef430..b5d3739 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_land.png
index de6d109..9915260 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home.png
index 7d0c3fbe..4a349e2 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home_land.png
index 3baeb52..d14da80 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu.png
index d5b48e8..4f5e723 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu_land.png
index 26d7e7b..05b9b44 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent.png
index c49198d..2035323 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent_land.png
index 2a21f29..69b541b 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back.png
index 538d7d1..3f2b8b4 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_ime.png
index eb8e80b..23e5e8f 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_land.png
index 1c2c35a..4b7f3ac 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home.png
index eec613f..41054f6 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home_land.png
index 1c0bad8..e4a7181 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu.png
index 1293fa8..be678e0 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu_land.png
index 96a9cce..24d37e0 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent.png
index 9ffc80a..9443656 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent_land.png
index aa9b57b..c3c64f4 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back.png
index b343522..0ab43ce 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_ime.png
index f2f7b50..3c58211 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_land.png
index 383398c..14ff6d3 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home.png
index 53444ab..eb74d0d 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home_land.png
index 4294937..e29c9d0 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu.png
index 7cb3ee4..cfecdcf 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu_land.png
index b017946..d98208a 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent.png
index e8dd07c..71cc61b 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent_land.png
index f396ea9..bdecf06 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back.png
index 1b817cf..01edd86 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_ime.png
index 21b7a06..52bd6e8 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_land.png
index 676fc14..b0dd0f0 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home.png
index 26f4ba9..b5c189d 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home_land.png
index ea21b60..42e9e31 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu.png
index c7d77c2..669d8ba 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu_land.png
index ae12cfd..0fbf1f6 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent.png
index 8c27d45..023b94c 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent_land.png
index c98827c..5884492 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
index ec2951d..4956aad 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png
index 5103190..e9a6223 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
index 818aa4f..e9767a1 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
index 254f757..acaf32d 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
index f0de417..20cb101 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
index 97f1526..cc620a2 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
index 773fa94..aa8a60e 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
index 8a8e941..88d6a41 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
index ad7dfc3..8acdd3c 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png
index 77969b8..01edd86 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png
index b171f92..52bd6e8 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png
index ad35c65..b0dd0f0 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png
index d60229f..b5c189d 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png
index 8fffa8e..42e9e31 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png
index 9215055..669d8ba 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_land.png
index bcf7eb1..0fbf1f6 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png
index a261f85..023b94c 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png
index 4c612f7..5884492 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/title_bar_shadow.9.png b/packages/SystemUI/res/drawable-xxhdpi/title_bar_shadow.9.png
deleted file mode 100644
index e86f891..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/title_bar_shadow.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_qs_vpn.xml b/packages/SystemUI/res/drawable/ic_qs_vpn.xml
index e9141ef..e7ef02a 100644
--- a/packages/SystemUI/res/drawable/ic_qs_vpn.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_vpn.xml
@@ -18,8 +18,7 @@
android:height="12.0dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
-
<path
android:fillColor="#4DFFFFFF"
- android:pathData="M22.000000,4.000000L22.000000,3.500000C22.000000,2.100000 20.900000,1.000000 19.500000,1.000000C18.100000,1.000000 17.000000,2.100000 17.000000,3.500000L17.000000,4.000000c-0.600000,0.000000 -1.000000,0.400000 -1.000000,1.000000l0.000000,4.000000c0.000000,0.600000 0.400000,1.000000 1.000000,1.000000l5.000000,0.000000c0.600000,0.000000 1.000000,-0.400000 1.000000,-1.000000L23.000000,5.000000C23.000000,4.400000 22.600000,4.000000 22.000000,4.000000zM21.200001,4.000000l-3.400000,0.000000L17.800001,3.500000c0.000000,-0.900000 0.800000,-1.700000 1.700000,-1.700000c0.900000,0.000000 1.700000,0.800000 1.700000,1.700000L21.200003,4.000000zM18.900000,12.000000c0.000000,0.300000 0.100000,0.700000 0.100000,1.000000c0.000000,2.100000 -0.800000,4.000000 -2.100000,5.400000c-0.300000,-0.800000 -1.000000,-1.400000 -1.900000,-1.400000l-1.000000,0.000000l0.000000,-3.000000c0.000000,-0.600000 -0.400000,-1.000000 -1.000000,-1.000000L7.000000,13.000000l0.000000,-2.000000l2.000000,0.000000c0.600000,0.000000 1.000000,-0.400000 1.000000,-1.000000L10.000000,8.000000l2.000000,0.000000c1.100000,0.000000 2.000000,-0.900000 2.000000,-2.000000L14.000000,3.500000C13.100000,3.200000 12.000000,3.000000 11.000000,3.000000C5.500000,3.000000 1.000000,7.500000 1.000000,13.000000c0.000000,5.500000 4.500000,10.000000 10.000000,10.000000c5.500000,0.000000 10.000000,-4.500000 10.000000,-10.000000c0.000000,-0.300000 0.000000,-0.700000 -0.100000,-1.000000L18.900000,12.000000zM10.000000,20.900000c-3.900000,-0.500000 -7.000000,-3.900000 -7.000000,-7.900000c0.000000,-0.600000 0.100000,-1.200000 0.200000,-1.800000L8.000000,16.000000l0.000000,1.000000c0.000000,1.100000 0.900000,2.000000 2.000000,2.000000L10.000000,20.900000z"/>
+ android:pathData="M12.700000,10.000000c-0.800000,-2.300000 -3.000000,-4.000000 -5.700000,-4.000000c-3.300000,0.000000 -6.000000,2.700000 -6.000000,6.000000s2.700000,6.000000 6.000000,6.000000c2.600000,0.000000 4.800000,-1.700000 5.700000,-4.000000L17.000000,14.000000l0.000000,4.000000l4.000000,0.000000l0.000000,-4.000000l2.000000,0.000000l0.000000,-4.000000L12.700000,10.000000zM7.000000,14.000000c-1.100000,0.000000 -2.000000,-0.900000 -2.000000,-2.000000c0.000000,-1.100000 0.900000,-2.000000 2.000000,-2.000000s2.000000,0.900000 2.000000,2.000000C9.000000,13.100000 8.100000,14.000000 7.000000,14.000000z"/>
</vector>
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 8e9b501..ef0c9bb 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -31,7 +31,7 @@
android:layout_gravity="bottom|center_horizontal"
android:textStyle="italic"
android:textColor="#ffffff"
- android:textAppearance="?android:attr/textAppearanceSmall"/>
+ android:textAppearance="?android:attr/textAppearanceSmall" />
<FrameLayout
android:id="@+id/preview_container"
@@ -66,6 +66,7 @@
android:layout_gravity="bottom|center_horizontal"
android:src="@drawable/ic_lock_24dp"
android:scaleType="center"
- android:tint="#ffffffff" />
+ android:tint="#ffffffff"
+ android:contentDescription="@string/accessibility_unlock_button_not_secured" />
</com.android.systemui.statusbar.phone.KeyguardBottomAreaView>
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index 5869bf3..5cdf819 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -41,7 +41,8 @@
android:layout_marginEnd="8dp"
android:minWidth="132dp"
android:text="@string/quick_settings_more_settings"
- android:textAppearance="@style/TextAppearance.QS.DetailButton" />
+ android:textAppearance="@style/TextAppearance.QS.DetailButton"
+ android:focusable="true" />
<TextView
android:id="@android:id/button1"
@@ -50,7 +51,8 @@
android:layout_height="wrap_content"
android:minWidth="88dp"
android:text="@string/quick_settings_done"
- android:textAppearance="@style/TextAppearance.QS.DetailButton" />
+ android:textAppearance="@style/TextAppearance.QS.DetailButton"
+ android:focusable="true"/>
</LinearLayout>
</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_detail_header.xml b/packages/SystemUI/res/layout/qs_detail_header.xml
index f3f1918..48bb213 100644
--- a/packages/SystemUI/res/layout/qs_detail_header.xml
+++ b/packages/SystemUI/res/layout/qs_detail_header.xml
@@ -19,6 +19,7 @@
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:padding="@dimen/qs_panel_padding"
+ android:visibility="invisible"
android:background="@drawable/btn_borderless_rect" >
<TextView
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index cc449c5..96f9b91 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -50,10 +50,6 @@
android:visibility="gone"
/>
- <include
- layout="@layout/keyguard_bottom_area"
- android:visibility="gone" />
-
<com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -101,7 +97,7 @@
android:layout_width="@dimen/notification_panel_width"
android:layout_height="match_parent"
android:layout_gravity="@integer/notification_panel_layout_gravity"
- android:layout_marginBottom="@dimen/close_handle_underlap"/>
+ android:layout_marginBottom="@dimen/close_handle_underlap" />
<ViewStub
android:id="@+id/keyguard_user_switcher"
@@ -117,6 +113,10 @@
</com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer>
+ <include
+ layout="@layout/keyguard_bottom_area"
+ android:visibility="gone" />
+
<include layout="@layout/status_bar_expanded_header" />
<com.android.systemui.statusbar.AlphaOptimizedView
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index aa276bc..f4f26a2 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -36,7 +36,7 @@
android:layout_width="@dimen/multi_user_switch_width_collapsed"
android:layout_height="@dimen/status_bar_header_height"
android:layout_alignParentEnd="true"
- android:background="@drawable/ripple_drawable">
+ android:background="@drawable/ripple_drawable" >
<ImageView android:id="@+id/multi_user_avatar"
android:layout_width="24dp"
android:layout_height="24dp"
@@ -51,7 +51,7 @@
android:layout_height="@dimen/status_bar_header_height"
android:background="@drawable/ripple_drawable"
android:src="@drawable/ic_settings"
- android:contentDescription="@string/accessibility_desc_settings"/>
+ android:contentDescription="@string/accessibility_desc_settings" />
<LinearLayout android:id="@+id/system_icons_super_container"
android:layout_width="wrap_content"
@@ -60,11 +60,11 @@
android:layout_alignWithParentIfMissing="true"
android:layout_marginStart="16dp"
android:background="@drawable/ripple_drawable"
- android:paddingEnd="2dp">
+ android:paddingEnd="2dp" >
<FrameLayout android:id="@+id/system_icons_container"
android:layout_width="wrap_content"
android:layout_height="@dimen/status_bar_height"
- android:layout_gravity="center_vertical"/>
+ android:layout_gravity="center_vertical" />
<TextView android:id="@+id/battery_level"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml b/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml
index f506adc..902b837 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml
@@ -21,7 +21,7 @@
android:layout_height="wrap_content"
android:visibility="gone"
>
- <ImageButton
+ <com.android.systemui.statusbar.DismissViewImageButton
android:id="@+id/dismiss_text"
android:layout_width="48dp"
android:layout_height="48dp"
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 365a7d2..09e541f 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -38,7 +38,9 @@
android:layout_height="match_parent"
android:elevation="2dp"
android:background="@drawable/brightness_mirror_background">
- <include layout="@layout/quick_settings_brightness_dialog" />
+ <include layout="@layout/quick_settings_brightness_dialog"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
</FrameLayout>
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/volume_panel.xml b/packages/SystemUI/res/layout/volume_panel.xml
index c85a750..4d8aaa7 100644
--- a/packages/SystemUI/res/layout/volume_panel.xml
+++ b/packages/SystemUI/res/layout/volume_panel.xml
@@ -25,7 +25,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/system_secondary_color"
- android:paddingTop="12dp"
+ android:paddingTop="8dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:clipChildren="false" />
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index 9d5f7bd..3949d7d 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -35,8 +35,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/qs_panel_padding"
android:layout_marginRight="@dimen/qs_panel_padding"
- android:layout_marginTop="8dp"
- android:layout_marginBottom="12dp"
+ android:layout_marginTop="4dp"
+ android:layout_marginBottom="8dp"
android:clipChildren="false" />
</FrameLayout>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 49169e6..eee7f24 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -23,8 +23,7 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Εκκαθάριση"</string>
<string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Κατάργηση από τη λίστα"</string>
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Πληροφορίες εφαρμογής"</string>
- <!-- no translation found for status_bar_no_recent_apps (7374907845131203189) -->
- <skip />
+ <string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Οι πρόσφατες οθόνες σας εμφανίζονται εδώ"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Παράβλεψη πρόσφατων εφαρμογών"</string>
<plurals name="status_bar_accessibility_recent_apps">
<item quantity="one" msgid="5854176083865845541">"1 πρόσφατη εφαρμογή"</item>
@@ -81,8 +80,7 @@
<string name="accessibility_back" msgid="567011538994429120">"Πίσω"</string>
<string name="accessibility_home" msgid="8217216074895377641">"Αρχική σελίδα"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Μενού"</string>
- <!-- no translation found for accessibility_recent (1606470783629913980) -->
- <skip />
+ <string name="accessibility_recent" msgid="1606470783629913980">"Πρόσφατες οθόνες"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Αναζήτηση"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Φωτογραφική μηχανή"</string>
<string name="accessibility_phone_button" msgid="6738112589538563574">"Τηλέφωνο"</string>
@@ -160,8 +158,7 @@
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Πλαίσιο σκίασης ειδοποιήσεων."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Γρήγορες ρυθμίσεις."</string>
<string name="accessibility_desc_settings" msgid="3417884241751434521">"Ρυθμίσεις"</string>
- <!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="8376953390514779637">"Πρόσφατες οθόνες."</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Χρήστης <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Κινητό <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
@@ -173,8 +170,7 @@
<string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Κλείσιμο παραθύρου"</string>
<string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Περισσότερος χρόνος"</string>
<string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Λιγότερος χρόνος"</string>
- <!-- no translation found for accessibility_brightness (8003681285547803095) -->
- <skip />
+ <string name="accessibility_brightness" msgid="8003681285547803095">"Φωτεινότητα οθόνης"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Τα δεδομένα 2G-3G είναι ανενεργά"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Τα δεδομένα 4G είναι ανενεργά"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Τα δεδομένα κινητής τηλεφωνίας είναι ανενεργά"</string>
@@ -246,8 +242,7 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Χρησιμοποιούνται <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Όριο <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Προειδοποίηση για <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <!-- no translation found for recents_empty_message (8682129509540827999) -->
- <skip />
+ <string name="recents_empty_message" msgid="8682129509540827999">"Οι πρόσφατες οθόνες σας εμφανίζονται εδώ"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Πληροφορίες εφαρμογής"</string>
<string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lock to app"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"αναζήτηση"</string>
@@ -267,8 +262,7 @@
<string name="zen_alarm_warning" msgid="6873910860111498041">"Δεν θα ακούτε το ξυπνητήρι σας στις <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Λιγότερο επείγουσες ειδοποιήσεις παρακάτω"</string>
- <!-- no translation found for notification_tap_again (8524949573675922138) -->
- <skip />
+ <string name="notification_tap_again" msgid="8524949573675922138">"Αγγίξτε ξανά για άνοιγμα"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Σύρετε για να ξεκλειδώσετε"</string>
<string name="phone_hint" msgid="3101468054914424646">"Σύρετε προς τα δεξιά για το τηλέφωνο"</string>
<string name="camera_hint" msgid="5241441720959174226">"Σύρετε αριστερά για τη φωτογραφική μηχανή"</string>
@@ -277,25 +271,19 @@
<string name="interruption_level_priority" msgid="6517366750688942030">"Προτεραιότητα"</string>
<string name="interruption_level_all" msgid="1330581184930945764">"Όλα"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Φόρτιση (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> για πλήρη φόρτιση)"</string>
- <!-- no translation found for accessibility_multi_user_switch_switcher (7305948938141024937) -->
- <skip />
- <!-- no translation found for accessibility_multi_user_switch_quick_contact (3020367729287990475) -->
- <skip />
+ <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Εναλλαγή χρήστη"</string>
+ <string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Εμφάνιση προφίλ"</string>
<string name="user_add_user" msgid="5110251524486079492">"Προσθήκη χρήστη"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Νέος χρήστης"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Επισκέπτης"</string>
- <!-- no translation found for guest_new_guest (600537543078847803) -->
- <skip />
+ <string name="guest_new_guest" msgid="600537543078847803">"Προσθήκη επισκέπτη"</string>
<string name="guest_exit_guest" msgid="7187359342030096885">"Κατάργηση επισκέπτη"</string>
<string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"Έξοδος από την περίοδο σύνδεσης επισκέπτη;"</string>
<string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"Η έξοδος από την περίοδο σύνδεσης επισκέπτη θα καταργήσει τα τοπικά δεδομένα."</string>
<string name="guest_wipe_session_title" msgid="6419439912885956132">"Επισκέπτη , καλώς όρισες ξανά!"</string>
- <!-- no translation found for guest_wipe_session_message (8476238178270112811) -->
- <skip />
- <!-- no translation found for guest_wipe_session_wipe (5065558566939858884) -->
- <skip />
- <!-- no translation found for guest_wipe_session_dontwipe (1401113462524894716) -->
- <skip />
+ <string name="guest_wipe_session_message" msgid="8476238178270112811">"Θέλετε να συνεχίσετε την περίοδο σύνδεσής σας;"</string>
+ <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"Έναρξη από την αρχή"</string>
+ <string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"Ναι, συνέχεια"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Για ένα λεπτό"</item>
<item quantity="other" msgid="6924190729213550991">"Για %d λεπτά"</item>
@@ -325,6 +313,5 @@
<string name="monitoring_description_legacy_vpn" msgid="4740349017929725435">"Είστε συνδεδεμένοι σε VPN (\"<xliff:g id="APPLICATION">%1$s</xliff:g>\").\n\nΟ πάροχος της υπηρεσίας VPN μπορεί να παρακολουθεί τη δραστηριότητα της συσκευής σας και του δικτύου, συμπεριλαμβανομένων των μηνυμάτων ηλεκτρονικού ταχυδρομείου, των εφαρμογών και των ασφαλών ιστότοπων."</string>
<string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Η διαχ. της συσκευής γίνεται από:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nΟ διαχειριστής μπορεί να παρακ. τη δραστ. του δικτύου, όπως τα μην. ηλ. ταχυδρ., τις εφαρ. και τους ασφ. ιστότ. Για περισ. πληροφορίες, επικοιν. με το διαχειριστή.\n\nΕπίσης, επιτρέψατε στο \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" να ρυθμίσει σύνδεση VPN. Αυτή η εφαρ. μπορεί να παρακ. τη δραστ. του δικτύου."</string>
<string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Η διαχείριση της συσκευής γίνεται από:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nΟ διαχειριστής μπορεί να παρακολ. τη δραστ. του δικτύου, όπως τα μην. ηλεκ. ταχυδρ., τις εφαρμογές και τους ασφαλείς ιστότοπους. Για περισ. πληροφορίες, επικοιν. με το διαχειριστή.\n\nΕπίσης, είστε συνδεδ. σε VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Ο παροχέας VPN μπορεί να παρακολ. τη δραστ. του δικτύου."</string>
- <!-- no translation found for keyguard_indication_trust_disabled (7412534203633528135) -->
- <skip />
+ <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Η συσκευή θα παραμείνει κλειδωμένη έως ότου την ξεκλειδώσετε μη αυτόματα"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 37c3b7d..bc4bbe0 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -157,8 +157,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Ilmoitus hylätty."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Ilmoitusalue."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Pika-asetukset."</string>
- <!-- no translation found for accessibility_desc_settings (3417884241751434521) -->
- <skip />
+ <string name="accessibility_desc_settings" msgid="3417884241751434521">"Asetukset"</string>
<!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) -->
<skip />
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Käyttäjä: <xliff:g id="USER">%s</xliff:g>."</string>
@@ -285,8 +284,7 @@
<string name="guest_nickname" msgid="8059989128963789678">"Vieras"</string>
<!-- no translation found for guest_new_guest (600537543078847803) -->
<skip />
- <!-- no translation found for guest_exit_guest (7187359342030096885) -->
- <skip />
+ <string name="guest_exit_guest" msgid="7187359342030096885">"Poista vieras"</string>
<string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"Lopetetaanko vierasistunto?"</string>
<string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"Vierasistunnon lopettaminen poistaa paikalliset tiedot."</string>
<string name="guest_wipe_session_title" msgid="6419439912885956132">"Tervetuloa takaisin!"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 7a8e741..1ea9cce 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -157,8 +157,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Ծանուցումը անտեսվեց:"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Ծանուցումների վահանակ:"</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Արագ կարգավորումներ:"</string>
- <!-- no translation found for accessibility_desc_settings (3417884241751434521) -->
- <skip />
+ <string name="accessibility_desc_settings" msgid="3417884241751434521">"Կարգավորումներ"</string>
<!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) -->
<skip />
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Օգտվող <xliff:g id="USER">%s</xliff:g>:"</string>
@@ -285,8 +284,7 @@
<string name="guest_nickname" msgid="8059989128963789678">"Հյուր"</string>
<!-- no translation found for guest_new_guest (600537543078847803) -->
<skip />
- <!-- no translation found for guest_exit_guest (7187359342030096885) -->
- <skip />
+ <string name="guest_exit_guest" msgid="7187359342030096885">"Հեռացնել հյուրին"</string>
<string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"Դուրս գա՞լ հյուրի ռեժիմից:"</string>
<string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"Հյուրի ռեժիմից դուրս գալուց հետո ձեր տեղական տվյալները կջնջվեն:"</string>
<string name="guest_wipe_session_title" msgid="6419439912885956132">"Բարի վերադարձ, հյուր:"</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 5ca2339..4041dab 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -157,8 +157,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"បានបដិសេធការជូនដំណឹង"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"ពណ៌ការជូនដំណឹង"</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"ការកំណត់រហ័ស។"</string>
- <!-- no translation found for accessibility_desc_settings (3417884241751434521) -->
- <skip />
+ <string name="accessibility_desc_settings" msgid="3417884241751434521">"ការកំណត់"</string>
<!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) -->
<skip />
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"អ្នកប្រើ <xliff:g id="USER">%s</xliff:g> ។"</string>
@@ -285,8 +284,7 @@
<string name="guest_nickname" msgid="8059989128963789678">"ភ្ញៀវ"</string>
<!-- no translation found for guest_new_guest (600537543078847803) -->
<skip />
- <!-- no translation found for guest_exit_guest (7187359342030096885) -->
- <skip />
+ <string name="guest_exit_guest" msgid="7187359342030096885">"លុបសម័យភ្ញៀវ"</string>
<string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"ចេញពីសម័យភ្ញៀវ?"</string>
<string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"ការចេញពីសម័យភ្ញៀវនឹងលុបទិន្នន័យមូលដ្ឋាន។"</string>
<string name="guest_wipe_session_title" msgid="6419439912885956132">"សូមស្វាគមន៍ការត្រឡប់មកវិញ, ភ្ញៀវ!"</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index f7dfb89..ab76d24 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_quick_settings_close" msgid="2571790856136835943">"ປິດແຖບ"</string>
<string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"ເພີ່ມເວລາ"</string>
<string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"ຫຼຸດເວລາ"</string>
- <!-- no translation found for accessibility_brightness (8003681285547803095) -->
- <skip />
+ <string name="accessibility_brightness" msgid="8003681285547803095">"ຄວາມແຈ້ງຂອງຈໍ"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"ຂໍ້ມູນ 2G-3G ແມ່ນປິດ"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"ຂໍ້ມູນ 4G ແມ່ນປິດ"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"ຂໍ້ມູນມືຖືຖືກປິດ"</string>
@@ -261,8 +260,7 @@
<string name="zen_alarm_warning" msgid="6873910860111498041">"ທ່ານຈະບໍ່ໄດ້ຍິນສຽງໂມງປຸກໃນເວລາ <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"ການແຈ້ງເຕືອນທີ່ສຳຄັນໜ້ອຍກວ່າຢູ່ດ້ານລຸ່ມ"</string>
- <!-- no translation found for notification_tap_again (8524949573675922138) -->
- <skip />
+ <string name="notification_tap_again" msgid="8524949573675922138">"ແຕະອີກເທື່ອນຶ່ງເພື່ອເປີດ"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"ເລື່ອນຂຶ້ນເພື່ອປົດລັອກ"</string>
<string name="phone_hint" msgid="3101468054914424646">"ປັດຂວາເພື່ອໃຊ້ໂທລະສັບ"</string>
<string name="camera_hint" msgid="5241441720959174226">"ປັດຊ້າຍເພື່ອໃຊ້ກ້ອງ"</string>
@@ -271,10 +269,8 @@
<string name="interruption_level_priority" msgid="6517366750688942030">"ລະດັບຄວາມສຳຄັນ"</string>
<string name="interruption_level_all" msgid="1330581184930945764">"ທັງໝົດ"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ກຳລັງສາກໄຟ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ກວ່າຈະເຕັມ)"</string>
- <!-- no translation found for accessibility_multi_user_switch_switcher (7305948938141024937) -->
- <skip />
- <!-- no translation found for accessibility_multi_user_switch_quick_contact (3020367729287990475) -->
- <skip />
+ <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ສະລັບຜູ່ໃຊ້"</string>
+ <string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"ສະແດງໂປຣໄຟລ໌"</string>
<string name="user_add_user" msgid="5110251524486079492">"ເພີ່ມຜູ່ໃຊ້"</string>
<string name="user_new_user_name" msgid="426540612051178753">"ຜູ່ໃຊ້ໃໝ່"</string>
<string name="guest_nickname" msgid="8059989128963789678">"ແຂກ"</string>
@@ -283,12 +279,9 @@
<string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"ສິ້ນສຸດການນຳໃຊ້ຂອງຜູ່ຢ້ຽມຢາມບໍ່?"</string>
<string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"ການອອກຈາກເຊດຊັນຜູ່ຢ້ຽມຢາມຈະເປັນການລຶບຂໍ້ມູນໃນເຄື່ອງອອ."</string>
<string name="guest_wipe_session_title" msgid="6419439912885956132">"ຍິນດີຕ້ອນຮັບກັບມາ, ຜູ່ຢ້ຽມຢາມ!"</string>
- <!-- no translation found for guest_wipe_session_message (8476238178270112811) -->
- <skip />
- <!-- no translation found for guest_wipe_session_wipe (5065558566939858884) -->
- <skip />
- <!-- no translation found for guest_wipe_session_dontwipe (1401113462524894716) -->
- <skip />
+ <string name="guest_wipe_session_message" msgid="8476238178270112811">"ທ່ານຕ້ອງການສືບຕໍ່ເຊດຊັນຂອງທ່ານບໍ່?"</string>
+ <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"ເລີ່ມຕົ້ນໃຫມ່"</string>
+ <string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"ຕົກລົງ, ດຳເນີນການຕໍ່"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"ເປັນເວລານຶ່ງນາທີ"</item>
<item quantity="other" msgid="6924190729213550991">"ເປັນເວລາ %d ນາທີ"</item>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 7cd48a0..4a665b6 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Самбарыг хаах"</string>
<string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Цаг нэмэх"</string>
<string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Цаг хасах"</string>
- <!-- no translation found for accessibility_brightness (8003681285547803095) -->
- <skip />
+ <string name="accessibility_brightness" msgid="8003681285547803095">"Дэлгэцийн гэрэлтэлт"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G дата идэвхгүй"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G дата идэвхгүй"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Үүрэн дата идэвхгүй"</string>
@@ -261,8 +260,7 @@
<string name="zen_alarm_warning" msgid="6873910860111498041">"Та <xliff:g id="ALARM_TIME">%s</xliff:g>-д өөрийн сэрүүлгээ сонсохгүй"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Яаралтай биш мэдэгдлүүдийг доор"</string>
- <!-- no translation found for notification_tap_again (8524949573675922138) -->
- <skip />
+ <string name="notification_tap_again" msgid="8524949573675922138">"Нээхийн тулд дахин хүрнэ үү"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Түгжээг тайлах бол шудрана уу"</string>
<string name="phone_hint" msgid="3101468054914424646">"Утас гаргахын тулд баруун шударна уу"</string>
<string name="camera_hint" msgid="5241441720959174226">"Камер гаргахын тулд зүүн шударна уу"</string>
@@ -271,10 +269,8 @@
<string name="interruption_level_priority" msgid="6517366750688942030">"Нэн тэргүүний"</string>
<string name="interruption_level_all" msgid="1330581184930945764">"Бүгд"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Цэнэглэж байна (дүүргэхэд <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
- <!-- no translation found for accessibility_multi_user_switch_switcher (7305948938141024937) -->
- <skip />
- <!-- no translation found for accessibility_multi_user_switch_quick_contact (3020367729287990475) -->
- <skip />
+ <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Хэрэглэгчийг сэлгэх"</string>
+ <string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Профайлыг харуулах"</string>
<string name="user_add_user" msgid="5110251524486079492">"Хэрэглэгч нэмэх"</string>
<string name="user_new_user_name" msgid="426540612051178753">"Шинэ хэрэглэгч"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Зочин"</string>
@@ -283,12 +279,9 @@
<string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"Зочны нэвтрэлтээс гарч байна уу?"</string>
<string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"Зочны нэвтрэлтээс гарснаар локал датаг арилгах болно."</string>
<string name="guest_wipe_session_title" msgid="6419439912885956132">"Тавтай морилно уу!"</string>
- <!-- no translation found for guest_wipe_session_message (8476238178270112811) -->
- <skip />
- <!-- no translation found for guest_wipe_session_wipe (5065558566939858884) -->
- <skip />
- <!-- no translation found for guest_wipe_session_dontwipe (1401113462524894716) -->
- <skip />
+ <string name="guest_wipe_session_message" msgid="8476238178270112811">"Та үргэлжлүүлэхийг хүсэж байна уу?"</string>
+ <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"Дахин эхлүүлэх"</string>
+ <string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"Тийм, үргэлжлүүлэх"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Нэг минутын турш"</item>
<item quantity="other" msgid="6924190729213550991">"%d минутын турш"</item>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index f4b29f6..2effb6b 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -157,8 +157,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pemberitahuan diketepikan."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bidai pemberitahuan."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Tetapan pantas."</string>
- <!-- no translation found for accessibility_desc_settings (3417884241751434521) -->
- <skip />
+ <string name="accessibility_desc_settings" msgid="3417884241751434521">"Tetapan"</string>
<!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) -->
<skip />
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Pengguna <xliff:g id="USER">%s</xliff:g>."</string>
@@ -285,8 +284,7 @@
<string name="guest_nickname" msgid="8059989128963789678">"Tetamu"</string>
<!-- no translation found for guest_new_guest (600537543078847803) -->
<skip />
- <!-- no translation found for guest_exit_guest (7187359342030096885) -->
- <skip />
+ <string name="guest_exit_guest" msgid="7187359342030096885">"Alih keluar tetamu"</string>
<string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"Keluar dari sesi tetamu?"</string>
<string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"Data tempatan akan dialih keluar apabila anda keluar dari sesi tetamu."</string>
<string name="guest_wipe_session_title" msgid="6419439912885956132">"Selamat kembali, tetamu!"</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index f6a89e0..d8d71a8 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -23,8 +23,7 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"ရှင်းလင်းရန်"</string>
<string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"စာရင်းမှ ဖယ်မည်"</string>
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"အပ်ပလီကေးရှင်း အချက်အလက်များ"</string>
- <!-- no translation found for status_bar_no_recent_apps (7374907845131203189) -->
- <skip />
+ <string name="status_bar_no_recent_apps" msgid="7374907845131203189">"သင်၏ မကြာမီက မျက်နှာပြင်များ ဒီမှာ ပေါ်လာကြမည်"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"လတ်တလောအပ်ပလီကေးရှင်းများအား ဖယ်ထုတ်မည်"</string>
<!-- String.format failed for translation -->
<!-- no translation found for status_bar_accessibility_recent_apps:other (1040784359794890744) -->
@@ -79,8 +78,7 @@
<string name="accessibility_back" msgid="567011538994429120">"နောက်သို့"</string>
<string name="accessibility_home" msgid="8217216074895377641">"ပင်မစာမျက်နှာ"</string>
<string name="accessibility_menu" msgid="316839303324695949">"မီနူး"</string>
- <!-- no translation found for accessibility_recent (1606470783629913980) -->
- <skip />
+ <string name="accessibility_recent" msgid="1606470783629913980">"မကြာမီက မျက်နှာပြင်များ"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"ရှာဖွေရန်"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"ကင်မရာ"</string>
<string name="accessibility_phone_button" msgid="6738112589538563574">"ဖုန်း"</string>
@@ -156,8 +154,7 @@
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"အကြောင်းကြားစာအကွက်"</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"အမြန်လုပ် အပြင်အဆင်"</string>
<string name="accessibility_desc_settings" msgid="3417884241751434521">"ဆက်တင်များ"</string>
- <!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) -->
- <skip />
+ <string name="accessibility_desc_recent_apps" msgid="8376953390514779637">"မကြာမီက မျက်နှာပြင်များ"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"သုံးစွဲသူ <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
<string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"မိုဘိုင်းလ် <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
@@ -169,8 +166,7 @@
<string name="accessibility_quick_settings_close" msgid="2571790856136835943">"ပိတ်ရန် အကွက်"</string>
<string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"အချိန် တိုးရန်"</string>
<string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"အချိန် လျှော့ရန်"</string>
- <!-- no translation found for accessibility_brightness (8003681285547803095) -->
- <skip />
+ <string name="accessibility_brightness" msgid="8003681285547803095">"တောက်ပမှုကို ပြရန်"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G ဒေတာ ပိတ်ထား"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G ဒေတာ ပိတ်ထား"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"ဆယ်လူလာ ဒေတာကို ပိတ်ထား"</string>
@@ -242,8 +238,7 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> သုံးထား"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ကန့်သတ်ချက်"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> သတိပေးချက်"</string>
- <!-- no translation found for recents_empty_message (8682129509540827999) -->
- <skip />
+ <string name="recents_empty_message" msgid="8682129509540827999">"သင်၏ မကြာမီက မျက်နှာပြင်များ ဒီမှာ ပေါ်လာကြမည်"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"အပလီကေးရှင်း အင်ဖို"</string>
<string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"appသို့ သော့ခတ်ထားရန်"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ရှာဖွေရန်"</string>
@@ -263,8 +258,7 @@
<string name="zen_alarm_warning" msgid="6873910860111498041">"သင်သည် သင်၏ <xliff:g id="ALARM_TIME">%s</xliff:g> နှိုးစက်ကို ကြားရမည် မဟုတ်"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"အရေးပါမှု နည်းသည့် အကြောင်းကြားချက်များ အောက်မှာ"</string>
- <!-- no translation found for notification_tap_again (8524949573675922138) -->
- <skip />
+ <string name="notification_tap_again" msgid="8524949573675922138">"ဖွင့်ရန် ထပ်ပြီး ထိပါ"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"သော့ဖွင့်ရန် အပေါ်သို့ ပွတ်ဆွဲပါ"</string>
<string name="phone_hint" msgid="3101468054914424646">"ဖုန်း အတွက် ညာသို့ ပွတ်ဆွဲပါ"</string>
<string name="camera_hint" msgid="5241441720959174226">"ကင်မရာ အတွက် ဘယ်သို့ ပွတ်ဆွဲပါ"</string>
@@ -273,25 +267,19 @@
<string name="interruption_level_priority" msgid="6517366750688942030">"ဦးစားပေးမှု"</string>
<string name="interruption_level_all" msgid="1330581184930945764">"အားလုံး"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> အပြည့် အထိ) အားသွင်းနေ"</string>
- <!-- no translation found for accessibility_multi_user_switch_switcher (7305948938141024937) -->
- <skip />
- <!-- no translation found for accessibility_multi_user_switch_quick_contact (3020367729287990475) -->
- <skip />
+ <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"အသုံးပြုသူကို ပြောင်းလဲရန်"</string>
+ <string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"ပရိုဖိုင်ကို ပြရန်"</string>
<string name="user_add_user" msgid="5110251524486079492">"သုံးသူ ထပ်ထည့်ရန်"</string>
<string name="user_new_user_name" msgid="426540612051178753">"အသုံးပြုသူ အသစ်"</string>
<string name="guest_nickname" msgid="8059989128963789678">"ဧည့်သည်"</string>
- <!-- no translation found for guest_new_guest (600537543078847803) -->
- <skip />
+ <string name="guest_new_guest" msgid="600537543078847803">"ဧည့်သည့်ကို ထည့်ပေးရန်"</string>
<string name="guest_exit_guest" msgid="7187359342030096885">"ဧည့်သည်ကို ဖယ်ထုတ်ရန်"</string>
<string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"ဧည့်သည် ချိတ်ဆက်မှုထဲက ထွက်မလား?"</string>
<string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"ဧည့်သည် ချိတ်ဆက်မှု ထဲမှ ထွက်လိုက်ခြင်းက စက်တွင်း ဒေတာကို ဖယ်ရှားပစ်မည်။"</string>
<string name="guest_wipe_session_title" msgid="6419439912885956132">"ပြန်လာတာ ကြိုဆိုပါသည်၊ ဧည့်သည်!"</string>
- <!-- no translation found for guest_wipe_session_message (8476238178270112811) -->
- <skip />
- <!-- no translation found for guest_wipe_session_wipe (5065558566939858884) -->
- <skip />
- <!-- no translation found for guest_wipe_session_dontwipe (1401113462524894716) -->
- <skip />
+ <string name="guest_wipe_session_message" msgid="8476238178270112811">"သင်သည် သင်၏ ချိတ်ဆက်မှုကို ဆက်ပြုလုပ် လိုပါသလား?"</string>
+ <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"အစမှ ပြန်စပါ"</string>
+ <string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"ဟုတ်ကဲ့၊ ဆက်လုပ်ပါ"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"တစ်မိနစ် အတွင်း"</item>
<item quantity="other" msgid="6924190729213550991">"%d မိနစ် အတွင်း"</item>
@@ -319,6 +307,5 @@
<string name="monitoring_description_legacy_vpn" msgid="4740349017929725435">"VPN (\"<xliff:g id="APPLICATION">%1$s</xliff:g>\") ကို သင်ချိတ်ဆက်မိ၏။\n\nသင့် VPN ဝန်ဆောင်မှုပေးသူသည် သင့်စက်ပစ္စည်းနှင့် အီးမေးများ၊ app များ နှင့် လုံခြုံသည့်ဝက်ဘ်ဆိုက် အပါအဝင် ကွန်ယက် လှုပ်ှရားမှုများကို စောင့်ကြည့်နိုင်သည်။"</string>
<string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"ဒီကိရိယာကို စီမံကွပ်ကဲသူမှာ:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nသင်၏ စီမံအုပ်ချုပ်သူက သင်၏ ကွန်ရက် လှုပ်ရှားမှုကို၊ အီးမေးလ်များ၊ appများ နှင့် လုံခြုံသည့် ဝက်ဘ်ဆိုက်များ အပါအဝင်ကို၊ စောင့်ကြပ် နိုင်ပါသည်။ အချက်အလက်များ ပိုပြီး ရယူရန်၊ သင်၏ စီမံအုပ်ချုပ်သူကို ဆက်သွယ်ပါ။\n\n ထို့အပြင် သင်သည် \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" အား VPN ချိတ်ဆက်မှု စဖွင့်လုပ်ကိုင်ရန် ခွင့်ပြုခဲ့သည်။ ဒီ appကပါ သင်၏ ကွန်ရက် လှုပ်ရှားမှုကို စောင့်ကြပ် နိုင်ပါသည်။"</string>
<string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"ဒီကိရိယာကို စီမံကွပ်ကဲသူမှာ:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nသင်၏ စီမံအုပ်ချုပ်သူက သင်၏ ကွန်ရက် လှုပ်ရှားမှုကို၊ အီးမေးလ်များ၊ appများ နှင့် လုံခြုံသည့် ဝက်ဘ်ဆိုက်များ အပါအဝင်ကို၊ စောင့်ကြပ် နိုင်ပါသည်။ အချက်အလက်များ ပိုပြီး ရယူရန်၊ သင်၏ စီမံအုပ်ချုပ်သူကို ဆက်သွယ်ပါ။\n\nထို့အပြင်၊ သင်သည် VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\") သို့ ချိတ်ဆက်ထားသည်။ သင်၏ VPN ဝန်ဆောင်မှုကို စီမံပေးသူကပါ ကွန်ရက် လှုပ်ရှားမှုများကို စောင့်ကြပ်နိုင်သေးသည်။"</string>
- <!-- no translation found for keyguard_indication_trust_disabled (7412534203633528135) -->
- <skip />
+ <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"သင်က လက်ဖြင့် သော့မဖွင့်မချင်း ကိရိယာမှာ သော့ပိတ်လျက် ရှိနေမည်"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 5f2c7ba..e44a5bc 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -157,8 +157,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"सूचना खारेज।"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"सूचना कक्ष।"</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"द्रुत सेटिङहरू"</string>
- <!-- no translation found for accessibility_desc_settings (3417884241751434521) -->
- <skip />
+ <string name="accessibility_desc_settings" msgid="3417884241751434521">"सेटिङहरू"</string>
<!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) -->
<skip />
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"प्रयोगकर्ता <xliff:g id="USER">%s</xliff:g>।"</string>
@@ -285,8 +284,7 @@
<string name="guest_nickname" msgid="8059989128963789678">"अतिथि"</string>
<!-- no translation found for guest_new_guest (600537543078847803) -->
<skip />
- <!-- no translation found for guest_exit_guest (7187359342030096885) -->
- <skip />
+ <string name="guest_exit_guest" msgid="7187359342030096885">"अतिथि हटाउनुहोस्"</string>
<string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"अतिथि सत्र बाहिरिंदै छ?"</string>
<string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"अतिथि सत्र अन्त्यले स्थानीय डेटा हटाउने छ।"</string>
<string name="guest_wipe_session_title" msgid="6419439912885956132">"पुनः स्वागत, अतिथि!"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 51c05261..4f6ccc8 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -159,8 +159,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificação dispensada."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Aba de notificações."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Configurações rápidas."</string>
- <!-- no translation found for accessibility_desc_settings (3417884241751434521) -->
- <skip />
+ <string name="accessibility_desc_settings" msgid="3417884241751434521">"Configurações"</string>
<!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) -->
<skip />
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Usuário <xliff:g id="USER">%s</xliff:g>."</string>
@@ -287,8 +286,7 @@
<string name="guest_nickname" msgid="8059989128963789678">"Convidado"</string>
<!-- no translation found for guest_new_guest (600537543078847803) -->
<skip />
- <!-- no translation found for guest_exit_guest (7187359342030096885) -->
- <skip />
+ <string name="guest_exit_guest" msgid="7187359342030096885">"Remover convidado"</string>
<string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"Sair da sessão de convidado?"</string>
<string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"Sair da sessão de convidado removerá os dados locais."</string>
<string name="guest_wipe_session_title" msgid="6419439912885956132">"Bem-vindo, convidado."</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 9da5cc5..dba66e7 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -157,8 +157,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificarea a fost închisă."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Fereastră pentru notificări."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Setări rapide."</string>
- <!-- no translation found for accessibility_desc_settings (3417884241751434521) -->
- <skip />
+ <string name="accessibility_desc_settings" msgid="3417884241751434521">"Setări"</string>
<!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) -->
<skip />
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Utilizatorul <xliff:g id="USER">%s</xliff:g>."</string>
@@ -285,8 +284,7 @@
<string name="guest_nickname" msgid="8059989128963789678">"Invitat"</string>
<!-- no translation found for guest_new_guest (600537543078847803) -->
<skip />
- <!-- no translation found for guest_exit_guest (7187359342030096885) -->
- <skip />
+ <string name="guest_exit_guest" msgid="7187359342030096885">"Eliminați invitatul"</string>
<!-- no translation found for guest_exit_guest_dialog_title (7587460301980067285) -->
<skip />
<!-- no translation found for guest_exit_guest_dialog_message (10255285459589280) -->
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 18601a0..d65d765 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -157,8 +157,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"දැනුම්දීම නිෂ්ප්රභා කරඇත."</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"දැනුම්දීම් ආවරණය."</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"ක්ෂණික සැකසීම්."</string>
- <!-- no translation found for accessibility_desc_settings (3417884241751434521) -->
- <skip />
+ <string name="accessibility_desc_settings" msgid="3417884241751434521">"සැකසීම්"</string>
<!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) -->
<skip />
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"පරිශීලකයා <xliff:g id="USER">%s</xliff:g>."</string>
@@ -285,8 +284,7 @@
<string name="guest_nickname" msgid="8059989128963789678">"අමුත්තා"</string>
<!-- no translation found for guest_new_guest (600537543078847803) -->
<skip />
- <!-- no translation found for guest_exit_guest (7187359342030096885) -->
- <skip />
+ <string name="guest_exit_guest" msgid="7187359342030096885">"අමුත්තාන් ඉවත් කරන්න"</string>
<string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"අමුත්තාගේ සැසියෙන් පිටවෙයිද?"</string>
<string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"අමුත්තාගේ සැසිය අවසන් කිරීමෙන් පෙදෙසි දත්ත සියල්ලම පිට කරයි."</string>
<string name="guest_wipe_session_title" msgid="6419439912885956132">"නැවත සාදරයෙන් පිළිගනිමු, අමුත්තා!"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index c09209c..bca8966 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -159,8 +159,7 @@
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"已关闭通知。"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知栏。"</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"快捷设置。"</string>
- <!-- no translation found for accessibility_desc_settings (3417884241751434521) -->
- <skip />
+ <string name="accessibility_desc_settings" msgid="3417884241751434521">"设置"</string>
<!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) -->
<skip />
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"用户:<xliff:g id="USER">%s</xliff:g>。"</string>
@@ -287,8 +286,7 @@
<string name="guest_nickname" msgid="8059989128963789678">"访客"</string>
<!-- no translation found for guest_new_guest (600537543078847803) -->
<skip />
- <!-- no translation found for guest_exit_guest (7187359342030096885) -->
- <skip />
+ <string name="guest_exit_guest" msgid="7187359342030096885">"移除访客"</string>
<string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"要退出访客模式吗?"</string>
<string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"退出访客模式将移除本地数据。"</string>
<string name="guest_wipe_session_title" msgid="6419439912885956132">"访客,欢迎回来!"</string>
diff --git a/packages/SystemUI/res/values/arrays.xml b/packages/SystemUI/res/values/arrays.xml
index 630a48d..6102aa6 100644
--- a/packages/SystemUI/res/values/arrays.xml
+++ b/packages/SystemUI/res/values/arrays.xml
@@ -25,7 +25,7 @@
<item>100</item>
</array>
<array name="batterymeter_color_values">
- <item>#FFFF3300</item>
+ <item>@*android:color/battery_saver_mode_color</item>
<item>#FFFFFFFF</item>
</array>
<array name="batterymeter_bolt_points">
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 40870bf..dea14e9 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -105,4 +105,5 @@
<color name="search_panel_card_color">#ffffff</color>
<color name="keyguard_user_switcher_background_gradient_color">#77000000</color>
+ <color name="doze_small_icon_background_color">#ff434343</color>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 42d9734..52dc000 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -189,6 +189,9 @@
<!-- Doze: interval between pulses when following the notification light -->
<integer name="doze_notification_pulse_interval">30000</integer>
+ <!-- Doze: alpha to apply to small icons when dozing -->
+ <integer name="doze_small_icon_alpha">222</integer><!-- 87% of 0xff -->
+
<!-- Volume: time to delay dismissing the volume panel after a click is performed -->
<integer name="volume_panel_dismiss_delay">200</integer>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 1b8eeb2..c8db284 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -430,4 +430,16 @@
<!-- The text size for battery level -->
<dimen name="battery_level_text_size">12sp</dimen>
+
+ <!-- TrustDrawable: Minimum inner radius of the breathing animation -->
+ <dimen name="trust_circle_inner_radius_visible_min">22dp</dimen>
+ <!-- TrustDrawable: Maximum inner radius of the breathing animation -->
+ <dimen name="trust_circle_inner_radius_visible_max">24dp</dimen>
+ <!-- TrustDrawable: Inner radius at the end of the exit animation -->
+ <dimen name="trust_circle_inner_radius_exit">38dp</dimen>
+ <!-- TrustDrawable: Inner radius at the beginning of the enter animation -->
+ <dimen name="trust_circle_inner_radius_enter">18dp</dimen>
+ <!-- TrustDrawable: Thickness of the circle -->
+ <dimen name="trust_circle_thickness">2dp</dimen>
+
</resources>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 6418930..4e93cd8 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -34,5 +34,6 @@
<item type="id" name="alpha_animator_start_value_tag"/>
<item type="id" name="top_inset_animator_start_value_tag"/>
<item type="id" name="height_animator_start_value_tag"/>
+ <item type="id" name="doze_saved_filter_tag"/>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d49312d..120af1d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -213,6 +213,23 @@
<string name="accessibility_camera_button">Camera</string>
<!-- Content description of the phone button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_phone_button">Phone</string>
+ <!-- Click action label for accessibility for the unlock button. [CHAR LIMIT=NONE] -->
+ <string name="unlock_label">unlock</string>
+ <!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
+ <string name="phone_label">open phone</string>
+ <!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
+ <string name="camera_label">open camera</string>
+
+ <!-- Content description of the lock icon when device is secured (lock closed) and trust not managed (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_unlock_button_secured">Device secured.</string>
+ <!-- Content description of the lock icon when device is not secured (lock open) and trust not managed (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_unlock_button_not_secured">Device not secured.</string>
+ <!-- Content description of the lock icon when device is secured (lock closed) and trust managed (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_unlock_button_secured_trust_managed">Device secured, trust agent active.</string>
+ <!-- Content description of the lock icon when device is not secured (lock open) and trust managed (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_unlock_button_not_secured_trust_managed">Device not secured, trust agent active.</string>
+ <!-- Content description of the lock icon when face unlock is running (face icon) and trust managed (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_unlock_button_face_unlock_running">Face detection running, trust agent active.</string>
<!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_ime_switch_button">Switch input method button.</string>
@@ -306,15 +323,6 @@
<!-- Content description of an item with full signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_signal_full">Signal full.</string>
- <!-- Content description of an item that is turned on for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_desc_on">On.</string>
- <!-- Content description of an item that is turned off for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_desc_off">Off.</string>
- <!-- Content description of an item that is connected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_desc_connected">Connected.</string>
- <!-- Content description of an item that is connecting for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_desc_connecting">Connecting.</string>
-
<!-- Content description of the data connection type GPRS for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_data_connection_gprs">GPRS</string>
@@ -408,24 +416,68 @@
<string name="accessibility_quick_settings_user">User <xliff:g id="user" example="John Doe">%s</xliff:g>.</string>
<!-- Content description of the wifi tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_wifi"><xliff:g id="signal" example="Three bars">%1$s</xliff:g>.</string>
+ <!-- Announcement made when the wifi is turned off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_wifi_changed_off">Wifi turned off.</string>
+ <!-- Announcement made when the wifi is turned on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_wifi_changed_on">Wifi turned on.</string>
<!-- Content description of the mobile data tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_mobile">Mobile <xliff:g id="signal" example="Three bars">%1$s</xliff:g>. <xliff:g id="type" example="4G">%2$s</xliff:g>. <xliff:g id="network" example="T-Mobile">%3$s</xliff:g>.</string>
<!-- Content description of the battery tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_battery">Battery <xliff:g id="state" example="50% charging">%s</xliff:g>.</string>
- <!-- Content description of the airplane mode tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_airplane">Airplane Mode <xliff:g id="state" example="Off">%s</xliff:g>.</string>
- <!-- Content description of the bluetooth tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_bluetooth">Bluetooth <xliff:g id="state" example="Off">%s</xliff:g>.</string>
- <!-- Content description of the location tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_location">Location <xliff:g id="state" example="Off">%s</xliff:g>.</string>
+ <!-- Content description of the airplane mode tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_airplane_off">Airplane mode off.</string>
+ <!-- Content description of the airplane mode tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_airplane_on">Airplane mode on.</string>
+ <!-- Announcement made when the airplane mode changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_airplane_changed_off">Airplane mode turned off.</string>
+ <!-- Announcement made when the airplane mode changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_airplane_changed_on">Airplane mode turned on.</string>
+ <!-- Content description of the bluetooth tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_bluetooth_off">Bluetooth off.</string>
+ <!-- Content description of the bluetooth tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_bluetooth_on">Bluetooth on.</string>
+ <!-- Content description of the bluetooth tile in quick settings when connecting (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_bluetooth_connecting">Bluetooth connecting.</string>
+ <!-- Content description of the bluetooth tile in quick settings when connected (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_bluetooth_connected">Bluetooth connected.</string>
+ <!-- Announcement made when the bluetooth is turned off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_bluetooth_changed_off">Bluetooth turned off.</string>
+ <!-- Announcement made when the bluetooth is turned on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_bluetooth_changed_on">Bluetooth turned on.</string>
+ <!-- Content description of the location tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_location_off">Location reporting off.</string>
+ <!-- Content description of the location tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_location_on">Location reporting on.</string>
+ <!-- Announcement made when the location tile changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_location_changed_off">Location reporting turned off.</string>
+ <!-- Announcement made when the location tile changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_location_changed_on">Location reporting turned on.</string>
<!-- Content description of the alarm tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_alarm">Alarm set for <xliff:g id="time" example="Wed 3:30 PM">%s</xliff:g>.</string>
<!-- Content description of quick settings detail panel close button (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_close">Close panel</string>
+ <string name="accessibility_quick_settings_close">Close panel.</string>
<!-- Content description of zen mode time condition plus button (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_more_time">More time</string>
+ <string name="accessibility_quick_settings_more_time">More time.</string>
<!-- Content description of zen mode time condition minus button (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_quick_settings_less_time">Less time</string>
+ <string name="accessibility_quick_settings_less_time">Less time.</string>
+ <!-- Content description of the flashlight tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_flashlight_off">Flashlight off.</string>
+ <!-- Content description of the flashlight tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_flashlight_on">Flashlight on.</string>
+ <!-- Announcement made when the flashlight state changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_flashlight_changed_off">Flashlight turned off.</string>
+ <!-- Announcement made when the flashlight state changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_flashlight_changed_on">Flashlight turned on.</string>
+ <!-- Announcement made when the color inversion state changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_color_inversion_changed_off">Color inversion turned off.</string>
+ <!-- Announcement made when the color inversion state changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_color_inversion_changed_on">Color inversion turned on.</string>
+ <!-- Announcement made when the hotspot state changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_hotspot_changed_off">Mobile hotspot turned off.</string>
+ <!-- Announcement made when the hotspot state changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_hotspot_changed_on">Mobile hotspot turned on.</string>
+ <!-- Announcement made when the screen stopped casting (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_casting_turned_off">Screen casting stopped.</string>
<!-- Content description of the display brightness slider (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_brightness">Display brightness</string>
@@ -480,6 +532,15 @@
<!-- Description of the button in the phone-style notification panel that controls auto-rotation, when auto-rotation is off. [CHAR LIMIT=NONE] -->
<string name="accessibility_rotation_lock_on_portrait">Screen is locked in portrait orientation.</string>
+ <!-- Announcement made when the screen is rotating automatically again (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_rotation_lock_off_changed">Screen will now rotate automatically.</string>
+
+ <!-- Announcement made when the rotation lock state changes to landscape only (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_rotation_lock_on_landscape_changed">Screen is now locked in landscape orientation.</string>
+
+ <!-- Announcement made when the rotation lock state changes to portrait only (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_rotation_lock_on_portrait_changed">Screen is now locked in portrait orientation.</string>
+
<!-- Name of the K-release easter egg: a display case for all our tastiest desserts. [CHAR LIMIT=30] -->
<string name="dessert_case">Dessert Case</string>
@@ -782,8 +843,8 @@
<!-- Monitoring dialog title for normal devices [CHAR LIMIT=35]-->
<string name="monitoring_title">Network monitoring</string>
- <!-- Monitoring dialog open app button [CHAR LIMIT=30] -->
- <string name="open_app">Open app</string>
+ <!-- Monitoring dialog disable vpn button [CHAR LIMIT=30] -->
+ <string name="disable_vpn">Disable VPN</string>
<!-- Monitoring dialog disconnect vpn button [CHAR LIMIT=30] -->
<string name="disconnect_vpn">Disconnect VPN</string>
@@ -806,4 +867,6 @@
<!-- Indication on the keyguard that appears when the user disables trust agents until the next time they unlock manually. [CHAR LIMIT=NONE] -->
<string name="keyguard_indication_trust_disabled">Device will stay locked until you manually unlock</string>
+ <!-- Indication that the current volume and other effects (vibration) are being suppressed by a third party, such as a notification listener. [CHAR LIMIT=30] -->
+ <string name="muted_by">Muted by <xliff:g id="third_party">%1$s</xliff:g></string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index b9ffdbb..5e2f784 100755
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -33,7 +33,10 @@
import android.util.AttributeSet;
import android.view.View;
-public class BatteryMeterView extends View implements DemoMode {
+import com.android.systemui.statusbar.policy.BatteryController;
+
+public class BatteryMeterView extends View implements DemoMode,
+ BatteryController.BatteryStateChangeCallback {
public static final String TAG = BatteryMeterView.class.getSimpleName();
public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
@@ -68,6 +71,9 @@
private final Path mClipPath = new Path();
private final Path mTextPath = new Path();
+ private BatteryController mBatteryController;
+ private boolean mPowerSaveEnabled;
+
private class BatteryTracker extends BroadcastReceiver {
public static final int UNKNOWN_LEVEL = -1;
@@ -155,6 +161,7 @@
// preload the battery level
mTracker.onReceive(getContext(), sticky);
}
+ mBatteryController.addStateChangedCallback(this);
}
@Override
@@ -162,6 +169,7 @@
super.onDetachedFromWindow();
getContext().unregisterReceiver(mTracker);
+ mBatteryController.removeStateChangedCallback(this);
}
public BatteryMeterView(Context context) {
@@ -227,6 +235,22 @@
mBoltPoints = loadBoltPoints(res);
}
+ public void setBatteryController(BatteryController batteryController) {
+ mBatteryController = batteryController;
+ mPowerSaveEnabled = mBatteryController.isPowerSave();
+ }
+
+ @Override
+ public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+ // TODO: Use this callback instead of own broadcast receiver.
+ }
+
+ @Override
+ public void onPowerSaveChanged() {
+ mPowerSaveEnabled = mBatteryController.isPowerSave();
+ invalidate();
+ }
+
private static float[] loadBoltPoints(Resources res) {
final int[] pts = res.getIntArray(R.array.batterymeter_bolt_points);
int maxX = 0, maxY = 0;
@@ -251,6 +275,11 @@
}
private int getColorForLevel(int percent) {
+
+ // If we are in power save mode, always use the normal color.
+ if (mPowerSaveEnabled) {
+ return mColors[mColors.length-1];
+ }
int thresh, color = 0;
for (int i=0; i<mColors.length; i+=2) {
thresh = mColors[i];
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 74c0328..fe1e5db 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -76,6 +76,7 @@
private PendingIntent mNotificationPulseIntent;
private int mMultipulseCount;
private int mNotificationPulseInterval;
+ private boolean mPowerSaveActive;
public DozeService() {
if (DEBUG) Log.d(mTag, "new DozeService()");
@@ -94,6 +95,7 @@
pw.print(" mNotificationLightOn: "); pw.println(mNotificationLightOn);
pw.print(" mMultipulseCount: "); pw.println(mMultipulseCount);
pw.print(" mNotificationPulseInterval: "); pw.println(mNotificationPulseInterval);
+ pw.print(" mPowerSaveActive: "); pw.println(mPowerSaveActive);
}
@Override
@@ -141,7 +143,13 @@
@Override
public void onDreamingStarted() {
super.onDreamingStarted();
- if (DEBUG) Log.d(mTag, "onDreamingStarted canDoze=" + canDoze());
+ mPowerSaveActive = mHost != null && mHost.isPowerSaveActive();
+ if (DEBUG) Log.d(mTag, "onDreamingStarted canDoze=" + canDoze() + " mPowerSaveActive="
+ + mPowerSaveActive);
+ if (mPowerSaveActive) {
+ finishToSavePower();
+ return;
+ }
mDreaming = true;
listenForPulseSignals(true);
requestDoze();
@@ -232,6 +240,11 @@
}
}
+ private void finishToSavePower() {
+ Log.w(mTag, "Exiting ambient mode due to low power battery saver");
+ finish();
+ }
+
private void listenForPulseSignals(boolean listen) {
if (DEBUG) Log.d(mTag, "listenForPulseSignals: " + listen);
mSigMotionSensor.setListening(listen);
@@ -329,6 +342,14 @@
mNotificationLightOn = on;
rescheduleNotificationPulse();
}
+
+ @Override
+ public void onPowerSaveChanged(boolean active) {
+ mPowerSaveActive = active;
+ if (mPowerSaveActive && mDreaming) {
+ finishToSavePower();
+ }
+ }
};
public interface Host {
@@ -337,11 +358,13 @@
void requestDoze(DozeService dozeService);
void requestPulse(int pulses, boolean delayed, DozeService dozeService);
void dozingStopped(DozeService dozeService);
+ boolean isPowerSaveActive();
public interface Callback {
void onNewNotifications();
void onBuzzBeepBlinked();
void onNotificationLight(boolean on);
+ void onPowerSaveChanged(boolean active);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index bfbc56c..a8199fa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -119,11 +119,7 @@
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_NEGATIVE) {
- if (mSecurityController.isLegacyVpn()) {
- mSecurityController.disconnectFromLegacyVpn();
- } else {
- mSecurityController.openVpnApp();
- }
+ mSecurityController.disconnectFromVpn();
}
}
@@ -142,7 +138,7 @@
if (mSecurityController.isLegacyVpn()) {
return mContext.getString(R.string.disconnect_vpn);
} else {
- return mContext.getString(R.string.open_app);
+ return mContext.getString(R.string.disable_vpn);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index bf01b7b..a2136d2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -71,6 +71,7 @@
private QSTileHost mHost;
private QSFooter mFooter;
+ private boolean mGridContentVisible = true;
public QSPanel(Context context) {
this(context, null);
@@ -189,13 +190,13 @@
mHandler.obtainMessage(H.SHOW_DETAIL, show ? 1 : 0, 0, r).sendToTarget();
}
- private void setTileVisibility(View v, boolean visible) {
- mHandler.obtainMessage(H.SET_TILE_VISIBILITY, visible ? 1 : 0, 0, v).sendToTarget();
+ private void setTileVisibility(View v, int visibility) {
+ mHandler.obtainMessage(H.SET_TILE_VISIBILITY, visibility, 0, v).sendToTarget();
}
- private void handleSetTileVisibility(View v, boolean visible) {
- if (visible == (v.getVisibility() == VISIBLE)) return;
- v.setVisibility(visible ? VISIBLE : GONE);
+ private void handleSetTileVisibility(View v, int visibility) {
+ if (visibility == v.getVisibility()) return;
+ v.setVisibility(visibility);
}
public void setTiles(Collection<QSTile<?>> tiles) {
@@ -219,7 +220,14 @@
final QSTile.Callback callback = new QSTile.Callback() {
@Override
public void onStateChanged(QSTile.State state) {
- setTileVisibility(r.tileView, state.visible);
+ int visibility = state.visible ? VISIBLE : GONE;
+ if (state.visible && !mGridContentVisible) {
+
+ // We don't want to show it if the content is hidden,
+ // then we just set it to invisible, to ensure that it gets visible again
+ visibility = INVISIBLE;
+ }
+ setTileVisibility(r.tileView, visibility);
r.tileView.onStateChanged(state);
}
@Override
@@ -239,6 +247,11 @@
fireScanStateChanged(r.scanState);
}
}
+
+ @Override
+ public void onAnnouncementRequested(CharSequence announcement) {
+ announceForAccessibility(announcement);
+ }
};
r.tile.setCallback(callback);
final View.OnClickListener click = new View.OnClickListener() {
@@ -312,7 +325,9 @@
mDetail.bringToFront();
mDetailContent.addView(r.detailView);
setDetailRecord(r);
+ listener = mHideGridContentWhenDone;
} else {
+ setGridContentVisibility(true);
listener = mTeardownDetailWhenDone;
fireScanStateChanged(false);
}
@@ -320,6 +335,18 @@
mClipper.animateCircularClip(x, y, show, listener);
}
+ private void setGridContentVisibility(boolean visible) {
+ int newVis = visible ? VISIBLE : INVISIBLE;
+ for (int i = 0; i < mRecords.size(); i++) {
+ TileRecord tileRecord = mRecords.get(i);
+ if (tileRecord.tileView.getVisibility() != GONE) {
+ tileRecord.tileView.setVisibility(newVis);
+ }
+ }
+ mBrightnessView.setVisibility(newVis);
+ mGridContentVisible = visible;
+ }
+
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = MeasureSpec.getSize(widthMeasureSpec);
@@ -443,7 +470,7 @@
if (msg.what == SHOW_DETAIL) {
handleShowDetail((Record)msg.obj, msg.arg1 != 0);
} else if (msg.what == SET_TILE_VISIBILITY) {
- handleSetTileVisibility((View)msg.obj, msg.arg1 != 0);
+ handleSetTileVisibility((View)msg.obj, msg.arg1);
}
}
}
@@ -468,6 +495,13 @@
};
};
+ private final AnimatorListenerAdapter mHideGridContentWhenDone = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ setGridContentVisibility(false);
+ }
+ };
+
public interface Callback {
void onShowingDetail(QSTile.DetailAdapter detail);
void onToggleStateChanged(boolean state);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 409cc46..876652c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -60,6 +60,7 @@
private Callback mCallback;
protected final TState mState = newTileState();
private final TState mTmpState = newTileState();
+ private boolean mAnnounceNextStateChange;
abstract protected TState newTileState();
abstract protected void handleClick();
@@ -161,9 +162,25 @@
}
private void handleStateChanged() {
+ boolean delayAnnouncement = shouldAnnouncementBeDelayed();
if (mCallback != null) {
mCallback.onStateChanged(mState);
+ if (mAnnounceNextStateChange && !delayAnnouncement) {
+ String announcement = composeChangeAnnouncement();
+ if (announcement != null) {
+ mCallback.onAnnouncementRequested(announcement);
+ }
+ }
}
+ mAnnounceNextStateChange = mAnnounceNextStateChange && delayAnnouncement;
+ }
+
+ protected boolean shouldAnnouncementBeDelayed() {
+ return false;
+ }
+
+ protected String composeChangeAnnouncement() {
+ return null;
}
private void handleShowDetail(boolean show) {
@@ -217,6 +234,7 @@
handleSetCallback((QSTile.Callback)msg.obj);
} else if (msg.what == CLICK) {
name = "handleClick";
+ mAnnounceNextStateChange = true;
handleClick();
} else if (msg.what == SECONDARY_CLICK) {
name = "handleSecondaryClick";
@@ -255,6 +273,7 @@
void onShowDetail(boolean show);
void onToggleStateChanged(boolean state);
void onScanStateChanged(boolean state);
+ void onAnnouncementRequested(CharSequence announcement);
}
public interface Host {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index 2cc1f07..20fd5a0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -50,6 +50,7 @@
private final int mTilePaddingTopPx;
private final int mTilePaddingBelowIconPx;
private final int mDualTileVerticalPaddingPx;
+ private final View mTopBackgroundView;
private TextView mLabel;
private QSDualTileLabel mDualLabel;
@@ -72,6 +73,9 @@
recreateLabel();
setClipChildren(false);
+ mTopBackgroundView = new View(context);
+ addView(mTopBackgroundView);
+
mIcon = createIcon();
addView(mIcon);
@@ -82,7 +86,6 @@
addView(mDivider);
setClickable(true);
- setBackground(getTileBackground());
}
private void recreateLabel() {
@@ -104,7 +107,6 @@
mDualLabel = new QSDualTileLabel(mContext);
mDualLabel.setId(android.R.id.title);
mDualLabel.setBackgroundResource(R.drawable.btn_borderless_rect);
- mDualLabel.setFirstLineCaret(res.getDrawable(R.drawable.qs_dual_tile_caret));
mDualLabel.setTextColor(res.getColor(R.color.qs_tile_text));
mDualLabel.setPadding(0, mDualTileVerticalPaddingPx, 0, mDualTileVerticalPaddingPx);
mDualLabel.setTypeface(CONDENSED);
@@ -112,6 +114,7 @@
res.getDimensionPixelSize(R.dimen.qs_tile_text_size));
mDualLabel.setClickable(true);
mDualLabel.setOnClickListener(mClickSecondary);
+ mDualLabel.setFocusable(true);
if (labelText != null) {
mDualLabel.setText(labelText);
}
@@ -143,11 +146,36 @@
if (changed) {
recreateLabel();
}
- setOnClickListener(mClickPrimary);
+ Drawable tileBackground = getTileBackground();
+ if (tileBackground instanceof RippleDrawable) {
+ setRipple((RippleDrawable) tileBackground);
+ }
+ if (dual) {
+ mTopBackgroundView.setOnClickListener(mClickPrimary);
+ setOnClickListener(null);
+ setClickable(false);
+ setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+ mTopBackgroundView.setBackground(tileBackground);
+ } else {
+ mTopBackgroundView.setOnClickListener(null);
+ mTopBackgroundView.setClickable(false);
+ setOnClickListener(mClickPrimary);
+ setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+ setBackground(tileBackground);
+ }
+ mTopBackgroundView.setFocusable(dual);
+ setFocusable(!dual);
mDivider.setVisibility(dual ? VISIBLE : GONE);
postInvalidate();
}
+ private void setRipple(RippleDrawable tileBackground) {
+ mRipple = tileBackground;
+ if (getWidth() != 0) {
+ updateRippleSize(getWidth(), getHeight());
+ }
+ }
+
public void init(OnClickListener clickPrimary, OnClickListener clickSecondary) {
mClickPrimary = clickPrimary;
mClickSecondary = clickSecondary;
@@ -165,9 +193,6 @@
final TypedArray ta = mContext.obtainStyledAttributes(attrs);
final Drawable d = ta.getDrawable(0);
ta.recycle();
- if (d instanceof RippleDrawable) {
- mRipple = (RippleDrawable) d;
- }
return d;
}
@@ -185,6 +210,9 @@
if (mDual) {
mDivider.measure(widthMeasureSpec, exactly(mDivider.getLayoutParams().height));
}
+ int heightSpec = exactly(
+ mIconSizePx + mTilePaddingBelowIconPx + mTilePaddingTopPx);
+ mTopBackgroundView.measure(widthMeasureSpec, heightSpec);
setMeasuredDimension(w, h);
}
@@ -197,17 +225,16 @@
final int w = getMeasuredWidth();
final int h = getMeasuredHeight();
+ layout(mTopBackgroundView, 0, mTileSpacingPx);
+
int top = 0;
top += mTileSpacingPx;
top += mTilePaddingTopPx;
final int iconLeft = (w - mIcon.getMeasuredWidth()) / 2;
layout(mIcon, iconLeft, top);
if (mRipple != null) {
- // center the touch feedback on the center of the icon, and dial it down a bit
- final int cx = w / 2;
- final int cy = mDual ? mIcon.getTop() + mIcon.getHeight() / 2 : h / 2;
- final int rad = (int)(mIcon.getHeight() * 1.25);
- mRipple.setHotspotBounds(cx - rad, cy - rad, cx + rad, cy + rad);
+ updateRippleSize(w, h);
+
}
top = mIcon.getBottom();
top += mTilePaddingBelowIconPx;
@@ -218,6 +245,14 @@
layout(labelView(), 0, top);
}
+ private void updateRippleSize(int width, int height) {
+ // center the touch feedback on the center of the icon, and dial it down a bit
+ final int cx = width / 2;
+ final int cy = mDual ? mIcon.getTop() + mIcon.getHeight() / 2 : height / 2;
+ final int rad = (int)(mIcon.getHeight() * 1.25f);
+ mRipple.setHotspotBounds(cx - rad, cy - rad, cx + rad, cy + rad);
+ }
+
private static void layout(View child, int left, int top) {
child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight());
}
@@ -256,4 +291,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index 5d1fa80..51401c8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -70,13 +70,20 @@
if (airplaneMode) {
state.iconId = R.drawable.ic_qs_airplane_on;
state.contentDescription = mContext.getString(
- R.string.accessibility_quick_settings_airplane,
- mContext.getString(R.string.accessibility_desc_on));
+ R.string.accessibility_quick_settings_airplane_on);
} else {
state.iconId = R.drawable.ic_qs_airplane_off;
state.contentDescription = mContext.getString(
- R.string.accessibility_quick_settings_airplane,
- mContext.getString(R.string.accessibility_desc_off));
+ R.string.accessibility_quick_settings_airplane_off);
+ }
+ }
+
+ @Override
+ protected String composeChangeAnnouncement() {
+ if (mState.value) {
+ return mContext.getString(R.string.accessibility_quick_settings_airplane_changed_on);
+ } else {
+ return mContext.getString(R.string.accessibility_quick_settings_airplane_changed_off);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 19b9ec1..109237b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -77,7 +77,7 @@
@Override
protected void handleSecondaryClick() {
- showDetail(true);
+ mHost.startSettingsActivity(BLUETOOTH_SETTINGS);
}
@Override
@@ -88,21 +88,22 @@
final boolean connecting = mController.isBluetoothConnecting();
state.visible = supported;
state.value = enabled;
- final String stateContentDescription;
if (enabled) {
state.label = null;
if (connected) {
state.iconId = R.drawable.ic_qs_bluetooth_connected;
- stateContentDescription = mContext.getString(R.string.accessibility_desc_connected);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_bluetooth_connected);
state.label = mController.getLastDeviceName();
} else if (connecting) {
state.iconId = R.drawable.ic_qs_bluetooth_connecting;
- stateContentDescription =
- mContext.getString(R.string.accessibility_desc_connecting);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_bluetooth_connecting);
state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
} else {
state.iconId = R.drawable.ic_qs_bluetooth_on;
- stateContentDescription = mContext.getString(R.string.accessibility_desc_on);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_bluetooth_on);
}
if (TextUtils.isEmpty(state.label)) {
state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
@@ -110,10 +111,10 @@
} else {
state.iconId = R.drawable.ic_qs_bluetooth_off;
state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
- stateContentDescription = mContext.getString(R.string.accessibility_desc_off);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_bluetooth_off);
}
- state.contentDescription = mContext.getString(
- R.string.accessibility_quick_settings_bluetooth, stateContentDescription);
+
String bluetoothName = state.label;
if (connected) {
bluetoothName = state.dualLabelContentDescription = mContext.getString(
@@ -122,6 +123,15 @@
state.dualLabelContentDescription = bluetoothName;
}
+ @Override
+ protected String composeChangeAnnouncement() {
+ if (mState.value) {
+ return mContext.getString(R.string.accessibility_quick_settings_bluetooth_changed_on);
+ } else {
+ return mContext.getString(R.string.accessibility_quick_settings_bluetooth_changed_off);
+ }
+ }
+
private final BluetoothController.Callback mCallback = new BluetoothController.Callback() {
@Override
public void onBluetoothStateChange(boolean enabled, boolean connecting) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 6b3e871..6cd0f39 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -110,6 +110,15 @@
mDetailAdapter.updateItems(devices);
}
+ @Override
+ protected String composeChangeAnnouncement() {
+ if (!mState.value) {
+ // We only announce when it's turned off to avoid vocal overflow.
+ return mContext.getString(R.string.accessibility_casting_turned_off);
+ }
+ return null;
+ }
+
private String getDeviceName(CastDevice device) {
return device.name != null ? device.name
: mContext.getString(R.string.quick_settings_cast_device_default_name);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index edb5932..a62bbff 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -88,4 +88,15 @@
state.label = mContext.getString(R.string.quick_settings_inversion_label);
state.iconId = enabled ? R.drawable.ic_qs_inversion_on : R.drawable.ic_qs_inversion_off;
}
+
+ @Override
+ protected String composeChangeAnnouncement() {
+ if (mState.value) {
+ return mContext.getString(
+ R.string.accessibility_quick_settings_color_inversion_changed_on);
+ } else {
+ return mContext.getString(
+ R.string.accessibility_quick_settings_color_inversion_changed_off);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index 3ddf5e3..e6b7f02 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -94,6 +94,19 @@
state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
state.iconId = state.value
? R.drawable.ic_qs_flashlight_on : R.drawable.ic_qs_flashlight_off;
+ int onOrOffId = state.value
+ ? R.string.accessibility_quick_settings_flashlight_on
+ : R.string.accessibility_quick_settings_flashlight_off;
+ state.contentDescription = mContext.getString(onOrOffId);
+ }
+
+ @Override
+ protected String composeChangeAnnouncement() {
+ if (mState.value) {
+ return mContext.getString(R.string.accessibility_quick_settings_flashlight_changed_on);
+ } else {
+ return mContext.getString(R.string.accessibility_quick_settings_flashlight_changed_off);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 96333a3..9984fca 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -74,6 +74,15 @@
: R.drawable.ic_qs_hotspot_off;
}
+ @Override
+ protected String composeChangeAnnouncement() {
+ if (mState.value) {
+ return mContext.getString(R.string.accessibility_quick_settings_hotspot_changed_on);
+ } else {
+ return mContext.getString(R.string.accessibility_quick_settings_hotspot_changed_off);
+ }
+ }
+
private final class Callback implements HotspotController.Callback {
@Override
public void onHotspotChanged(boolean enabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index c4dd643..7ac6644 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -71,14 +71,21 @@
state.iconId = R.drawable.ic_qs_location_on;
state.label = mContext.getString(R.string.quick_settings_location_label);
state.contentDescription = mContext.getString(
- R.string.accessibility_quick_settings_location,
- mContext.getString(R.string.accessibility_desc_on));
+ R.string.accessibility_quick_settings_location_on);
} else {
state.iconId = R.drawable.ic_qs_location_off;
state.label = mContext.getString(R.string.quick_settings_location_label);
state.contentDescription = mContext.getString(
- R.string.accessibility_quick_settings_location,
- mContext.getString(R.string.accessibility_desc_off));
+ R.string.accessibility_quick_settings_location_off);
+ }
+ }
+
+ @Override
+ protected String composeChangeAnnouncement() {
+ if (mState.value) {
+ return mContext.getString(R.string.accessibility_quick_settings_location_changed_on);
+ } else {
+ return mContext.getString(R.string.accessibility_quick_settings_location_changed_off);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index 21cf9ec..ae40a4d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -74,6 +74,38 @@
state.label = mContext.getString(R.string.quick_settings_rotation_unlocked_label);
state.icon = res.getDrawable(R.drawable.ic_qs_rotation_unlocked);
}
+ state.contentDescription = getAccessibilityString(
+ R.string.accessibility_rotation_lock_on_portrait,
+ R.string.accessibility_rotation_lock_on_landscape,
+ R.string.accessibility_rotation_lock_off);
+ }
+
+ /**
+ * Get the correct accessibility string based on the state
+ *
+ * @param idWhenPortrait The id which should be used when locked in portrait.
+ * @param idWhenLandscape The id which should be used when locked in landscape.
+ * @param idWhenOff The id which should be used when the rotation lock is off.
+ * @return
+ */
+ private String getAccessibilityString(int idWhenPortrait, int idWhenLandscape, int idWhenOff) {
+ int stringID;
+ if (mState.value) {
+ final boolean portrait = mContext.getResources().getConfiguration().orientation
+ != Configuration.ORIENTATION_LANDSCAPE;
+ stringID = portrait ? idWhenPortrait: idWhenLandscape;
+ } else {
+ stringID = idWhenOff;
+ }
+ return mContext.getString(stringID);
+ }
+
+ @Override
+ protected String composeChangeAnnouncement() {
+ return getAccessibilityString(
+ R.string.accessibility_rotation_lock_on_portrait_changed,
+ R.string.accessibility_rotation_lock_on_landscape_changed,
+ R.string.accessibility_rotation_lock_off_changed);
}
private final RotationLockControllerCallback mCallback = new RotationLockControllerCallback() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index a8bf026..4fc2ee4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -40,6 +40,7 @@
private final NetworkController mController;
private final WifiDetailAdapter mDetailAdapter;
+ private final QSTile.SignalState mStateBeforeClick = newTileState();
public WifiTile(Host host) {
super(host);
@@ -80,16 +81,13 @@
@Override
protected void handleClick() {
+ mState.copyTo(mStateBeforeClick);
mController.setWifiEnabled(!mState.enabled);
}
@Override
protected void handleSecondaryClick() {
- if (!mState.enabled) {
- mController.setWifiEnabled(true);
- mState.enabled = true;
- }
- showDetail(true);
+ mHost.startSettingsActivity(WIFI_SETTINGS);
}
@Override
@@ -140,6 +138,20 @@
state.dualLabelContentDescription = wifiName;
}
+ @Override
+ protected boolean shouldAnnouncementBeDelayed() {
+ return mStateBeforeClick.enabled == mState.enabled;
+ }
+
+ @Override
+ protected String composeChangeAnnouncement() {
+ if (mState.enabled) {
+ return mContext.getString(R.string.accessibility_quick_settings_wifi_changed_on);
+ } else {
+ return mContext.getString(R.string.accessibility_quick_settings_wifi_changed_off);
+ }
+ }
+
private static String removeDoubleQuotes(String string) {
if (string == null) return null;
final int length = string.length();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index fb77751..5390daf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -71,6 +71,8 @@
public class SystemServicesProxy {
final static String TAG = "SystemServicesProxy";
+ final static BitmapFactory.Options sBitmapOptions;
+
ActivityManager mAm;
IActivityManager mIam;
AppWidgetManager mAwm;
@@ -89,6 +91,11 @@
Paint mBgProtectionPaint;
Canvas mBgProtectionCanvas;
+ static {
+ sBitmapOptions = new BitmapFactory.Options();
+ sBitmapOptions.inMutable = true;
+ }
+
/** Private constructor */
public SystemServicesProxy(Context context) {
mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
@@ -258,7 +265,8 @@
Bitmap thumbnail = taskThumbnail.mainThumbnail;
ParcelFileDescriptor descriptor = taskThumbnail.thumbnailFileDescriptor;
if (thumbnail == null && descriptor != null) {
- thumbnail = BitmapFactory.decodeFileDescriptor(descriptor.getFileDescriptor());
+ thumbnail = BitmapFactory.decodeFileDescriptor(descriptor.getFileDescriptor(),
+ null, sBitmapOptions);
}
if (descriptor != null) {
try {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index c7198fe..d39f64e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -143,7 +143,7 @@
mBackgroundColor = new ColorDrawable(0);
// Copy the ripple drawable since we are going to be manipulating it
mBackground = (RippleDrawable)
- getResources().getDrawable(R.drawable.recents_task_view_header_bg);
+ getContext().getDrawable(R.drawable.recents_task_view_header_bg);
mBackground = (RippleDrawable) mBackground.mutate().getConstantState().newDrawable();
mBackground.setColor(ColorStateList.valueOf(0));
mBackground.setDrawableByLayerId(mBackground.getId(0), mBackgroundColor);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 53bdcbf..e3f034d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1169,8 +1169,8 @@
final ImageView icon = (ImageView) publicViewLocal.findViewById(
com.android.internal.R.id.icon);
- final ImageView profileIcon = (ImageView) publicViewLocal.findViewById(
- com.android.internal.R.id.profile_icon);
+ final ImageView profileBadge = (ImageView) publicViewLocal.findViewById(
+ com.android.internal.R.id.profile_badge_line3);
final StatusBarIcon ic = new StatusBarIcon(entry.notification.getPackageName(),
entry.notification.getUser(),
@@ -1183,17 +1183,20 @@
icon.setImageDrawable(iconDrawable);
if (mNotificationColorUtil.isGrayscale(iconDrawable)) {
icon.setBackgroundResource(
- com.android.internal.R.drawable.notification_icon_legacy_bg_inset);
+ com.android.internal.R.drawable.notification_icon_legacy_bg);
+ int padding = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.notification_large_icon_circle_padding);
+ icon.setPadding(padding, padding, padding, padding);
}
- if (profileIcon != null) {
+ if (profileBadge != null) {
Drawable profileDrawable
= mUserManager.getBadgeForUser(entry.notification.getUser(), 0);
if (profileDrawable != null) {
- profileIcon.setImageDrawable(profileDrawable);
- profileIcon.setVisibility(View.VISIBLE);
+ profileBadge.setImageDrawable(profileDrawable);
+ profileBadge.setVisibility(View.VISIBLE);
} else {
- profileIcon.setVisibility(View.GONE);
+ profileBadge.setVisibility(View.GONE);
}
}
@@ -1214,6 +1217,11 @@
R.style.TextAppearance_StatusBar_Material_EventContent_Parenthetical);
}
+ int topPadding = Notification.Builder.calculateTopPadding(mContext,
+ false /* hasThreeLines */,
+ mContext.getResources().getConfiguration().fontScale);
+ title.setPadding(0, topPadding, 0, 0);
+
entry.autoRedacted = true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DismissViewImageButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/DismissViewImageButton.java
new file mode 100644
index 0000000..d55b0b3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DismissViewImageButton.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
+
+public class DismissViewImageButton extends ImageButton {
+ public DismissViewImageButton(Context context) {
+ super(context);
+ }
+
+ public DismissViewImageButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public DismissViewImageButton(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public DismissViewImageButton(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ /**
+ * This method returns the drawing rect for the view which is different from the regular
+ * drawing rect, since we layout all children in the {@link NotificationStackScrollLayout} at
+ * position 0 and usually the translation is neglected. The standard implementation doesn't
+ * account for translation.
+ *
+ * @param outRect The (scrolled) drawing bounds of the view.
+ */
+ @Override
+ public void getDrawingRect(Rect outRect) {
+ super.getDrawingRect(outRect);
+ float translationX = ((ViewGroup) mParent).getTranslationX();
+ float translationY = ((ViewGroup) mParent).getTranslationY();
+ outRect.left += translationX;
+ outRect.right += translationX;
+ outRect.top += translationY;
+ outRect.bottom += translationY;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 9ac20a6..7d64325 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -120,6 +120,15 @@
return false;
}
+ @Override
+ public void setDark(boolean dark, boolean fade) {
+ super.setDark(dark, fade);
+ final NotificationContentView showing = getShowingLayout();
+ if (showing != null) {
+ showing.setDark(dark, fade);
+ }
+ }
+
public void setHeightRange(int rowMinHeight, int rowMaxHeight) {
mRowMinHeight = rowMinHeight;
mRowMaxHeight = rowMaxHeight;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 127ff6c..5c66660 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -17,12 +17,14 @@
package com.android.systemui.statusbar;
import android.content.Context;
+import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import com.android.systemui.R;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import java.util.ArrayList;
@@ -262,6 +264,24 @@
}
/**
+ * This method returns the drawing rect for the view which is different from the regular
+ * drawing rect, since we layout all children in the {@link NotificationStackScrollLayout} at
+ * position 0 and usually the translation is neglected. Since we are manually clipping this
+ * view,we also need to subtract the clipTopAmount from the top. This is needed in order to
+ * ensure that accessibility and focusing work correctly.
+ *
+ * @param outRect The (scrolled) drawing bounds of the view.
+ */
+ @Override
+ public void getDrawingRect(Rect outRect) {
+ super.getDrawingRect(outRect);
+ outRect.left += getTranslationX();
+ outRect.right += getTranslationX();
+ outRect.bottom = (int) (outRect.top + getTranslationY() + getActualHeight());
+ outRect.top += getTranslationY() + getClipTopAmount();
+ }
+
+ /**
* A listener notifying when {@link #getActualHeight} changes.
*/
public interface OnHeightChangedListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index a030f61..548e7d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -17,15 +17,20 @@
package com.android.systemui.statusbar;
import android.content.Context;
+import android.graphics.ColorFilter;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
+import android.widget.ImageView;
import com.android.systemui.R;
@@ -37,6 +42,8 @@
public class NotificationContentView extends FrameLayout {
private static final long ANIMATION_DURATION_LENGTH = 170;
+ private static final Paint INVERT_PAINT = createInvertPaint();
+ private static final ColorFilter NO_COLOR_FILTER = new ColorFilter();
private final Rect mClipBounds = new Rect();
@@ -50,6 +57,7 @@
private final Interpolator mLinearInterpolator = new LinearInterpolator();
private boolean mContractedVisible = true;
+ private boolean mDark;
private final Paint mFadePaint = new Paint();
@@ -192,4 +200,49 @@
public boolean isContentExpandable() {
return mExpandedChild != null;
}
+
+ public void setDark(boolean dark, boolean fade) {
+ if (mDark == dark) return;
+ mDark = dark;
+ setImageViewDark(dark, fade, com.android.internal.R.id.right_icon);
+ setImageViewDark(dark, fade, com.android.internal.R.id.icon);
+ }
+
+ private void setImageViewDark(boolean dark, boolean fade, int imageViewId) {
+ // TODO: implement fade
+ final ImageView v = (ImageView) mContractedChild.findViewById(imageViewId);
+ final Drawable d = v.getBackground();
+ if (dark) {
+ v.setLayerType(LAYER_TYPE_HARDWARE, INVERT_PAINT);
+ if (d != null) {
+ v.setTag(R.id.doze_saved_filter_tag, d.getColorFilter() != null ? d.getColorFilter()
+ : NO_COLOR_FILTER);
+ d.setColorFilter(getResources().getColor(R.color.doze_small_icon_background_color),
+ PorterDuff.Mode.SRC_ATOP);
+ v.setImageAlpha(getResources().getInteger(R.integer.doze_small_icon_alpha));
+ }
+ } else {
+ v.setLayerType(LAYER_TYPE_NONE, null);
+ if (d != null) {
+ final ColorFilter filter = (ColorFilter) v.getTag(R.id.doze_saved_filter_tag);
+ if (filter != null) {
+ d.setColorFilter(filter == NO_COLOR_FILTER ? null : filter);
+ v.setTag(R.id.doze_saved_filter_tag, null);
+ }
+ v.setImageAlpha(0xff);
+ }
+ }
+ }
+
+ private static Paint createInvertPaint() {
+ final Paint p = new Paint();
+ final float[] invert = {
+ -1f, 0f, 0f, 1f, 1f,
+ 0f, -1f, 0f, 1f, 1f,
+ 0f, 0f, -1f, 1f, 1f,
+ 0f, 0f, 0f, 1f, 0f
+ };
+ p.setColorFilter(new ColorMatrixColorFilter(new ColorMatrix(invert)));
+ return p;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 9408042..7fefa64 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -252,18 +252,21 @@
int N = mSortedAndFiltered.size();
pw.print(indent);
pw.println("active notifications: " + N);
- for (int i = 0; i < N; i++) {
- NotificationData.Entry e = mSortedAndFiltered.get(i);
- dumpEntry(pw, indent, i, e);
+ int active;
+ for (active = 0; active < N; active++) {
+ NotificationData.Entry e = mSortedAndFiltered.get(active);
+ dumpEntry(pw, indent, active, e);
}
int M = mEntries.size();
pw.print(indent);
- pw.println("inactive notifications: " + M);
+ pw.println("inactive notifications: " + (M - active));
+ int inactiveCount = 0;
for (int i = 0; i < M; i++) {
Entry entry = mEntries.valueAt(i);
if (!mSortedAndFiltered.contains(entry)) {
- dumpEntry(pw, indent, i, entry);
+ dumpEntry(pw, indent, inactiveCount, entry);
+ inactiveCount++;
}
}
}
@@ -273,8 +276,8 @@
pw.println(" [" + i + "] key=" + e.key + " icon=" + e.icon);
StatusBarNotification n = e.notification;
pw.print(indent);
- pw.println(" pkg=" + n.getPackageName() + " id=" + n.getId() + " score=" + n
- .getScore());
+ pw.println(" pkg=" + n.getPackageName() + " id=" + n.getId() + " score=" +
+ n.getScore());
pw.print(indent);
pw.println(" notification=" + n.getNotification());
pw.print(indent);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 3e2a398..cb2d40a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -26,6 +26,7 @@
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.os.AsyncTask;
+import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.phone.PhoneManager;
@@ -36,7 +37,7 @@
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.TextView;
@@ -44,17 +45,23 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.R;
-import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.policy.FlashlightController;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardAffordanceView;
+import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.policy.AccessibilityController;
+import com.android.systemui.statusbar.policy.FlashlightController;
import com.android.systemui.statusbar.policy.PreviewInflater;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
+import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+
/**
* Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
* text.
*/
public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener,
- UnlockMethodCache.OnUnlockMethodChangedListener {
+ UnlockMethodCache.OnUnlockMethodChangedListener,
+ AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener {
final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView";
@@ -80,25 +87,63 @@
private FlashlightController mFlashlightController;
private PreviewInflater mPreviewInflater;
private KeyguardIndicationController mIndicationController;
- private boolean mFaceUnlockRunning;
+ private AccessibilityController mAccessibilityController;
+ private PhoneStatusBar mPhoneStatusBar;
+
+ private final TrustDrawable mTrustDrawable;
public KeyguardBottomAreaView(Context context) {
- super(context);
+ this(context, null);
}
public KeyguardBottomAreaView(Context context, AttributeSet attrs) {
- super(context, attrs);
+ this(context, attrs, 0);
}
public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
+ this(context, attrs, defStyleAttr, 0);
}
public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ mTrustDrawable = new TrustDrawable(mContext);
}
+ private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() {
+ @Override
+ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(host, info);
+ String label = null;
+ if (host == mLockIcon) {
+ label = getResources().getString(R.string.unlock_label);
+ } else if (host == mCameraImageView) {
+ label = getResources().getString(R.string.camera_label);
+ } else if (host == mPhoneImageView) {
+ label = getResources().getString(R.string.phone_label);
+ }
+ info.addAction(new AccessibilityAction(ACTION_CLICK, label));
+ }
+
+ @Override
+ public boolean performAccessibilityAction(View host, int action, Bundle args) {
+ if (action == ACTION_CLICK) {
+ if (host == mLockIcon) {
+ mPhoneStatusBar.animateCollapsePanels(
+ CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
+ return true;
+ } else if (host == mCameraImageView) {
+ launchCamera();
+ return true;
+ } else if (host == mPhoneImageView) {
+ launchPhone();
+ return true;
+ }
+ }
+ return super.performAccessibilityAction(host, action, args);
+ }
+ };
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
@@ -109,7 +154,6 @@
mLockIcon = (KeyguardAffordanceView) findViewById(R.id.lock_icon);
mIndicationText = (TextView) findViewById(R.id.keyguard_indication_text);
watchForCameraPolicyChanges();
- watchForAccessibilityChanges();
updateCameraVisibility();
updatePhoneVisibility();
mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
@@ -120,6 +164,17 @@
mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext));
inflatePreviews();
mLockIcon.setOnClickListener(this);
+ mLockIcon.setBackground(mTrustDrawable);
+ mLockIcon.setOnLongClickListener(this);
+ mCameraImageView.setOnClickListener(this);
+ mPhoneImageView.setOnClickListener(this);
+ initAccessibility();
+ }
+
+ private void initAccessibility() {
+ mLockIcon.setAccessibilityDelegate(mAccessibilityDelegate);
+ mPhoneImageView.setAccessibilityDelegate(mAccessibilityDelegate);
+ mCameraImageView.setAccessibilityDelegate(mAccessibilityDelegate);
}
@Override
@@ -147,6 +202,15 @@
mFlashlightController = flashlightController;
}
+ public void setAccessibilityController(AccessibilityController accessibilityController) {
+ mAccessibilityController = accessibilityController;
+ accessibilityController.addStateChangedCallback(this);
+ }
+
+ public void setPhoneStatusBar(PhoneStatusBar phoneStatusBar) {
+ mPhoneStatusBar = phoneStatusBar;
+ }
+
private Intent getCameraIntent() {
KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
boolean currentUserHasTrust = updateMonitor.getUserHasTrust(
@@ -200,28 +264,24 @@
KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
}
- private void watchForAccessibilityChanges() {
- final AccessibilityManager am =
- (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
-
- // Set the initial state
- enableAccessibility(am.isTouchExplorationEnabled());
-
- // Watch for changes
- am.addTouchExplorationStateChangeListener(
- new AccessibilityManager.TouchExplorationStateChangeListener() {
- @Override
- public void onTouchExplorationStateChanged(boolean enabled) {
- enableAccessibility(enabled);
- }
- });
+ @Override
+ public void onStateChanged(boolean accessibilityEnabled, boolean touchExplorationEnabled) {
+ mCameraImageView.setClickable(touchExplorationEnabled);
+ mPhoneImageView.setClickable(touchExplorationEnabled);
+ mCameraImageView.setFocusable(accessibilityEnabled);
+ mPhoneImageView.setFocusable(accessibilityEnabled);
+ updateLockIconClickability();
}
- private void enableAccessibility(boolean touchExplorationEnabled) {
- mCameraImageView.setOnClickListener(touchExplorationEnabled ? this : null);
- mCameraImageView.setClickable(touchExplorationEnabled);
- mPhoneImageView.setOnClickListener(touchExplorationEnabled ? this : null);
- mPhoneImageView.setClickable(touchExplorationEnabled);
+ private void updateLockIconClickability() {
+ if (mAccessibilityController == null) {
+ return;
+ }
+ mLockIcon.setClickable(mUnlockMethodCache.isTrustManaged()
+ || mAccessibilityController.isTouchExplorationEnabled());
+ mLockIcon.setLongClickable(mAccessibilityController.isTouchExplorationEnabled()
+ && mUnlockMethodCache.isTrustManaged());
+ mLockIcon.setFocusable(mAccessibilityController.isAccessibilityEnabled());
}
@Override
@@ -231,12 +291,27 @@
} else if (v == mPhoneImageView) {
launchPhone();
} if (v == mLockIcon) {
- mIndicationController.showTransientIndication(
- R.string.keyguard_indication_trust_disabled);
- mLockPatternUtils.requireCredentialEntry(mLockPatternUtils.getCurrentUser());
+ if (!mAccessibilityController.isAccessibilityEnabled()) {
+ handleTrustCircleClick();
+ } else {
+ mPhoneStatusBar.animateCollapsePanels(
+ CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
+ }
}
}
+ @Override
+ public boolean onLongClick(View v) {
+ handleTrustCircleClick();
+ return true;
+ }
+
+ private void handleTrustCircleClick() {
+ mIndicationController.showTransientIndication(
+ R.string.keyguard_indication_trust_disabled);
+ mLockPatternUtils.requireCredentialEntry(mLockPatternUtils.getCurrentUser());
+ }
+
public void launchCamera() {
mFlashlightController.killFlashlight();
Intent intent = getCameraIntent();
@@ -267,25 +342,54 @@
@Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
+ if (isShown()) {
+ mTrustDrawable.start();
+ } else {
+ mTrustDrawable.stop();
+ }
if (changedView == this && visibility == VISIBLE) {
updateLockIcon();
updateCameraVisibility();
}
}
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mTrustDrawable.stop();
+ }
+
private void updateLockIcon() {
- if (getVisibility() != VISIBLE) {
+ boolean visible = isShown() && KeyguardUpdateMonitor.getInstance(mContext).isScreenOn();
+ if (visible) {
+ mTrustDrawable.start();
+ } else {
+ mTrustDrawable.stop();
+ }
+ if (!visible) {
return;
}
// TODO: Real icon for facelock.
- int iconRes = mFaceUnlockRunning ? R.drawable.ic_account_circle
+ int iconRes = mUnlockMethodCache.isFaceUnlockRunning() ? R.drawable.ic_account_circle
: mUnlockMethodCache.isMethodInsecure() ? R.drawable.ic_lock_open_24dp
: R.drawable.ic_lock_24dp;
mLockIcon.setImageResource(iconRes);
boolean trustManaged = mUnlockMethodCache.isTrustManaged();
- mLockIcon.setBackgroundResource(trustManaged && !mFaceUnlockRunning
- ? R.drawable.trust_circle : 0);
- mLockIcon.setClickable(trustManaged);
+ mTrustDrawable.setTrustManaged(trustManaged);
+
+ updateLockIconClickability();
+ updateLockIconContentDescription(mUnlockMethodCache.isFaceUnlockRunning(),
+ mUnlockMethodCache.isMethodInsecure(), trustManaged);
+ }
+
+ private void updateLockIconContentDescription(boolean faceUnlockRunning, boolean insecure,
+ boolean trustManaged) {
+ mLockIcon.setContentDescription(getResources().getString(
+ faceUnlockRunning ? R.string.accessibility_unlock_button_face_unlock_running
+ : insecure && !trustManaged ? R.string.accessibility_unlock_button_not_secured
+ : insecure ? R.string.accessibility_unlock_button_not_secured_trust_managed
+ : !trustManaged ? R.string.accessibility_unlock_button_secured
+ : R.string.accessibility_unlock_button_secured_trust_managed));
}
public KeyguardAffordanceView getPhoneView() {
@@ -355,8 +459,12 @@
}
@Override
- public void onFaceUnlockStateChanged(boolean running) {
- mFaceUnlockRunning = running;
+ public void onScreenTurnedOn() {
+ updateLockIcon();
+ }
+
+ @Override
+ public void onScreenTurnedOff(int why) {
updateLockIcon();
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 5e5c3aa..650a14f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -30,6 +30,7 @@
import android.widget.RelativeLayout;
import android.widget.TextView;
+import com.android.systemui.BatteryMeterView;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
@@ -135,6 +136,7 @@
public void setBatteryController(BatteryController batteryController) {
mBatteryController = batteryController;
+ ((BatteryMeterView) findViewById(R.id.battery)).setBatteryController(batteryController);
}
public void setUserInfoController(UserInfoController userInfoController) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 9188457..e1beb08 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -182,6 +182,7 @@
mClockView = (TextView) findViewById(R.id.clock_view);
mScrollView = (ObservableScrollView) findViewById(R.id.scroll_view);
mScrollView.setListener(this);
+ mScrollView.setFocusable(false);
mReserveNotificationSpace = findViewById(R.id.reserve_notification_space);
mNotificationContainerParent = findViewById(R.id.notification_container_parent);
mNotificationStackScroller = (NotificationStackScrollLayout)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index decf231..7158ba1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -109,6 +109,7 @@
import com.android.internal.statusbar.StatusBarIcon;
import com.android.keyguard.KeyguardHostView.OnDismissAction;
import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.BatteryMeterView;
import com.android.systemui.DemoMode;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
@@ -131,6 +132,7 @@
import com.android.systemui.statusbar.SpeedBumpView;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.policy.AccessibilityController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
@@ -236,6 +238,7 @@
NextAlarmController mNextAlarmController;
KeyguardMonitor mKeyguardMonitor;
BrightnessMirrorController mBrightnessMirrorController;
+ AccessibilityController mAccessibilityController;
int mNaturalBarHeight = -1;
int mIconSize = -1;
@@ -749,6 +752,9 @@
@Override
public void onPowerSaveChanged() {
mHandler.post(mCheckBarModes);
+ if (mDozeServiceHost != null) {
+ mDozeServiceHost.firePowerSaveChanged(mBatteryController.isPowerSave());
+ }
}
@Override
public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
@@ -804,6 +810,9 @@
mFlashlightController = new FlashlightController(mContext);
mKeyguardBottomArea.setFlashlightController(mFlashlightController);
+ mKeyguardBottomArea.setPhoneStatusBar(this);
+ mAccessibilityController = new AccessibilityController(mContext);
+ mKeyguardBottomArea.setAccessibilityController(mAccessibilityController);
mNextAlarmController = new NextAlarmController(mContext);
mKeyguardMonitor = new KeyguardMonitor();
mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor);
@@ -845,6 +854,8 @@
mUserInfoController.reloadUserInfo();
mHeader.setBatteryController(mBatteryController);
+ ((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)).setBatteryController(
+ mBatteryController);
mKeyguardStatusBar.setBatteryController(mBatteryController);
mHeader.setNextAlarmController(mNextAlarmController);
@@ -1346,7 +1357,7 @@
updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
if (CLOSE_PANEL_WHEN_EMPTIED && !hasActiveNotifications()
- && !mNotificationPanel.isTracking()) {
+ && !mNotificationPanel.isTracking() && !mNotificationPanel.isQsExpanded()) {
if (mState == StatusBarState.SHADE) {
animateCollapsePanels();
} else if (mState == StatusBarState.SHADE_LOCKED) {
@@ -2123,6 +2134,7 @@
// Expand the window to encompass the full screen in anticipation of the drag.
// This is only possible to do atomically because the status bar is at the top of the screen!
mStatusBarWindowManager.setStatusBarExpanded(true);
+ mStatusBarView.setFocusable(false);
visibilityChanged(true);
mWaitingForKeyguardExit = false;
@@ -2297,6 +2309,7 @@
// Shrink the window to the size of the status bar only
mStatusBarWindowManager.setStatusBarExpanded(false);
+ mStatusBarView.setFocusable(true);
// Close any "App info" popups that might have snuck on-screen
dismissPopups();
@@ -3912,6 +3925,12 @@
private DozeService mCurrentDozeService;
+ public void firePowerSaveChanged(boolean active) {
+ for (Callback callback : mCallbacks) {
+ callback.onPowerSaveChanged(active);
+ }
+ }
+
public void fireBuzzBeepBlinked() {
for (Callback callback : mCallbacks) {
callback.onBuzzBeepBlinked();
@@ -3962,6 +3981,11 @@
mHandler.obtainMessage(H.DOZING_STOPPED, dozeService).sendToTarget();
}
+ @Override
+ public boolean isPowerSaveActive() {
+ return mBatteryController != null && mBatteryController.isPowerSave();
+ }
+
private void handleRequestDoze(DozeService dozeService) {
mCurrentDozeService = dozeService;
if (!mDozing) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 807a37b..3a110bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -114,6 +114,7 @@
private final LayoutValues mCurrentValues = new LayoutValues();
private float mCurrentT;
+ private boolean mShowingDetail;
public StatusBarHeaderView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -282,7 +283,7 @@
mDateExpanded.setVisibility(mExpanded && mAlarmShowing ? View.INVISIBLE : View.VISIBLE);
mAlarmStatus.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
mSettingsButton.setVisibility(mExpanded ? View.VISIBLE : View.INVISIBLE);
- mQsDetailHeader.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
+ mQsDetailHeader.setVisibility(mExpanded && mShowingDetail? View.VISIBLE : View.INVISIBLE);
if (mSignalCluster != null) {
updateSignalClusterDetachment();
}
@@ -375,7 +376,9 @@
private void updateClickTargets() {
mMultiUserSwitch.setClickable(mExpanded);
+ mMultiUserSwitch.setFocusable(mExpanded);
mSystemIconsSuperContainer.setClickable(mExpanded);
+ mSystemIconsSuperContainer.setFocusable(mExpanded);
mAlarmStatus.setClickable(mNextAlarm != null && mNextAlarm.getShowIntent() != null);
}
@@ -716,6 +719,7 @@
transition(mDateGroup, !showingDetail);
transition(mAlarmStatus, !showingDetail);
transition(mQsDetailHeader, showingDetail);
+ mShowingDetail = showingDetail;
if (showingDetail) {
mQsDetailHeaderTitle.setText(detail.getTitle());
final Boolean toggleState = detail.getToggleState();
@@ -741,8 +745,20 @@
private void transition(final View v, final boolean in) {
if (in) {
v.bringToFront();
+ v.setVisibility(VISIBLE);
}
- v.animate().alpha(in ? 1 : 0).withLayer().start();
+ v.animate()
+ .alpha(in ? 1 : 0)
+ .withLayer()
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ if (!in) {
+ v.setVisibility(INVISIBLE);
+ }
+ }
+ })
+ .start();
}
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java
new file mode 100644
index 0000000..dcda2c7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import com.android.systemui.R;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+
+public class TrustDrawable extends Drawable {
+
+ private static final long ENTERING_FROM_UNSET_START_DELAY = 200;
+ private static final long VISIBLE_DURATION = 1000;
+ private static final long EXIT_DURATION = 500;
+ private static final long ENTER_DURATION = 500;
+
+ private static final int ALPHA_VISIBLE_MIN = 0x26;
+ private static final int ALPHA_VISIBLE_MAX = 0x4c;
+
+ private static final int STATE_UNSET = -1;
+ private static final int STATE_GONE = 0;
+ private static final int STATE_ENTERING = 1;
+ private static final int STATE_VISIBLE = 2;
+ private static final int STATE_EXITING = 3;
+
+ private int mAlpha;
+ private boolean mAnimating;
+
+ private int mCurAlpha;
+ private float mCurInnerRadius;
+ private Animator mCurAnimator;
+ private int mState = STATE_UNSET;
+ private Paint mPaint;
+ private boolean mTrustManaged;
+
+ private final float mInnerRadiusVisibleMin;
+ private final float mInnerRadiusVisibleMax;
+ private final float mInnerRadiusExit;
+ private final float mInnerRadiusEnter;
+ private final float mThickness;
+
+ private final Animator mVisibleAnimator;
+
+ private final Interpolator mLinearOutSlowInInterpolator;
+ private final Interpolator mFastOutSlowInInterpolator;
+ private final Interpolator mAccelerateDecelerateInterpolator;
+
+ public TrustDrawable(Context context) {
+ Resources r = context.getResources();
+ mInnerRadiusVisibleMin = r.getDimension(R.dimen.trust_circle_inner_radius_visible_min);
+ mInnerRadiusVisibleMax = r.getDimension(R.dimen.trust_circle_inner_radius_visible_max);
+ mInnerRadiusExit = r.getDimension(R.dimen.trust_circle_inner_radius_exit);
+ mInnerRadiusEnter = r.getDimension(R.dimen.trust_circle_inner_radius_enter);
+ mThickness = r.getDimension(R.dimen.trust_circle_thickness);
+
+ mCurInnerRadius = mInnerRadiusEnter;
+
+ mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(
+ context, android.R.interpolator.linear_out_slow_in);
+ mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(
+ context, android.R.interpolator.fast_out_slow_in);
+ mAccelerateDecelerateInterpolator = new AccelerateDecelerateInterpolator();
+
+ mVisibleAnimator = makeVisibleAnimator();
+
+ mPaint = new Paint();
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setColor(Color.WHITE);
+ mPaint.setAntiAlias(true);
+ mPaint.setStrokeWidth(mThickness);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ int newAlpha = (mCurAlpha * mAlpha) / 256;
+ if (newAlpha == 0) {
+ return;
+ }
+ final Rect r = getBounds();
+ mPaint.setAlpha(newAlpha);
+ canvas.drawCircle(r.exactCenterX(), r.exactCenterY(), mCurInnerRadius, mPaint);
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ mAlpha = alpha;
+ }
+
+ @Override
+ public int getAlpha() {
+ return mAlpha;
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ public void start() {
+ if (!mAnimating) {
+ mAnimating = true;
+ updateState(true);
+ }
+ }
+
+ public void stop() {
+ if (mAnimating) {
+ mAnimating = false;
+ if (mCurAnimator != null) {
+ mCurAnimator.cancel();
+ mCurAnimator = null;
+ }
+ mState = STATE_UNSET;
+ mCurAlpha = 0;
+ mCurInnerRadius = mInnerRadiusEnter;
+ }
+ }
+
+ public void setTrustManaged(boolean trustManaged) {
+ if (trustManaged == mTrustManaged && mState != STATE_UNSET) return;
+ mTrustManaged = trustManaged;
+ if (mAnimating) {
+ updateState(true);
+ }
+ }
+
+ private void updateState(boolean animate) {
+ int nextState = mState;
+ if (mState == STATE_UNSET) {
+ nextState = mTrustManaged ? STATE_ENTERING : STATE_GONE;
+ } else if (mState == STATE_GONE) {
+ if (mTrustManaged) nextState = STATE_ENTERING;
+ } else if (mState == STATE_ENTERING) {
+ if (!mTrustManaged) nextState = STATE_EXITING;
+ } else if (mState == STATE_VISIBLE) {
+ if (!mTrustManaged) nextState = STATE_EXITING;
+ } else if (mState == STATE_EXITING) {
+ if (mTrustManaged) nextState = STATE_ENTERING;
+ }
+ if (!animate) {
+ if (nextState == STATE_ENTERING) nextState = STATE_VISIBLE;
+ if (nextState == STATE_EXITING) nextState = STATE_GONE;
+ }
+
+ if (nextState != mState) {
+ if (mCurAnimator != null) {
+ mCurAnimator.cancel();
+ mCurAnimator = null;
+ }
+
+ if (nextState == STATE_GONE) {
+ mCurAlpha = 0;
+ mCurInnerRadius = mInnerRadiusEnter;
+ } else if (nextState == STATE_ENTERING) {
+ mCurAnimator = makeEnterAnimator(mCurInnerRadius, mCurAlpha);
+ if (mState == STATE_UNSET) {
+ mCurAnimator.setStartDelay(ENTERING_FROM_UNSET_START_DELAY);
+ }
+ } else if (nextState == STATE_VISIBLE) {
+ mCurAlpha = ALPHA_VISIBLE_MAX;
+ mCurInnerRadius = mInnerRadiusVisibleMax;
+ mCurAnimator = mVisibleAnimator;
+ } else if (nextState == STATE_EXITING) {
+ mCurAnimator = makeExitAnimator(mCurInnerRadius, mCurAlpha);
+ }
+
+ mState = nextState;
+ if (mCurAnimator != null) {
+ mCurAnimator.start();
+ } else {
+ invalidateSelf();
+ }
+ }
+ }
+
+ private Animator makeVisibleAnimator() {
+ return makeAnimators(mInnerRadiusVisibleMax, mInnerRadiusVisibleMin,
+ ALPHA_VISIBLE_MAX, ALPHA_VISIBLE_MIN, VISIBLE_DURATION,
+ mAccelerateDecelerateInterpolator,
+ true /* repeating */, false /* stateUpdateListener */);
+ }
+
+ private Animator makeEnterAnimator(float radius, int alpha) {
+ return makeAnimators(radius, mInnerRadiusVisibleMax,
+ alpha, ALPHA_VISIBLE_MAX, ENTER_DURATION, mLinearOutSlowInInterpolator,
+ false /* repeating */, true /* stateUpdateListener */);
+ }
+
+ private Animator makeExitAnimator(float radius, int alpha) {
+ return makeAnimators(radius, mInnerRadiusExit,
+ alpha, 0, EXIT_DURATION, mFastOutSlowInInterpolator,
+ false /* repeating */, true /* stateUpdateListener */);
+ }
+
+ private Animator makeAnimators(float startRadius, float endRadius,
+ int startAlpha, int endAlpha, long duration, Interpolator interpolator,
+ boolean repeating, boolean stateUpdateListener) {
+ ValueAnimator alphaAnimator = configureAnimator(
+ ValueAnimator.ofInt(startAlpha, endAlpha),
+ duration, mAlphaUpdateListener, interpolator, repeating);
+ ValueAnimator sizeAnimator = configureAnimator(
+ ValueAnimator.ofFloat(startRadius, endRadius),
+ duration, mRadiusUpdateListener, interpolator, repeating);
+
+ AnimatorSet set = new AnimatorSet();
+ set.playTogether(alphaAnimator, sizeAnimator);
+ if (stateUpdateListener) {
+ set.addListener(new StateUpdateAnimatorListener());
+ }
+ return set;
+ }
+
+ private ValueAnimator configureAnimator(ValueAnimator animator, long duration,
+ ValueAnimator.AnimatorUpdateListener updateListener, Interpolator interpolator,
+ boolean repeating) {
+ animator.setDuration(duration);
+ animator.addUpdateListener(updateListener);
+ animator.setInterpolator(interpolator);
+ if (repeating) {
+ animator.setRepeatCount(ValueAnimator.INFINITE);
+ animator.setRepeatMode(ValueAnimator.REVERSE);
+ }
+ return animator;
+ }
+
+ private final ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener =
+ new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ mCurAlpha = (int) animation.getAnimatedValue();
+ invalidateSelf();
+ }
+ };
+
+ private final ValueAnimator.AnimatorUpdateListener mRadiusUpdateListener =
+ new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ mCurInnerRadius = (float) animation.getAnimatedValue();
+ invalidateSelf();
+ }
+ };
+
+ private class StateUpdateAnimatorListener extends AnimatorListenerAdapter {
+ boolean mCancelled;
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mCancelled = false;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCancelled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!mCancelled) {
+ updateState(false);
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
index 58196f7..e5eef9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -38,6 +38,7 @@
private final ArrayList<OnUnlockMethodChangedListener> mListeners = new ArrayList<>();
private boolean mMethodInsecure;
private boolean mTrustManaged;
+ private boolean mFaceUnlockRunning;
private UnlockMethodCache(Context ctx) {
mLockPatternUtils = new LockPatternUtils(ctx);
@@ -73,10 +74,14 @@
boolean methodInsecure = !mLockPatternUtils.isSecure() ||
mKeyguardUpdateMonitor.getUserHasTrust(user);
boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user);
- boolean changed = methodInsecure != mMethodInsecure || trustManaged != mTrustManaged;
+ boolean faceUnlockRunning = mKeyguardUpdateMonitor.isFaceUnlockRunning(user)
+ && trustManaged;
+ boolean changed = methodInsecure != mMethodInsecure || trustManaged != mTrustManaged
+ || faceUnlockRunning != mFaceUnlockRunning;
if (changed || updateAlways) {
mMethodInsecure = methodInsecure;
mTrustManaged = trustManaged;
+ mFaceUnlockRunning = faceUnlockRunning;
notifyListeners(mMethodInsecure);
}
}
@@ -112,12 +117,21 @@
public void onFingerprintRecognized(int userId) {
updateMethodSecure(false /* updateAlways */);
}
+
+ @Override
+ public void onFaceUnlockStateChanged(boolean running, int userId) {
+ updateMethodSecure(false /* updateAlways */);
+ }
};
public boolean isTrustManaged() {
return mTrustManaged;
}
+ public boolean isFaceUnlockRunning() {
+ return mFaceUnlockRunning;
+ }
+
public static interface OnUnlockMethodChangedListener {
void onMethodSecureChanged(boolean methodSecure);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityController.java
new file mode 100644
index 0000000..89ed787
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityController.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.accessibility.AccessibilityManager;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+public class AccessibilityController implements
+ AccessibilityManager.AccessibilityStateChangeListener,
+ AccessibilityManager.TouchExplorationStateChangeListener {
+
+ private final ArrayList<AccessibilityStateChangedCallback> mChangeCallbacks = new ArrayList<>();
+
+ private boolean mAccessibilityEnabled;
+ private boolean mTouchExplorationEnabled;
+
+ public AccessibilityController(Context context) {
+ AccessibilityManager am =
+ (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
+ am.addTouchExplorationStateChangeListener(this);
+ am.addAccessibilityStateChangeListener(this);
+ mAccessibilityEnabled = am.isEnabled();
+ mTouchExplorationEnabled = am.isTouchExplorationEnabled();
+ }
+
+ public boolean isAccessibilityEnabled() {
+ return mAccessibilityEnabled;
+ }
+
+ public boolean isTouchExplorationEnabled() {
+ return mTouchExplorationEnabled;
+ }
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("AccessibilityController state:");
+ pw.print(" mAccessibilityEnabled="); pw.println(mAccessibilityEnabled);
+ pw.print(" mTouchExplorationEnabled="); pw.println(mTouchExplorationEnabled);
+ }
+
+ public void addStateChangedCallback(AccessibilityStateChangedCallback cb) {
+ mChangeCallbacks.add(cb);
+ cb.onStateChanged(mAccessibilityEnabled, mTouchExplorationEnabled);
+ }
+
+ public void removeStateChangedCallback(AccessibilityStateChangedCallback cb) {
+ mChangeCallbacks.remove(cb);
+ }
+
+ private void fireChanged() {
+ final int N = mChangeCallbacks.size();
+ for (int i = 0; i < N; i++) {
+ mChangeCallbacks.get(i).onStateChanged(mAccessibilityEnabled, mTouchExplorationEnabled);
+ }
+ }
+
+ @Override
+ public void onAccessibilityStateChanged(boolean enabled) {
+ mAccessibilityEnabled = enabled;
+ fireChanged();
+ }
+
+ @Override
+ public void onTouchExplorationStateChanged(boolean enabled) {
+ mTouchExplorationEnabled = enabled;
+ fireChanged();
+ }
+
+ public interface AccessibilityStateChangedCallback {
+ void onStateChanged(boolean accessibilityEnabled, boolean touchExplorationEnabled);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
index ede8129..3a5a53b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
@@ -23,8 +23,7 @@
String getVpnApp();
boolean isLegacyVpn();
String getLegacyVpnName();
- void openVpnApp();
- void disconnectFromLegacyVpn();
+ void disconnectFromVpn();
void addCallback(VpnCallback callback);
void removeCallback(VpnCallback callback);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index 8e04e5e..499fe0b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -17,12 +17,11 @@
import android.app.admin.DevicePolicyManager;
import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.IConnectivityManager;
+import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.RemoteException;
@@ -46,6 +45,8 @@
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
.build();
+ private static final int NO_NETWORK = -1;
+
private final Context mContext;
private final ConnectivityManager mConnectivityManager;
private final IConnectivityManager mConnectivityService = IConnectivityManager.Stub.asInterface(
@@ -53,9 +54,9 @@
private final DevicePolicyManager mDevicePolicyManager;
private final ArrayList<VpnCallback> mCallbacks = new ArrayList<VpnCallback>();
- private boolean mIsVpnEnabled;
private VpnConfig mVpnConfig;
private String mVpnName;
+ private int mCurrentVpnNetworkId = NO_NETWORK;
public SecurityControllerImpl(Context context) {
mContext = context;
@@ -70,7 +71,7 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("SecurityController state:");
- pw.print(" mIsVpnEnabled="); pw.println(mIsVpnEnabled);
+ pw.print(" mCurrentVpnNetworkId="); pw.println(mCurrentVpnNetworkId);
pw.print(" mVpnConfig="); pw.println(mVpnConfig);
pw.print(" mVpnName="); pw.println(mVpnName);
}
@@ -87,10 +88,7 @@
@Override
public boolean isVpnEnabled() {
- // TODO: Remove once using NetworkCallback for updates.
- updateState();
-
- return mIsVpnEnabled;
+ return mCurrentVpnNetworkId != NO_NETWORK;
}
@Override
@@ -109,18 +107,17 @@
}
@Override
- public void openVpnApp() {
- Intent i = mContext.getPackageManager().getLaunchIntentForPackage(mVpnConfig.user);
- if (i != null) {
- i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(i);
- }
- }
-
- @Override
- public void disconnectFromLegacyVpn() {
+ public void disconnectFromVpn() {
try {
- mConnectivityService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN);
+ if (isLegacyVpn()) {
+ mConnectivityService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN);
+ } else {
+ // Prevent this app from initiating VPN connections in the future without user
+ // intervention.
+ mConnectivityService.setVpnPackageAuthorization(false);
+
+ mConnectivityService.prepareVpn(mVpnConfig.user, VpnConfig.LEGACY_VPN);
+ }
} catch (Exception e) {
Log.e(TAG, "Unable to disconnect from VPN", e);
}
@@ -140,6 +137,14 @@
mCallbacks.add(callback);
}
+ private void setCurrentNetid(int netId) {
+ if (netId != mCurrentVpnNetworkId) {
+ mCurrentVpnNetworkId = netId;
+ updateState();
+ fireCallbacks();
+ }
+ }
+
private void fireCallbacks() {
for (VpnCallback callback : mCallbacks) {
callback.onVpnStateChanged();
@@ -150,13 +155,8 @@
try {
mVpnConfig = mConnectivityService.getVpnConfig();
- // TODO: Remove once using NetworkCallback for updates.
- mIsVpnEnabled = mVpnConfig != null;
-
if (mVpnConfig != null && !mVpnConfig.legacy) {
- ApplicationInfo info =
- mContext.getPackageManager().getApplicationInfo(mVpnConfig.user, 0);
- mVpnName = mContext.getPackageManager().getApplicationLabel(info).toString();
+ mVpnName = VpnConfig.getVpnLabel(mContext, mVpnConfig.user).toString();
}
} catch (RemoteException | NameNotFoundException e) {
Log.w(TAG, "Unable to get current VPN", e);
@@ -164,13 +164,25 @@
}
private final NetworkCallback mNetworkCallback = new NetworkCallback() {
- public void onCapabilitiesChanged(android.net.Network network,
- android.net.NetworkCapabilities networkCapabilities) {
- if (DEBUG) Log.d(TAG, "onCapabilitiesChanged " + networkCapabilities);
- mIsVpnEnabled = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
- updateState();
- fireCallbacks();
- }
+ @Override
+ public void onAvailable(Network network) {
+ NetworkCapabilities networkCapabilities =
+ mConnectivityManager.getNetworkCapabilities(network);
+ if (DEBUG) Log.d(TAG, "onAvailable " + network.netId + " : " + networkCapabilities);
+ if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
+ setCurrentNetid(network.netId);
+ }
+ };
+
+ // TODO Find another way to receive VPN lost. This may be delayed depending on
+ // how long the VPN connection is held on to.
+ @Override
+ public void onLost(Network network) {
+ if (DEBUG) Log.d(TAG, "onLost " + network.netId);
+ if (mCurrentVpnNetworkId == network.netId) {
+ setCurrentNetid(NO_NETWORK);
+ }
+ };
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index d53aa47..735fbfc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -158,8 +158,9 @@
picture = BitmapHelper.createCircularClip(
picture, avatarSize, avatarSize);
}
- records.add(new UserRecord(info, picture, false /* isGuest */, isCurrent,
- false /* isAddUser */, false /* isRestricted */));
+ int index = isCurrent ? 0 : records.size();
+ records.add(index, new UserRecord(info, picture, false /* isGuest */,
+ isCurrent, false /* isAddUser */, false /* isRestricted */));
}
}
@@ -182,7 +183,8 @@
false /* isAddUser */, createIsRestricted));
}
} else {
- records.add(guestRecord);
+ int index = guestRecord.isCurrent ? 0 : records.size();
+ records.add(index, guestRecord);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index 51876b8..8a14288 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -37,7 +37,7 @@
import android.media.ToneGenerator;
import android.media.VolumeProvider;
import android.media.session.MediaController;
-import android.media.session.MediaController.AudioInfo;
+import android.media.session.MediaController.PlaybackInfo;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
@@ -537,7 +537,7 @@
if (mStreamControls != null) {
StreamControl sc = mStreamControls.get(streamType);
if (sc != null && sc.controller != null) {
- AudioInfo ai = sc.controller.getAudioInfo();
+ PlaybackInfo ai = sc.controller.getPlaybackInfo();
return ai.getMaxVolume();
}
}
@@ -554,7 +554,7 @@
if (mStreamControls != null) {
StreamControl sc = mStreamControls.get(streamType);
if (sc != null && sc.controller != null) {
- AudioInfo ai = sc.controller.getAudioInfo();
+ PlaybackInfo ai = sc.controller.getPlaybackInfo();
return ai.getCurrentVolume();
}
}
@@ -990,7 +990,7 @@
// We still don't have one, ignore the command.
Log.w(mTag, "sent remote volume change without a controller!");
} else {
- AudioInfo vi = controller.getAudioInfo();
+ PlaybackInfo vi = controller.getPlaybackInfo();
index = vi.getCurrentVolume();
max = vi.getMaxVolume();
if ((vi.getVolumeControl() & VolumeProvider.VOLUME_CONTROL_FIXED) != 0) {
@@ -1362,7 +1362,7 @@
};
private final MediaController.Callback mMediaControllerCb = new MediaController.Callback() {
- public void onAudioInfoChanged(AudioInfo info) {
+ public void onAudioInfoChanged(PlaybackInfo info) {
onRemoteVolumeUpdateIfShown();
}
};
diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml
index 03d920a..1768400 100644
--- a/packages/VpnDialogs/AndroidManifest.xml
+++ b/packages/VpnDialogs/AndroidManifest.xml
@@ -28,14 +28,5 @@
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
-
- <activity android:name=".ManageDialog"
- android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
- android:noHistory="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.DEFAULT"/>
- </intent-filter>
- </activity>
</application>
</manifest>
diff --git a/packages/VpnDialogs/res/drawable-hdpi/ic_vpn_dialog.png b/packages/VpnDialogs/res/drawable-hdpi/ic_vpn_dialog.png
new file mode 100644
index 0000000..a0b4b61
--- /dev/null
+++ b/packages/VpnDialogs/res/drawable-hdpi/ic_vpn_dialog.png
Binary files differ
diff --git a/packages/VpnDialogs/res/drawable-mdpi/ic_vpn_dialog.png b/packages/VpnDialogs/res/drawable-mdpi/ic_vpn_dialog.png
new file mode 100644
index 0000000..df5dfe8
--- /dev/null
+++ b/packages/VpnDialogs/res/drawable-mdpi/ic_vpn_dialog.png
Binary files differ
diff --git a/packages/VpnDialogs/res/drawable-xhdpi/ic_vpn_dialog.png b/packages/VpnDialogs/res/drawable-xhdpi/ic_vpn_dialog.png
new file mode 100644
index 0000000..18d5a3a
--- /dev/null
+++ b/packages/VpnDialogs/res/drawable-xhdpi/ic_vpn_dialog.png
Binary files differ
diff --git a/packages/VpnDialogs/res/drawable-xxhdpi/ic_vpn_dialog.png b/packages/VpnDialogs/res/drawable-xxhdpi/ic_vpn_dialog.png
new file mode 100644
index 0000000..4d475dc
--- /dev/null
+++ b/packages/VpnDialogs/res/drawable-xxhdpi/ic_vpn_dialog.png
Binary files differ
diff --git a/packages/VpnDialogs/res/drawable-xxxhdpi/ic_vpn_dialog.png b/packages/VpnDialogs/res/drawable-xxxhdpi/ic_vpn_dialog.png
new file mode 100644
index 0000000..9d458b4
--- /dev/null
+++ b/packages/VpnDialogs/res/drawable-xxxhdpi/ic_vpn_dialog.png
Binary files differ
diff --git a/packages/VpnDialogs/res/layout/confirm.xml b/packages/VpnDialogs/res/layout/confirm.xml
index ee7f4b8..66fec59 100644
--- a/packages/VpnDialogs/res/layout/confirm.xml
+++ b/packages/VpnDialogs/res/layout/confirm.xml
@@ -18,41 +18,12 @@
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
- <LinearLayout android:layout_width="match_parent"
+ <TextView android:id="@+id/warning"
+ android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:padding="3mm">
-
- <LinearLayout android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:gravity="center_vertical">
-
- <ImageView android:id="@+id/icon"
- android:layout_width="@android:dimen/app_icon_size"
- android:layout_height="@android:dimen/app_icon_size"
- android:paddingRight="1mm"/>
-
- <TextView android:id="@+id/prompt"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textSize="18sp"/>
- </LinearLayout>
-
- <TextView android:id="@+id/warning"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingTop="1mm"
- android:paddingBottom="1mm"
- android:text="@string/warning"
- android:textSize="18sp"/>
-
- <CheckBox android:id="@+id/check"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="@string/accept"
- android:textSize="20sp"
- android:filterTouchesWhenObscured="true"
- android:checked="false"/>
- </LinearLayout>
+ android:textSize="18sp"
+ android:paddingTop="4mm"
+ android:paddingLeft="3mm"
+ android:paddingRight="3mm"
+ android:paddingBottom="4mm"/>
</ScrollView>
diff --git a/packages/VpnDialogs/res/layout/manage.xml b/packages/VpnDialogs/res/layout/manage.xml
deleted file mode 100644
index 56332c3..0000000
--- a/packages/VpnDialogs/res/layout/manage.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-
-<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:padding="3mm"
- android:stretchColumns="0,1"
- android:shrinkColumns="1">
-
- <TableRow>
- <TextView android:text="@string/session" style="@style/label"/>
- <TextView android:id="@+id/session" style="@style/value"/>
- </TableRow>
-
- <TableRow>
- <TextView android:text="@string/duration" style="@style/label"/>
- <TextView android:id="@+id/duration" style="@style/value"/>
- </TableRow>
-
- <TableRow android:id="@+id/data_transmitted_row" android:visibility="gone">
- <TextView android:text="@string/data_transmitted" style="@style/label"/>
- <TextView android:id="@+id/data_transmitted" style="@style/value"/>
- </TableRow>
-
- <TableRow android:id="@+id/data_received_row" android:visibility="gone">
- <TextView android:text="@string/data_received" style="@style/label"/>
- <TextView android:id="@+id/data_received" style="@style/value"/>
- </TableRow>
-
-</TableLayout>
diff --git a/packages/VpnDialogs/res/values/strings.xml b/packages/VpnDialogs/res/values/strings.xml
index 3ff767a..84206a1 100644
--- a/packages/VpnDialogs/res/values/strings.xml
+++ b/packages/VpnDialogs/res/values/strings.xml
@@ -17,40 +17,15 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Dialog title to identify the request from a VPN application. [CHAR LIMIT=60] -->
- <string name="prompt"><xliff:g id="app">%s</xliff:g>
- attempts to create a VPN connection.
- </string>
+ <string name="prompt">Connection request</string>
<!-- Dialog message to warn about the risk of using a VPN application. [CHAR LIMIT=NONE] -->
- <string name="warning">By proceeding, you are giving the application
- permission to intercept all network traffic.
- <b>Do NOT accept unless you trust the application.</b> Otherwise,
- you run the risk of having your data compromised by a malicious
- software.
- </string>
-
- <!-- Checkbox label to accept the request from a VPN application. [CHAR LIMIT=60] -->
- <string name="accept">I trust this application.</string>
-
- <!-- Dialog title for built-in VPN. [CHAR LIMIT=40] -->
- <string name="legacy_title">VPN is connected</string>
- <!-- Button label to configure the current VPN session. [CHAR LIMIT=20] -->
- <string name="configure">Configure</string>
- <!-- Button label to disconnect the current VPN session. [CHAR LIMIT=20] -->
- <string name="disconnect">Disconnect</string>
-
- <!-- Label for the name of the current VPN session. [CHAR LIMIT=20] -->
- <string name="session">Session:</string>
- <!-- Label for the duration of the current VPN session. [CHAR LIMIT=20] -->
- <string name="duration">Duration:</string>
- <!-- Label for the network usage of data transmitted over VPN. [CHAR LIMIT=20] -->
- <string name="data_transmitted">Sent:</string>
- <!-- Label for the network usage of data received over VPN. [CHAR LIMIT=20] -->
- <string name="data_received">Received:</string>
-
- <!-- Formatted string for the network usage over VPN. [CHAR LIMIT=40] -->
- <string name="data_value_format">
- <xliff:g id="number">%1$s</xliff:g> bytes /
- <xliff:g id="number">%2$s</xliff:g> packets
+ <string name="warning"><xliff:g id="app">%s</xliff:g> wants to set up a VPN connection
+ that allows it to monitor network traffic. Only accept if you trust the source.
+ <![CDATA[
+ <br />
+ <br />
+ <img src="vpn_icon" />
+ ]]> appears at the top of your screen when VPN is active.
</string>
</resources>
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
index ddafc66..897c96cf 100644
--- a/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
@@ -18,21 +18,28 @@
import android.content.Context;
import android.content.DialogInterface;
+import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
import android.net.IConnectivityManager;
+import android.net.VpnService;
import android.os.ServiceManager;
+import android.text.Html;
+import android.text.Html.ImageGetter;
import android.util.Log;
import android.view.View;
import android.widget.Button;
-import android.widget.CompoundButton;
-import android.widget.ImageView;
import android.widget.TextView;
import com.android.internal.app.AlertActivity;
+import com.android.internal.net.VpnConfig;
-public class ConfirmDialog extends AlertActivity implements
- CompoundButton.OnCheckedChangeListener, DialogInterface.OnClickListener {
+import java.util.List;
+
+public class ConfirmDialog extends AlertActivity
+ implements DialogInterface.OnClickListener, ImageGetter {
private static final String TAG = "VpnConfirm";
private String mPackage;
@@ -56,27 +63,22 @@
return;
}
- PackageManager pm = getPackageManager();
- ApplicationInfo app = pm.getApplicationInfo(mPackage, 0);
-
View view = View.inflate(this, R.layout.confirm, null);
- ((ImageView) view.findViewById(R.id.icon)).setImageDrawable(app.loadIcon(pm));
- ((TextView) view.findViewById(R.id.prompt)).setText(
- getString(R.string.prompt, app.loadLabel(pm)));
- ((CompoundButton) view.findViewById(R.id.check)).setOnCheckedChangeListener(this);
- mAlertParams.mIconAttrId = android.R.attr.alertDialogIcon;
- mAlertParams.mTitle = getText(android.R.string.dialog_alert_title);
+ ((TextView) view.findViewById(R.id.warning)).setText(
+ Html.fromHtml(
+ getString(R.string.warning, VpnConfig.getVpnLabel(this, mPackage)),
+ this, null /* tagHandler */));
+
+ mAlertParams.mTitle = getText(R.string.prompt);
mAlertParams.mPositiveButtonText = getText(android.R.string.ok);
mAlertParams.mPositiveButtonListener = this;
mAlertParams.mNegativeButtonText = getText(android.R.string.cancel);
- mAlertParams.mNegativeButtonListener = this;
mAlertParams.mView = view;
setupAlert();
getWindow().setCloseOnTouchOutside(false);
mButton = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
- mButton.setEnabled(false);
mButton.setFilterTouchesWhenObscured(true);
} catch (Exception e) {
Log.e(TAG, "onResume", e);
@@ -85,18 +87,24 @@
}
@Override
- public void onBackPressed() {
+ public Drawable getDrawable(String source) {
+ // Should only reach this when fetching the VPN icon for the warning string.
+ Drawable icon = getDrawable(R.drawable.ic_vpn_dialog);
+ icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
+ return icon;
}
@Override
- public void onCheckedChanged(CompoundButton button, boolean checked) {
- mButton.setEnabled(checked);
+ public void onBackPressed() {
}
@Override
public void onClick(DialogInterface dialog, int which) {
try {
- if (which == DialogInterface.BUTTON_POSITIVE && mService.prepareVpn(null, mPackage)) {
+ if (mService.prepareVpn(null, mPackage)) {
+ // Authorize this app to initiate VPN connections in the future without user
+ // intervention.
+ mService.setVpnPackageAuthorization(true);
setResult(RESULT_OK);
}
} catch (Exception e) {
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
deleted file mode 100644
index eb20995..0000000
--- a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2011 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.vpndialogs;
-
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.net.IConnectivityManager;
-import android.os.Handler;
-import android.os.Message;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.util.Log;
-import android.view.View;
-import android.widget.TextView;
-
-import com.android.internal.app.AlertActivity;
-import com.android.internal.net.VpnConfig;
-
-import java.io.DataInputStream;
-import java.io.FileInputStream;
-
-public class ManageDialog extends AlertActivity implements
- DialogInterface.OnClickListener, Handler.Callback {
- private static final String TAG = "VpnManage";
-
- private VpnConfig mConfig;
-
- private IConnectivityManager mService;
-
- private TextView mDuration;
- private TextView mDataTransmitted;
- private TextView mDataReceived;
- private boolean mDataRowsHidden;
-
- private Handler mHandler;
-
- @Override
- protected void onResume() {
- super.onResume();
-
- if (getCallingPackage() != null) {
- Log.e(TAG, getCallingPackage() + " cannot start this activity");
- finish();
- return;
- }
-
- try {
-
- mService = IConnectivityManager.Stub.asInterface(
- ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
-
- mConfig = mService.getVpnConfig();
-
- // mConfig can be null if we are a restricted user, in that case don't show this dialog
- if (mConfig == null) {
- finish();
- return;
- }
-
- View view = View.inflate(this, R.layout.manage, null);
- if (mConfig.session != null) {
- ((TextView) view.findViewById(R.id.session)).setText(mConfig.session);
- }
- mDuration = (TextView) view.findViewById(R.id.duration);
- mDataTransmitted = (TextView) view.findViewById(R.id.data_transmitted);
- mDataReceived = (TextView) view.findViewById(R.id.data_received);
- mDataRowsHidden = true;
-
- if (mConfig.legacy) {
- mAlertParams.mIconId = android.R.drawable.ic_dialog_info;
- mAlertParams.mTitle = getText(R.string.legacy_title);
- } else {
- PackageManager pm = getPackageManager();
- ApplicationInfo app = pm.getApplicationInfo(mConfig.user, 0);
- mAlertParams.mIcon = app.loadIcon(pm);
- mAlertParams.mTitle = app.loadLabel(pm);
- }
- if (mConfig.configureIntent != null) {
- mAlertParams.mPositiveButtonText = getText(R.string.configure);
- mAlertParams.mPositiveButtonListener = this;
- }
- mAlertParams.mNeutralButtonText = getText(R.string.disconnect);
- mAlertParams.mNeutralButtonListener = this;
- mAlertParams.mNegativeButtonText = getText(android.R.string.cancel);
- mAlertParams.mNegativeButtonListener = this;
- mAlertParams.mView = view;
- setupAlert();
-
- if (mHandler == null) {
- mHandler = new Handler(this);
- }
- mHandler.sendEmptyMessage(0);
- } catch (Exception e) {
- Log.e(TAG, "onResume", e);
- finish();
- }
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- if (!isFinishing()) {
- finish();
- }
- }
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- try {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- mConfig.configureIntent.send();
- } else if (which == DialogInterface.BUTTON_NEUTRAL) {
- if (mConfig.legacy) {
- mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN);
- } else {
- mService.prepareVpn(mConfig.user, VpnConfig.LEGACY_VPN);
- }
- }
- } catch (Exception e) {
- Log.e(TAG, "onClick", e);
- finish();
- }
- }
-
- @Override
- public boolean handleMessage(Message message) {
- mHandler.removeMessages(0);
-
- if (!isFinishing()) {
- if (mConfig.startTime != -1) {
- long seconds = (SystemClock.elapsedRealtime() - mConfig.startTime) / 1000;
- mDuration.setText(String.format("%02d:%02d:%02d",
- seconds / 3600, seconds / 60 % 60, seconds % 60));
- }
-
- String[] numbers = getNumbers();
- if (numbers != null) {
- // First unhide the related data rows.
- if (mDataRowsHidden) {
- findViewById(R.id.data_transmitted_row).setVisibility(View.VISIBLE);
- findViewById(R.id.data_received_row).setVisibility(View.VISIBLE);
- mDataRowsHidden = false;
- }
-
- // [1] and [2] are received data in bytes and packets.
- mDataReceived.setText(getString(R.string.data_value_format,
- numbers[1], numbers[2]));
-
- // [9] and [10] are transmitted data in bytes and packets.
- mDataTransmitted.setText(getString(R.string.data_value_format,
- numbers[9], numbers[10]));
- }
- mHandler.sendEmptyMessageDelayed(0, 1000);
- }
- return true;
- }
-
- private String[] getNumbers() {
- DataInputStream in = null;
- try {
- // See dev_seq_printf_stats() in net/core/dev.c.
- in = new DataInputStream(new FileInputStream("/proc/net/dev"));
- String prefix = mConfig.interfaze + ':';
-
- while (true) {
- String line = in.readLine().trim();
- if (line.startsWith(prefix)) {
- String[] numbers = line.substring(prefix.length()).split(" +");
- for (int i = 1; i < 17; ++i) {
- if (!numbers[i].equals("0")) {
- return numbers;
- }
- }
- break;
- }
- }
- } catch (Exception e) {
- // ignore
- } finally {
- try {
- in.close();
- } catch (Exception e) {
- // ignore
- }
- }
- return null;
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 73358c8..9652ebd 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -267,6 +267,7 @@
private Boolean mAllowExitTransitionOverlap;
private Boolean mAllowEnterTransitionOverlap;
private long mBackgroundFadeDurationMillis = -1;
+ private Boolean mSharedElementsUseOverlay;
static class WindowManagerHolder {
static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface(
@@ -3546,6 +3547,10 @@
R.styleable.Window_windowTransitionBackgroundFadeDuration,
DEFAULT_BACKGROUND_FADE_DURATION_MS);
}
+ if (mSharedElementsUseOverlay == null) {
+ mSharedElementsUseOverlay = getWindowStyle().getBoolean(
+ R.styleable.Window_windowSharedElementsUseOverlay, true);
+ }
}
}
}
@@ -4024,6 +4029,16 @@
mBackgroundFadeDurationMillis = fadeDurationMillis;
}
+ @Override
+ public void setSharedElementsUseOverlay(boolean sharedElementsUseOverlay) {
+ mSharedElementsUseOverlay = sharedElementsUseOverlay;
+ }
+
+ @Override
+ public boolean getSharedElementsUseOverlay() {
+ return (mSharedElementsUseOverlay == null) ? true : mSharedElementsUseOverlay;
+ }
+
private static final class DrawableFeatureState {
DrawableFeatureState(int _featureId) {
featureId = _featureId;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 3f7c72e..9e268c3 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -70,6 +70,7 @@
import android.service.dreams.DreamManagerInternal;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
+import android.speech.RecognizerIntent;
import android.telecomm.TelecommManager;
import android.util.DisplayMetrics;
import android.util.EventLog;
@@ -2338,6 +2339,17 @@
}
}
return -1;
+ } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) {
+ if (!down) {
+ Intent voiceIntent;
+ if (!keyguardOn && mPowerManager.isInteractive()) {
+ voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
+ } else {
+ voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
+ voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardOn);
+ }
+ mContext.startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF);
+ }
} else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
if (down && repeatCount == 0) {
mHandler.post(mScreenshotRunnable);
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 609ffda..f1e99fd 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -20,6 +20,7 @@
import android.app.AppGlobals;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManagerInternal;
+import android.app.admin.DevicePolicyManagerInternal.OnCrossProfileWidgetProvidersChangeListener;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
@@ -102,7 +103,8 @@
import java.util.Map;
import java.util.Set;
-class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBackupProvider {
+class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBackupProvider,
+ OnCrossProfileWidgetProvidersChangeListener {
private static final String TAG = "AppWidgetServiceImpl";
private static boolean DEBUG = false;
@@ -199,6 +201,7 @@
mSecurityPolicy = new SecurityPolicy();
computeMaximumWidgetBitmapMemory();
registerBroadcastReceiver();
+ registerOnCrossProfileProvidersChangedListener();
}
private void computeMaximumWidgetBitmapMemory() {
@@ -243,6 +246,15 @@
userFilter, null, null);
}
+ private void registerOnCrossProfileProvidersChangedListener() {
+ DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService(
+ DevicePolicyManagerInternal.class);
+ // The device policy is an optional component.
+ if (devicePolicyManager != null) {
+ devicePolicyManager.addOnCrossProfileWidgetProvidersChangeListener(this);
+ }
+ }
+
public void setSafeMode(boolean safeMode) {
mSafeMode = safeMode;
}
@@ -368,7 +380,7 @@
saveGroupStateAsync(userId);
// If the set of providers has been modified, notify each active AppWidgetHost
- scheduleNotifyHostsForProvidersChangedLocked();
+ scheduleNotifyGroupHostsForProvidersChangedLocked(userId);
}
}
}
@@ -1527,7 +1539,7 @@
widget.views = views;
}
- scheduleNotifyUpdateAppWidgetLocked(widget);
+ scheduleNotifyUpdateAppWidgetLocked(widget, views);
}
}
@@ -1599,7 +1611,7 @@
}
}
- private void scheduleNotifyUpdateAppWidgetLocked(Widget widget) {
+ private void scheduleNotifyUpdateAppWidgetLocked(Widget widget, RemoteViews updateViews) {
if (widget == null || widget.provider == null || widget.provider.zombie
|| widget.host.callbacks == null || widget.host.zombie) {
return;
@@ -1608,7 +1620,7 @@
SomeArgs args = SomeArgs.obtain();
args.arg1 = widget.host;
args.arg2 = widget.host.callbacks;
- args.arg3 = widget.views;
+ args.arg3 = updateViews;
args.argi1 = widget.appWidgetId;
mCallbackHandler.obtainMessage(
@@ -1657,11 +1669,27 @@
}
}
- private void scheduleNotifyHostsForProvidersChangedLocked() {
+ private void scheduleNotifyGroupHostsForProvidersChangedLocked(int userId) {
+ final int[] profileIds = mSecurityPolicy.getEnabledGroupProfileIds(userId);
+
final int N = mHosts.size();
for (int i = N - 1; i >= 0; i--) {
Host host = mHosts.get(i);
+ boolean hostInGroup = false;
+ final int M = profileIds.length;
+ for (int j = 0; j < M; j++) {
+ final int profileId = profileIds[j];
+ if (host.getUserId() == profileId) {
+ hostInGroup = true;
+ break;
+ }
+ }
+
+ if (!hostInGroup) {
+ continue;
+ }
+
if (host == null || host.zombie || host.callbacks == null) {
continue;
}
@@ -2617,6 +2645,9 @@
private void onUserStopped(int userId) {
synchronized (mLock) {
+ boolean providersChanged = false;
+ boolean crossProfileWidgetsChanged = false;
+
// Remove widgets that have both host and provider in the user.
final int widgetCount = mWidgets.size();
for (int i = widgetCount - 1; i >= 0; i--) {
@@ -2645,6 +2676,7 @@
for (int i = hostCount - 1; i >= 0; i--) {
Host host = mHosts.get(i);
if (host.getUserId() == userId) {
+ crossProfileWidgetsChanged |= !host.widgets.isEmpty();
deleteHostLocked(host);
}
}
@@ -2654,6 +2686,8 @@
for (int i = providerCount - 1; i >= 0; i--) {
Provider provider = mProviders.get(i);
if (provider.getUserId() == userId) {
+ crossProfileWidgetsChanged |= !provider.widgets.isEmpty();
+ providersChanged = true;
deleteProviderLocked(provider);
}
}
@@ -2678,6 +2712,17 @@
if (nextIdIndex >= 0) {
mNextAppWidgetIds.removeAt(nextIdIndex);
}
+
+ // Announce removed provider changes to all hosts in the group.
+ if (providersChanged) {
+ scheduleNotifyGroupHostsForProvidersChangedLocked(userId);
+ }
+
+ // Save state if removing a profile changed the group state.
+ // Nothing will be saved if the group parent was removed.
+ if (crossProfileWidgetsChanged) {
+ saveGroupStateAsync(userId);
+ }
}
}
@@ -2843,6 +2888,31 @@
}
}
+ @Override
+ public void onCrossProfileWidgetProvidersChanged(int userId, List<String> packages) {
+ final int parentId = mSecurityPolicy.getProfileParent(userId);
+ // We care only if the white-listed package is in a profile of
+ // the group parent as only the parent can add widgets from the
+ // profile and not the other way around.
+ if (parentId != userId) {
+ synchronized (mLock) {
+ boolean providersChanged = false;
+
+ final int packageCount = packages.size();
+ for (int i = 0; i < packageCount; i++) {
+ String packageName = packages.get(i);
+ providersChanged |= updateProvidersForPackageLocked(packageName,
+ userId, null);
+ }
+
+ if (providersChanged) {
+ saveGroupStateAsync(userId);
+ scheduleNotifyGroupHostsForProvidersChangedLocked(userId);
+ }
+ }
+ }
+ }
+
private final class CallbackHandler extends Handler {
public static final int MSG_NOTIFY_UPDATE_APP_WIDGET = 1;
public static final int MSG_NOTIFY_PROVIDER_CHANGED = 2;
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 5900612..b576324 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -34,7 +34,6 @@
import android.app.backup.IFullBackupRestoreObserver;
import android.app.backup.IRestoreObserver;
import android.app.backup.IRestoreSession;
-import android.app.job.JobParameters;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -79,6 +78,7 @@
import android.provider.Settings;
import android.system.ErrnoException;
import android.system.Os;
+import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.EventLog;
import android.util.Log;
@@ -308,12 +308,13 @@
volatile boolean mClearingData;
// Transport bookkeeping
- final HashMap<String,String> mTransportNames
- = new HashMap<String,String>(); // component name -> registration name
- final HashMap<String,IBackupTransport> mTransports
- = new HashMap<String,IBackupTransport>(); // registration name -> binder
- final ArrayList<TransportConnection> mTransportConnections
- = new ArrayList<TransportConnection>();
+ final Intent mTransportServiceIntent = new Intent(SERVICE_ACTION_TRANSPORT_HOST);
+ final ArrayMap<String,String> mTransportNames
+ = new ArrayMap<String,String>(); // component name -> registration name
+ final ArrayMap<String,IBackupTransport> mTransports
+ = new ArrayMap<String,IBackupTransport>(); // registration name -> binder
+ final ArrayMap<String,TransportConnection> mTransportConnections
+ = new ArrayMap<String,TransportConnection>();
String mCurrentTransport;
ActiveRestoreSession mActiveRestoreSession;
@@ -867,6 +868,7 @@
// the timeout is suspended while a restore is in progress. Clean
// up now.
Slog.w(TAG, "Restore session timed out; aborting");
+ mActiveRestoreSession.markTimedOut();
post(mActiveRestoreSession.new EndRestoreRunnable(
BackupManagerService.this, mActiveRestoreSession));
}
@@ -1063,9 +1065,8 @@
if (DEBUG) Slog.v(TAG, "Starting with transport " + mCurrentTransport);
// Find transport hosts and bind to their services
- Intent transportServiceIntent = new Intent(SERVICE_ACTION_TRANSPORT_HOST);
List<ResolveInfo> hosts = mPackageManager.queryIntentServicesAsUser(
- transportServiceIntent, 0, UserHandle.USER_OWNER);
+ mTransportServiceIntent, 0, UserHandle.USER_OWNER);
if (DEBUG) {
Slog.v(TAG, "Found transports: " + ((hosts == null) ? "null" : hosts.size()));
}
@@ -1081,17 +1082,7 @@
ServiceInfo info = hosts.get(i).serviceInfo;
PackageInfo packInfo = mPackageManager.getPackageInfo(info.packageName, 0);
if ((packInfo.applicationInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0) {
- ComponentName svcName = new ComponentName(info.packageName, info.name);
- if (DEBUG) {
- Slog.i(TAG, "Binding to transport host " + svcName);
- }
- Intent intent = new Intent(transportServiceIntent);
- intent.setComponent(svcName);
- TransportConnection connection = new TransportConnection();
- mTransportConnections.add(connection);
- context.bindServiceAsUser(intent,
- connection, Context.BIND_AUTO_CREATE,
- UserHandle.OWNER);
+ bindTransport(info);
} else {
Slog.w(TAG, "Transport package not privileged: " + info.packageName);
}
@@ -1751,6 +1742,7 @@
String action = intent.getAction();
boolean replacing = false;
boolean added = false;
+ boolean rebind = false;
Bundle extras = intent.getExtras();
String pkgList[] = null;
if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
@@ -1763,7 +1755,7 @@
if (pkgName != null) {
pkgList = new String[] { pkgName };
}
- added = Intent.ACTION_PACKAGE_ADDED.equals(action);
+ rebind = added = Intent.ACTION_PACKAGE_ADDED.equals(action);
replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false);
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
added = true;
@@ -1796,6 +1788,20 @@
enqueueFullBackup(packageName, now);
scheduleNextFullBackupJob();
}
+
+ // if this was the PACKAGE_ADDED conclusion of an upgrade of the package
+ // hosting one of our transports, we need to explicitly rebind now.
+ if (rebind) {
+ synchronized (mTransportConnections) {
+ final TransportConnection conn = mTransportConnections.get(packageName);
+ if (conn != null) {
+ if (DEBUG) {
+ Slog.i(TAG, "Transport package changed; rebinding");
+ }
+ bindTransport(conn.mTransport);
+ }
+ }
+ }
} catch (NameNotFoundException e) {
// doesn't really exist; ignore it
if (DEBUG) {
@@ -1803,6 +1809,7 @@
}
}
}
+
} else {
if (replacing) {
// The package is being updated. We'll receive a PACKAGE_ADDED shortly.
@@ -1817,6 +1824,12 @@
// ----- Track connection to transports service -----
class TransportConnection implements ServiceConnection {
+ ServiceInfo mTransport;
+
+ public TransportConnection(ServiceInfo transport) {
+ mTransport = transport;
+ }
+
@Override
public void onServiceConnected(ComponentName component, IBinder service) {
if (DEBUG) Slog.v(TAG, "Connected to transport " + component);
@@ -1840,6 +1853,32 @@
}
};
+ void bindTransport(ServiceInfo transport) {
+ ComponentName svcName = new ComponentName(transport.packageName, transport.name);
+ if (DEBUG) {
+ Slog.i(TAG, "Binding to transport host " + svcName);
+ }
+ Intent intent = new Intent(mTransportServiceIntent);
+ intent.setComponent(svcName);
+
+ TransportConnection connection;
+ synchronized (mTransportConnections) {
+ connection = mTransportConnections.get(transport.packageName);
+ if (null == connection) {
+ connection = new TransportConnection(transport);
+ mTransportConnections.put(transport.packageName, connection);
+ } else {
+ // This is a rebind due to package upgrade. The service won't be
+ // automatically relaunched for us until we explicitly rebind, but
+ // we need to unbind the now-orphaned original connection.
+ mContext.unbindService(connection);
+ }
+ }
+ mContext.bindServiceAsUser(intent,
+ connection, Context.BIND_AUTO_CREATE,
+ UserHandle.OWNER);
+ }
+
// Add the backup agents in the given packages to our set of known backup participants.
// If 'packageNames' is null, adds all backup agents in the whole system.
void addPackageParticipantsLocked(String[] packageNames) {
@@ -8738,12 +8777,17 @@
private IBackupTransport mRestoreTransport = null;
RestoreSet[] mRestoreSets = null;
boolean mEnded = false;
+ boolean mTimedOut = false;
ActiveRestoreSession(String packageName, String transport) {
mPackageName = packageName;
mRestoreTransport = getTransport(transport);
}
+ public void markTimedOut() {
+ mTimedOut = true;
+ }
+
// --- Binder interface ---
public synchronized int getAvailableRestoreSets(IRestoreObserver observer) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
@@ -8756,6 +8800,11 @@
throw new IllegalStateException("Restore session already ended");
}
+ if (mTimedOut) {
+ Slog.i(TAG, "Session already timed out");
+ return -1;
+ }
+
long oldId = Binder.clearCallingIdentity();
try {
if (mRestoreTransport == null) {
@@ -8787,6 +8836,11 @@
throw new IllegalStateException("Restore session already ended");
}
+ if (mTimedOut) {
+ Slog.i(TAG, "Session already timed out");
+ return -1;
+ }
+
if (mRestoreTransport == null || mRestoreSets == null) {
Slog.e(TAG, "Ignoring restoreAll() with no restore set");
return -1;
@@ -8861,6 +8915,11 @@
throw new IllegalStateException("Restore session already ended");
}
+ if (mTimedOut) {
+ Slog.i(TAG, "Session already timed out");
+ return -1;
+ }
+
if (mRestoreTransport == null || mRestoreSets == null) {
Slog.e(TAG, "Ignoring restoreAll() with no restore set");
return -1;
@@ -8909,6 +8968,11 @@
throw new IllegalStateException("Restore session already ended");
}
+ if (mTimedOut) {
+ Slog.i(TAG, "Session already timed out");
+ return -1;
+ }
+
if (mPackageName != null) {
if (! mPackageName.equals(packageName)) {
Slog.e(TAG, "Ignoring attempt to restore pkg=" + packageName
@@ -9006,6 +9070,11 @@
public synchronized void endRestoreSession() {
if (DEBUG) Slog.d(TAG, "endRestoreSession");
+ if (mTimedOut) {
+ Slog.i(TAG, "Session already timed out");
+ return;
+ }
+
if (mEnded) {
throw new IllegalStateException("Restore session already ended");
}
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 07c9048..7b64139 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -121,6 +121,7 @@
private int mState;
private final BluetoothHandler mHandler;
private int mErrorRecoveryRetryCounter;
+ private final int mSystemUiUid;
private void registerForAirplaneMode(IntentFilter filter) {
final ContentResolver resolver = mContext.getContentResolver();
@@ -218,6 +219,15 @@
if (isBluetoothPersistedStateOn()) {
mEnableExternal = true;
}
+
+ int sysUiUid = -1;
+ try {
+ sysUiUid = mContext.getPackageManager().getPackageUid("com.android.systemui",
+ UserHandle.USER_OWNER);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.wtf(TAG, "Unable to resolve SystemUI's UID.", e);
+ }
+ mSystemUiUid = sysUiUid;
}
/**
@@ -1118,7 +1128,8 @@
try {
foregroundUser = ActivityManager.getCurrentUser();
valid = (callingUser == foregroundUser) ||
- callingAppId == Process.NFC_UID;
+ callingAppId == Process.NFC_UID ||
+ callingAppId == mSystemUiUid;
if (DBG) {
Log.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid
+ " callingUser=" + callingUser
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 67c01e5..7655e92 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -756,10 +756,20 @@
return mNextNetworkRequestId++;
}
- private synchronized int nextNetId() {
- int netId = mNextNetId;
- if (++mNextNetId > MAX_NET_ID) mNextNetId = MIN_NET_ID;
- return netId;
+ private void assignNextNetId(NetworkAgentInfo nai) {
+ synchronized (mNetworkForNetId) {
+ for (int i = MIN_NET_ID; i <= MAX_NET_ID; i++) {
+ int netId = mNextNetId;
+ if (++mNextNetId > MAX_NET_ID) mNextNetId = MIN_NET_ID;
+ // Make sure NetID unused. http://b/16815182
+ if (mNetworkForNetId.get(netId) == null) {
+ nai.network = new Network(netId);
+ mNetworkForNetId.put(netId, nai);
+ return;
+ }
+ }
+ }
+ throw new IllegalStateException("No free netIds");
}
private int getConnectivityChangeDelay() {
@@ -1733,6 +1743,19 @@
}
}
+ private boolean isLiveNetworkAgent(NetworkAgentInfo nai, String msg) {
+ final NetworkAgentInfo officialNai;
+ synchronized (mNetworkForNetId) {
+ officialNai = mNetworkForNetId.get(nai.network.netId);
+ }
+ if (officialNai != null && officialNai.equals(nai)) return true;
+ if (officialNai != null || VDBG) {
+ loge(msg + " - validateNetworkAgent found mismatched netId: " + officialNai +
+ " - " + nai);
+ }
+ return false;
+ }
+
// must be stateless - things change under us.
private class NetworkStateTrackerHandler extends Handler {
public NetworkStateTrackerHandler(Looper looper) {
@@ -1862,23 +1885,30 @@
}
case NetworkMonitor.EVENT_NETWORK_VALIDATED: {
NetworkAgentInfo nai = (NetworkAgentInfo)msg.obj;
- handleConnectionValidated(nai);
+ if (isLiveNetworkAgent(nai, "EVENT_NETWORK_VALIDATED")) {
+ handleConnectionValidated(nai);
+ }
break;
}
case NetworkMonitor.EVENT_NETWORK_LINGER_COMPLETE: {
NetworkAgentInfo nai = (NetworkAgentInfo)msg.obj;
- handleLingerComplete(nai);
+ if (isLiveNetworkAgent(nai, "EVENT_NETWORK_LINGER_COMPLETE")) {
+ handleLingerComplete(nai);
+ }
break;
}
case NetworkMonitor.EVENT_PROVISIONING_NOTIFICATION: {
+ NetworkAgentInfo nai = null;
+ synchronized (mNetworkForNetId) {
+ nai = mNetworkForNetId.get(msg.arg2);
+ }
+ if (nai == null) {
+ loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor");
+ break;
+ }
if (msg.arg1 == 0) {
setProvNotificationVisibleIntent(false, msg.arg2, 0, null, null);
} else {
- NetworkAgentInfo nai = mNetworkForNetId.get(msg.arg2);
- if (nai == null) {
- loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor");
- break;
- }
setProvNotificationVisibleIntent(true, msg.arg2, nai.networkInfo.getType(),
nai.networkInfo.getExtraInfo(), (PendingIntent)msg.obj);
}
@@ -2089,13 +2119,21 @@
if (newCap.satisfiedByNetworkCapabilities(network.networkCapabilities)) {
if (VDBG) log("apparently satisfied. currentScore=" + network.currentScore);
if ((bestNetwork == null) || bestNetwork.currentScore < network.currentScore) {
- bestNetwork = network;
+ if (!nri.isRequest) {
+ // Not setting bestNetwork here as a listening NetworkRequest may be
+ // satisfied by multiple Networks. Instead the request is added to
+ // each satisfying Network and notified about each.
+ network.addRequest(nri.request);
+ notifyNetworkCallback(network, nri);
+ } else {
+ bestNetwork = network;
+ }
}
}
}
if (bestNetwork != null) {
if (VDBG) log("using " + bestNetwork.name());
- if (nri.isRequest && bestNetwork.networkInfo.isConnected()) {
+ if (bestNetwork.networkInfo.isConnected()) {
// Cancel any lingering so the linger timeout doesn't teardown this network
// even though we have a request for it.
bestNetwork.networkLingered.clear();
@@ -2105,7 +2143,7 @@
mNetworkForRequestId.put(nri.request.requestId, bestNetwork);
notifyNetworkCallback(bestNetwork, nri);
score = bestNetwork.currentScore;
- if (nri.isRequest && nri.request.legacyType != TYPE_NONE) {
+ if (nri.request.legacyType != TYPE_NONE) {
mLegacyTypeTracker.add(nri.request.legacyType, bestNetwork);
}
}
@@ -2122,7 +2160,7 @@
private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
NetworkRequestInfo nri = mNetworkRequests.get(request);
if (nri != null) {
- if (nri.mUid != callingUid) {
+ if (Process.SYSTEM_UID != callingUid && nri.mUid != callingUid) {
if (DBG) log("Attempt to release unowned NetworkRequest " + request);
return;
}
@@ -2663,6 +2701,20 @@
}
/**
+ * Set whether the current VPN package has the ability to launch VPNs without
+ * user intervention. This method is used by system UIs and not available
+ * in ConnectivityManager. Permissions are checked in Vpn class.
+ * @hide
+ */
+ @Override
+ public void setVpnPackageAuthorization(boolean authorized) {
+ int user = UserHandle.getUserId(Binder.getCallingUid());
+ synchronized(mVpns) {
+ mVpns.get(user).setPackageAuthorization(authorized);
+ }
+ }
+
+ /**
* Configure a TUN interface and return its file descriptor. Parameters
* are encoded and opaque to this class. This method is used by VpnBuilder
* and not available in ConnectivityManager. Permissions are checked in
@@ -2798,11 +2850,13 @@
enforceConnectivityInternalPermission();
if (TextUtils.isEmpty(iface)) return ConnectivityManager.TYPE_NONE;
- for (NetworkStateTracker tracker : mNetTrackers) {
- if (tracker != null) {
- LinkProperties lp = tracker.getLinkProperties();
- if (lp != null && iface.equals(lp.getInterfaceName())) {
- return tracker.getNetworkInfo().getType();
+
+ synchronized(mNetworkForNetId) {
+ for (int i = 0; i < mNetworkForNetId.size(); i++) {
+ NetworkAgentInfo nai = mNetworkForNetId.valueAt(i);
+ LinkProperties lp = nai.linkProperties;
+ if (lp != null && iface.equals(lp.getInterfaceName()) && nai.networkInfo != null) {
+ return nai.networkInfo.getType();
}
}
}
@@ -3490,10 +3544,13 @@
mIsProvisioningNetwork.set(false);
// Check for apps that can handle provisioning first
Intent provisioningIntent = new Intent(TelephonyIntents.ACTION_CARRIER_SETUP);
- provisioningIntent.addCategory(TelephonyIntents.CATEGORY_MCCMNC_PREFIX
- + mTelephonyManager.getSimOperator());
- if (mContext.getPackageManager().resolveActivity(provisioningIntent, 0 /* flags */)
- != null) {
+ List<String> carrierPackages =
+ mTelephonyManager.getCarrierPackageNamesForBroadcastIntent(provisioningIntent);
+ if (carrierPackages != null && !carrierPackages.isEmpty()) {
+ if (carrierPackages.size() != 1) {
+ if (DBG) log("Multiple matching carrier apps found, launching the first.");
+ }
+ provisioningIntent.setPackage(carrierPackages.get(0));
provisioningIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(provisioningIntent);
@@ -4104,7 +4161,7 @@
int currentScore, NetworkMisc networkMisc) {
enforceConnectivityInternalPermission();
- NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), nextNetId(),
+ NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
new NetworkInfo(networkInfo), new LinkProperties(linkProperties),
new NetworkCapabilities(networkCapabilities), currentScore, mContext, mTrackerHandler,
networkMisc);
@@ -4118,9 +4175,7 @@
private void handleRegisterNetworkAgent(NetworkAgentInfo na) {
if (VDBG) log("Got NetworkAgent Messenger");
mNetworkAgentInfos.put(na.messenger, na);
- synchronized (mNetworkForNetId) {
- mNetworkForNetId.put(na.network.netId, na);
- }
+ assignNextNetId(na);
na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
NetworkInfo networkInfo = na.networkInfo;
na.networkInfo = null;
@@ -4386,6 +4441,10 @@
if (VDBG) log(" checking if request is satisfied: " + nri.request);
if (nri.request.networkCapabilities.satisfiedByNetworkCapabilities(
newNetwork.networkCapabilities)) {
+ if (!nri.isRequest) {
+ newNetwork.addRequest(nri.request);
+ continue;
+ }
// next check if it's better than any current network we're using for
// this request
if (VDBG) {
@@ -4702,7 +4761,9 @@
result.setType(networkType);
return result;
} else {
- return new NetworkInfo(networkType, 0, "Unknown", "");
+ NetworkInfo result = new NetworkInfo(networkType);
+ result.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
+ return result;
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b1d84f58..7edf54c 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -40,6 +40,9 @@
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManagerInternal;
import android.appwidget.AppWidgetManager;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Point;
import android.graphics.Rect;
import android.os.BatteryStats;
import android.os.PersistableBundle;
@@ -261,6 +264,7 @@
static final boolean DEBUG_VISBILITY = localLOGV || false;
static final boolean DEBUG_PSS = localLOGV || false;
static final boolean DEBUG_LOCKSCREEN = localLOGV || false;
+ static final boolean DEBUG_RECENTS = localLOGV || false;
static final boolean VALIDATE_TOKENS = false;
static final boolean SHOW_ACTIVITY_START_TIME = true;
@@ -410,6 +414,21 @@
ArrayList<TaskRecord> mRecentTasks;
ArraySet<TaskRecord> mTmpRecents = new ArraySet<TaskRecord>();
+ /**
+ * For addAppTask: cached of the last activity component that was added.
+ */
+ ComponentName mLastAddedTaskComponent;
+
+ /**
+ * For addAppTask: cached of the last activity uid that was added.
+ */
+ int mLastAddedTaskUid;
+
+ /**
+ * For addAppTask: cached of the last ActivityInfo that was added.
+ */
+ ActivityInfo mLastAddedTaskActivity;
+
public class PendingAssistExtras extends Binder implements Runnable {
public final ActivityRecord activity;
public boolean haveResult = false;
@@ -1181,6 +1200,9 @@
/** Flag whether the device has a recents UI */
final boolean mHasRecents;
+ final int mThumbnailWidth;
+ final int mThumbnailHeight;
+
final ServiceThread mHandlerThread;
final MainHandler mHandler;
@@ -1819,6 +1841,7 @@
BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START,
Integer.toString(msg.arg1), msg.arg1);
mSystemServiceManager.switchUser(msg.arg1);
+ mLockToAppRequest.clearPrompt();
break;
}
case ENTER_ANIMATION_COMPLETE_MSG: {
@@ -2229,8 +2252,10 @@
mConfigurationSeq = mConfiguration.seq = 1;
mProcessCpuTracker.init();
- mHasRecents = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_hasRecents);
+ final Resources res = mContext.getResources();
+ mHasRecents = res.getBoolean(com.android.internal.R.bool.config_hasRecents);
+ mThumbnailWidth = res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
+ mThumbnailHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
@@ -3481,7 +3506,8 @@
try {
int ret = mStackSupervisor.startActivityMayWait(null, targetUid, targetPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
- null, null, null, null, options, UserHandle.getUserId(targetUid), null);
+ null, null, null, null, options, UserHandle.getUserId(sourceRecord.app.uid),
+ null);
return ret;
} catch (SecurityException e) {
// XXX need to figure out how to propagate to original app.
@@ -3781,7 +3807,7 @@
}
final void addRecentTaskLocked(TaskRecord task) {
- int N = mRecentTasks.size();
+ final int N = mRecentTasks.size();
// Quick case: check if the top-most recent task is the same.
if (N > 0 && mRecentTasks.get(0) == task) {
return;
@@ -3790,10 +3816,25 @@
if (task.voiceSession != null) {
return;
}
- // Remove any existing entries that are the same kind of task.
+
+ trimRecentsForTask(task, true);
+
+ if (N >= MAX_RECENT_TASKS) {
+ final TaskRecord tr = mRecentTasks.remove(N - 1);
+ tr.disposeThumbnail();
+ tr.closeRecentsChain();
+ }
+ mRecentTasks.add(0, task);
+ }
+
+ /**
+ * If needed, remove oldest existing entries in recents that are for the same kind
+ * of task as the given one.
+ */
+ int trimRecentsForTask(TaskRecord task, boolean doTrim) {
+ int N = mRecentTasks.size();
final Intent intent = task.intent;
final boolean document = intent != null && intent.isDocument();
- final ComponentName comp = intent.getComponent();
int maxRecents = task.maxRecents - 1;
for (int i=0; i<N; i++) {
@@ -3825,6 +3866,12 @@
}
}
+ if (!doTrim) {
+ // If the caller is not actually asking for a trim, just tell them we reached
+ // a point where the trim would happen.
+ return i;
+ }
+
// Either task and tr are the same or, their affinities match or their intents match
// and neither of them is a document, or they are documents using the same activity
// and their maxRecents has been reached.
@@ -3842,12 +3889,8 @@
}
notifyTaskPersisterLocked(tr, false);
}
- if (N >= MAX_RECENT_TASKS) {
- final TaskRecord tr = mRecentTasks.remove(N - 1);
- tr.disposeThumbnail();
- tr.closeRecentsChain();
- }
- mRecentTasks.add(0, task);
+
+ return -1;
}
@Override
@@ -7639,7 +7682,10 @@
for (int i=0; i<N && maxNum > 0; i++) {
TaskRecord tr = mRecentTasks.get(i);
// Only add calling user or related users recent tasks
- if (!includedUsers.contains(Integer.valueOf(tr.userId))) continue;
+ if (!includedUsers.contains(Integer.valueOf(tr.userId))) {
+ if (DEBUG_RECENTS) Slog.d(TAG, "Skipping, not user: " + tr);
+ continue;
+ }
// Return the entry if desired by the caller. We always return
// the first entry, because callers always expect this to be the
@@ -7656,11 +7702,14 @@
// If the caller doesn't have the GET_TASKS permission, then only
// allow them to see a small subset of tasks -- their own and home.
if (!tr.isHomeTask() && tr.creatorUid != callingUid) {
+ if (DEBUG_RECENTS) Slog.d(TAG, "Skipping, not allowed: " + tr);
continue;
}
}
if (tr.autoRemoveRecents && tr.getTopActivity() == null) {
// Don't include auto remove tasks that are finished or finishing.
+ if (DEBUG_RECENTS) Slog.d(TAG, "Skipping, auto-remove without activity: "
+ + tr);
continue;
}
@@ -7675,11 +7724,15 @@
if (rti.origActivity != null) {
if (pm.getActivityInfo(rti.origActivity, 0, userId)
== null) {
+ if (DEBUG_RECENTS) Slog.d(TAG, "Skipping, unavail orig act: "
+ + tr);
continue;
}
} else if (rti.baseIntent != null) {
if (pm.queryIntentActivities(rti.baseIntent,
null, 0, userId) == null) {
+ if (DEBUG_RECENTS) Slog.d(TAG, "Skipping, unavail intent: "
+ + tr);
continue;
}
}
@@ -7721,6 +7774,97 @@
}
@Override
+ public int addAppTask(IBinder activityToken, Intent intent,
+ ActivityManager.TaskDescription description, Bitmap thumbnail) throws RemoteException {
+ final int callingUid = Binder.getCallingUid();
+ final long callingIdent = Binder.clearCallingIdentity();
+
+ try {
+ synchronized (this) {
+ ActivityRecord r = ActivityRecord.isInStackLocked(activityToken);
+ if (r == null) {
+ throw new IllegalArgumentException("Activity does not exist; token="
+ + activityToken);
+ }
+ ComponentName comp = intent.getComponent();
+ if (comp == null) {
+ throw new IllegalArgumentException("Intent " + intent
+ + " must specify explicit component");
+ }
+ if (thumbnail.getWidth() != mThumbnailWidth
+ || thumbnail.getHeight() != mThumbnailHeight) {
+ throw new IllegalArgumentException("Bad thumbnail size: got "
+ + thumbnail.getWidth() + "x" + thumbnail.getHeight() + ", require "
+ + mThumbnailWidth + "x" + mThumbnailHeight);
+ }
+ if (intent.getSelector() != null) {
+ intent.setSelector(null);
+ }
+ if (intent.getSourceBounds() != null) {
+ intent.setSourceBounds(null);
+ }
+ if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0) {
+ if ((intent.getFlags()&Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS) == 0) {
+ // The caller has added this as an auto-remove task... that makes no
+ // sense, so turn off auto-remove.
+ intent.addFlags(Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
+ }
+ } else if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+ // Must be a new task.
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ }
+ if (!comp.equals(mLastAddedTaskComponent) || callingUid != mLastAddedTaskUid) {
+ mLastAddedTaskActivity = null;
+ }
+ ActivityInfo ainfo = mLastAddedTaskActivity;
+ if (ainfo == null) {
+ ainfo = mLastAddedTaskActivity = AppGlobals.getPackageManager().getActivityInfo(
+ comp, 0, UserHandle.getUserId(callingUid));
+ if (ainfo.applicationInfo.uid != callingUid) {
+ throw new SecurityException(
+ "Can't add task for another application: target uid="
+ + ainfo.applicationInfo.uid + ", calling uid=" + callingUid);
+ }
+ }
+
+ TaskRecord task = new TaskRecord(this, mStackSupervisor.getNextTaskId(), ainfo,
+ intent, description);
+
+ int trimIdx = trimRecentsForTask(task, false);
+ if (trimIdx >= 0) {
+ // If this would have caused a trim, then we'll abort because that
+ // means it would be added at the end of the list but then just removed.
+ return -1;
+ }
+
+ final int N = mRecentTasks.size();
+ if (N >= (MAX_RECENT_TASKS-1)) {
+ final TaskRecord tr = mRecentTasks.remove(N - 1);
+ tr.disposeThumbnail();
+ tr.closeRecentsChain();
+ }
+
+ mRecentTasks.add(task);
+ r.task.stack.addTask(task, false, false);
+
+ task.setLastThumbnail(thumbnail);
+ task.freeLastThumbnail();
+
+ return task.taskId;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingIdent);
+ }
+ }
+
+ @Override
+ public Point getAppTaskThumbnailSize() {
+ synchronized (this) {
+ return new Point(mThumbnailWidth, mThumbnailHeight);
+ }
+ }
+
+ @Override
public void setTaskDescription(IBinder token, ActivityManager.TaskDescription td) {
synchronized (this) {
ActivityRecord r = ActivityRecord.isInStackLocked(token);
@@ -15422,10 +15566,14 @@
}
@Override
- public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity) {
- ActivityRecord srec = ActivityRecord.forToken(token);
- return srec != null && srec.task.affinity != null &&
- srec.task.affinity.equals(destAffinity);
+ public boolean shouldUpRecreateTask(IBinder token, String destAffinity) {
+ synchronized (this) {
+ ActivityRecord srec = ActivityRecord.forToken(token);
+ if (srec.task != null && srec.task.stack != null) {
+ return srec.task.stack.shouldUpRecreateTaskLocked(srec, destAffinity);
+ }
+ }
+ return false;
}
public boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode,
@@ -18056,14 +18204,16 @@
mCallingUid = callingUid;
}
+ private void checkCaller() {
+ if (mCallingUid != Binder.getCallingUid()) {
+ throw new SecurityException("Caller " + mCallingUid
+ + " does not match caller of getAppTasks(): " + Binder.getCallingUid());
+ }
+ }
+
@Override
public void finishAndRemoveTask() {
- // Ensure that we are called from the same process that created this AppTask
- if (mCallingUid != Binder.getCallingUid()) {
- Slog.w(TAG, "finishAndRemoveTask: caller " + mCallingUid
- + " does not match caller of getAppTasks(): " + Binder.getCallingUid());
- return;
- }
+ checkCaller();
synchronized (ActivityManagerService.this) {
long origId = Binder.clearCallingIdentity();
@@ -18085,12 +18235,7 @@
@Override
public ActivityManager.RecentTaskInfo getTaskInfo() {
- // Ensure that we are called from the same process that created this AppTask
- if (mCallingUid != Binder.getCallingUid()) {
- Slog.w(TAG, "finishAndRemoveTask: caller " + mCallingUid
- + " does not match caller of getAppTasks(): " + Binder.getCallingUid());
- return null;
- }
+ checkCaller();
synchronized (ActivityManagerService.this) {
long origId = Binder.clearCallingIdentity();
@@ -18105,5 +18250,28 @@
return null;
}
}
+
+ @Override
+ public void setExcludeFromRecents(boolean exclude) {
+ checkCaller();
+
+ synchronized (ActivityManagerService.this) {
+ long origId = Binder.clearCallingIdentity();
+ try {
+ TaskRecord tr = recentTaskForIdLocked(mTaskId);
+ if (tr != null) {
+ Intent intent = tr.getBaseIntent();
+ if (exclude) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ } else {
+ intent.setFlags(intent.getFlags()
+ & ~Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index abacb2d..fcbe71e 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -773,8 +773,8 @@
if (newThumbnail != null) {
if (ActivityManagerService.DEBUG_THUMBNAILS) Slog.i(ActivityManagerService.TAG,
"Setting thumbnail of " + this + " to " + newThumbnail);
- task.setLastThumbnail(newThumbnail);
- if (isPersistable()) {
+ boolean thumbnailUpdated = task.setLastThumbnail(newThumbnail);
+ if (thumbnailUpdated && isPersistable()) {
mStackSupervisor.mService.notifyTaskPersisterLocked(task, false);
}
}
@@ -1054,8 +1054,8 @@
return null;
}
- private static String createImageFilename(ActivityRecord r, int taskId) {
- return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + r.createTime +
+ private static String createImageFilename(long createTime, int taskId) {
+ return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + createTime +
TaskPersister.IMAGE_EXTENSION;
}
@@ -1072,7 +1072,7 @@
out.attribute(null, ATTR_USERID, String.valueOf(userId));
if (taskDescription != null) {
- task.saveTaskDescription(taskDescription, createImageFilename(this, task.taskId),
+ task.saveTaskDescription(taskDescription, createImageFilename(createTime, task.taskId),
out);
}
@@ -1165,7 +1165,8 @@
r.persistentState = persistentState;
if (createTime >= 0) {
- taskDescription.setIcon(TaskPersister.restoreImage(createImageFilename(r, taskId)));
+ taskDescription.setIcon(TaskPersister.restoreImage(createImageFilename(createTime,
+ taskId)));
}
r.taskDescription = taskDescription;
r.createTime = createTime;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index e309a03..4bd86e4 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -355,8 +355,8 @@
mCurrentUser = mService.mCurrentUserId;
// Get the activity screenshot thumbnail dimensions
Resources res = mService.mContext.getResources();
- mThumbnailWidth = res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
- mThumbnailHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
+ mThumbnailWidth = mService.mThumbnailWidth;
+ mThumbnailHeight = mService.mThumbnailHeight;
}
/**
@@ -2806,6 +2806,42 @@
}
}
+ final boolean shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity) {
+ // Basic case: for simple app-centric recents, we need to recreate
+ // the task if the affinity has changed.
+ if (srec == null || srec.task.affinity == null ||
+ !srec.task.affinity.equals(destAffinity)) {
+ return true;
+ }
+ // Document-centric case: an app may be split in to multiple documents;
+ // they need to re-create their task if this current activity is the root
+ // of a document, unless simply finishing it will return them to the the
+ // correct app behind.
+ if (srec.frontOfTask && srec.task != null) {
+ // Okay, this activity is at the root of its task. What to do, what to do...
+ if (srec.task.getTaskToReturnTo() != ActivityRecord.APPLICATION_ACTIVITY_TYPE) {
+ // Finishing won't return to an application, so we need to recreate.
+ return true;
+ }
+ // We now need to get the task below it to determine what to do.
+ int taskIdx = mTaskHistory.indexOf(srec.task);
+ if (taskIdx <= 0) {
+ Slog.w(TAG, "shouldUpRecreateTask: task not in history for " + srec);
+ return false;
+ }
+ if (taskIdx == 0) {
+ // At the bottom of the stack, nothing to go back to.
+ return true;
+ }
+ TaskRecord prevTask = mTaskHistory.get(taskIdx);
+ if (!srec.task.affinity.equals(prevTask.affinity)) {
+ // These are different apps, so need to recreate.
+ return true;
+ }
+ }
+ return false;
+ }
+
final boolean navigateUpToLocked(IBinder token, Intent destIntent, int resultCode,
Intent resultData) {
final ActivityRecord srec = ActivityRecord.forToken(token);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 931f448..8aec392 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -3189,7 +3189,11 @@
void endLockTaskModeIfTaskEnding(TaskRecord task) {
if (mLockTaskModeTask != null && mLockTaskModeTask == task) {
+ final Message lockTaskMsg = Message.obtain();
+ lockTaskMsg.arg1 = mLockTaskModeTask.userId;
+ lockTaskMsg.what = LOCK_TASK_END_MSG;
mLockTaskModeTask = null;
+ mHandler.sendMessage(lockTaskMsg);
}
}
diff --git a/services/core/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java
index 0ba62c5..098b0b6 100644
--- a/services/core/java/com/android/server/am/AppErrorDialog.java
+++ b/services/core/java/com/android/server/am/AppErrorDialog.java
@@ -94,6 +94,9 @@
}
mResult.set(msg.what);
+ // Make sure we don't have time timeout still hanging around.
+ removeMessages(FORCE_QUIT);
+
// If this is a timeout we won't be automatically closed, so go
// ahead and explicitly dismiss ourselves just in case.
dismiss();
diff --git a/services/core/java/com/android/server/am/LockTaskNotify.java b/services/core/java/com/android/server/am/LockTaskNotify.java
index cf65243..5768ddb 100644
--- a/services/core/java/com/android/server/am/LockTaskNotify.java
+++ b/services/core/java/com/android/server/am/LockTaskNotify.java
@@ -34,6 +34,7 @@
private final Context mContext;
private final H mHandler;
private AccessibilityManager mAccessibilityManager;
+ private Toast mLastToast;
public LockTaskNotify(Context context) {
mContext = context;
@@ -52,7 +53,11 @@
if (!isLocked && mAccessibilityManager.isEnabled()) {
text = mContext.getString(R.string.lock_to_app_toast_accessible);
}
- Toast.makeText(mContext, text, Toast.LENGTH_LONG).show();
+ if (mLastToast != null) {
+ mLastToast.cancel();
+ }
+ mLastToast = Toast.makeText(mContext, text, Toast.LENGTH_LONG);
+ mLastToast.show();
}
public void show(boolean starting) {
diff --git a/services/core/java/com/android/server/am/LockToAppRequestDialog.java b/services/core/java/com/android/server/am/LockToAppRequestDialog.java
index 12dcf7e..a1eb31e 100644
--- a/services/core/java/com/android/server/am/LockToAppRequestDialog.java
+++ b/services/core/java/com/android/server/am/LockToAppRequestDialog.java
@@ -74,11 +74,15 @@
return 0;
}
- public void showLockTaskPrompt(TaskRecord task) {
+ public void clearPrompt() {
if (mDialog != null) {
mDialog.dismiss();
mDialog = null;
}
+ }
+
+ public void showLockTaskPrompt(TaskRecord task) {
+ clearPrompt();
mRequestedTask = task;
final int unlockStringId = getLockString(task.userId);
@@ -97,13 +101,14 @@
mDialog = builder.create();
mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ mDialog.getWindow().getAttributes().privateFlags |=
+ WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
mDialog.show();
if (unlockStringId != 0) {
String unlockString = mContext.getString(unlockStringId);
mCheckbox = (CheckBox) mDialog.findViewById(R.id.lock_to_app_checkbox);
- mCheckbox.setText(mContext.getString(R.string.lock_to_app_use_screen_lock,
- unlockString));
+ mCheckbox.setText(unlockString);
// Remember state.
try {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index ccca657..d35e09f 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -167,6 +167,34 @@
setIntent(_intent, info);
}
+ TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
+ ActivityManager.TaskDescription _taskDescription) {
+ mService = service;
+ mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
+ TaskPersister.IMAGE_EXTENSION;
+ mLastThumbnailFile = new File(TaskPersister.sImagesDir, mFilename);
+ taskId = _taskId;
+ mAffiliatedTaskId = _taskId;
+ voiceSession = null;
+ voiceInteractor = null;
+ mActivities = new ArrayList<ActivityRecord>();
+ setIntent(_intent, info);
+
+ taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE;
+ isPersistable = true;
+ mCallingUid = info.applicationInfo.uid;
+ mCallingPackage = info.packageName;
+ // Clamp to [1, 100].
+ maxRecents = Math.min(Math.max(info.maxRecents, 1), 100);
+
+ taskType = APPLICATION_ACTIVITY_TYPE;
+ mTaskToReturnTo = HOME_ACTIVITY_TYPE;
+ userId = UserHandle.getUserId(info.applicationInfo.uid);
+ lastTaskDescription = _taskDescription;
+ mCallingUid = info.applicationInfo.uid;
+ mCallingPackage = info.packageName;
+ }
+
TaskRecord(ActivityManagerService service, int _taskId, Intent _intent, Intent _affinityIntent,
String _affinity, ComponentName _realActivity, ComponentName _origActivity,
boolean _rootWasReset, boolean _autoRemoveRecents, boolean _askedCompatMode,
@@ -358,15 +386,23 @@
setNextAffiliate(null);
}
- void setLastThumbnail(Bitmap thumbnail) {
- mLastThumbnail = thumbnail;
- if (thumbnail == null) {
- if (mLastThumbnailFile != null) {
- mLastThumbnailFile.delete();
+ /**
+ * Sets the last thumbnail.
+ * @return whether the thumbnail was set
+ */
+ boolean setLastThumbnail(Bitmap thumbnail) {
+ if (mLastThumbnail != thumbnail) {
+ mLastThumbnail = thumbnail;
+ if (thumbnail == null) {
+ if (mLastThumbnailFile != null) {
+ mLastThumbnailFile.delete();
+ }
+ } else {
+ mService.mTaskPersister.saveImage(thumbnail, mFilename);
}
- } else {
- mService.mTaskPersister.saveImage(thumbnail, mFilename);
+ return true;
}
+ return false;
}
void getLastThumbnail(TaskThumbnail thumbs) {
@@ -375,7 +411,8 @@
if (mLastThumbnail == null) {
thumbs.mainThumbnail = mService.mTaskPersister.getThumbnail(mFilename);
}
- if (mLastThumbnailFile.exists()) {
+ // Only load the thumbnail file if we don't have a thumbnail
+ if (thumbs.mainThumbnail == null && mLastThumbnailFile.exists()) {
try {
thumbs.thumbnailFileDescriptor = ParcelFileDescriptor.open(mLastThumbnailFile,
ParcelFileDescriptor.MODE_READ_ONLY);
@@ -764,8 +801,13 @@
return true;
}
+ private static String createLastTaskDescriptionIconFilename(int taskId, long lastActiveTime) {
+ return String.valueOf(taskId) + LAST_ACTIVITY_ICON_SUFFIX + lastActiveTime +
+ TaskPersister.IMAGE_EXTENSION;
+ }
+
void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
- Slog.i(TAG, "Saving task=" + this);
+ if (ActivityManagerService.DEBUG_RECENTS) Slog.i(TAG, "Saving task=" + this);
out.attribute(null, ATTR_TASKID, String.valueOf(taskId));
if (realActivity != null) {
@@ -790,8 +832,8 @@
out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
}
if (lastTaskDescription != null) {
- saveTaskDescription(lastTaskDescription, String.valueOf(taskId) +
- LAST_ACTIVITY_ICON_SUFFIX + lastActiveTime, out);
+ saveTaskDescription(lastTaskDescription, createLastTaskDescriptionIconFilename(taskId,
+ lastActiveTime), out);
}
out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
@@ -933,8 +975,8 @@
}
if (lastActiveTime >= 0) {
- taskDescription.setIcon(TaskPersister.restoreImage(String.valueOf(taskId) +
- LAST_ACTIVITY_ICON_SUFFIX + lastActiveTime + TaskPersister.IMAGE_EXTENSION));
+ taskDescription.setIcon(TaskPersister.restoreImage(
+ createLastTaskDescriptionIconFilename(taskId, lastActiveTime)));
}
final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent,
@@ -948,18 +990,15 @@
activities.get(activityNdx).task = task;
}
- Slog.i(TAG, "Restored task=" + task);
+ if (ActivityManagerService.DEBUG_RECENTS) Slog.d(TAG, "Restored task=" + task);
return task;
}
void dump(PrintWriter pw, String prefix) {
- if (rootWasReset || userId != 0 || numFullscreen != 0) {
- pw.print(prefix); pw.print(" rootWasReset="); pw.print(rootWasReset);
- pw.print(" userId="); pw.print(userId);
- pw.print(" taskType="); pw.print(taskType);
- pw.print(" numFullscreen="); pw.print(numFullscreen);
- pw.print(" mTaskToReturnTo="); pw.println(mTaskToReturnTo);
- }
+ pw.print(prefix); pw.print("userId="); pw.print(userId);
+ pw.print(" creatorUid="); pw.print(creatorUid);
+ pw.print(" mCallingUid="); pw.print(mCallingUid);
+ pw.print(" mCallingPackage="); pw.println(mCallingPackage);
if (affinity != null) {
pw.print(prefix); pw.print("affinity="); pw.println(affinity);
}
@@ -991,6 +1030,17 @@
pw.print(prefix); pw.print("realActivity=");
pw.println(realActivity.flattenToShortString());
}
+ if (autoRemoveRecents || taskType != 0 || mTaskToReturnTo != 0 || numFullscreen != 0) {
+ pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents);
+ pw.print(" numFullscreen="); pw.print(numFullscreen);
+ pw.print(" taskType="); pw.print(taskType);
+ pw.print(" mTaskToReturnTo="); pw.println(mTaskToReturnTo);
+ }
+ if (rootWasReset || mNeverRelinquishIdentity || mReuseTask) {
+ pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset);
+ pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity);
+ pw.print(" mReuseTask="); pw.println(mReuseTask);
+ }
pw.print(prefix); pw.print("Activities="); pw.println(mActivities);
if (!askedCompatMode) {
pw.print(prefix); pw.print("askedCompatMode="); pw.println(askedCompatMode);
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 4eb2ef1..5a97aee 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -40,7 +40,7 @@
*/
public class NetworkAgentInfo {
public NetworkInfo networkInfo;
- public final Network network;
+ public Network network;
public LinkProperties linkProperties;
public NetworkCapabilities networkCapabilities;
public int currentScore;
@@ -55,12 +55,12 @@
public final Messenger messenger;
public final AsyncChannel asyncChannel;
- public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, int netId, NetworkInfo info,
+ public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, NetworkInfo info,
LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler,
NetworkMisc misc) {
this.messenger = messenger;
asyncChannel = ac;
- network = new Network(netId);
+ network = null;
networkInfo = info;
linkProperties = lp;
networkCapabilities = nc;
@@ -87,6 +87,7 @@
public String name() {
return "NetworkAgentInfo [" + networkInfo.getTypeName() + " (" +
- networkInfo.getSubtypeName() + ") - " + network.toString() + "]";
+ networkInfo.getSubtypeName() + ") - " +
+ (network == null ? "null" : network.toString()) + "]";
}
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 5057994..9f4ed89 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -272,23 +272,22 @@
case CMD_NETWORK_LINGER:
if (DBG) log("Lingering");
transitionTo(mLingeringState);
- break;
+ return HANDLED;
case CMD_NETWORK_CONNECTED:
if (DBG) log("Connected");
transitionTo(mEvaluatingState);
- break;
+ return HANDLED;
case CMD_NETWORK_DISCONNECTED:
if (DBG) log("Disconnected - quitting");
quit();
- break;
+ return HANDLED;
case CMD_FORCE_REEVALUATION:
if (DBG) log("Forcing reevaluation");
transitionTo(mEvaluatingState);
- break;
+ return HANDLED;
default:
- break;
+ return HANDLED;
}
- return HANDLED;
}
}
@@ -314,11 +313,10 @@
switch (message.what) {
case CMD_NETWORK_CONNECTED:
transitionTo(mValidatedState);
- break;
+ return HANDLED;
default:
return NOT_HANDLED;
}
- return HANDLED;
}
}
@@ -347,23 +345,25 @@
switch (message.what) {
case CMD_REEVALUATE:
if (message.arg1 != mReevaluateToken)
- break;
+ return HANDLED;
if (mNetworkAgentInfo.isVPN()) {
transitionTo(mValidatedState);
+ return HANDLED;
}
// If network provides no internet connectivity adjust evaluation.
if (!mNetworkAgentInfo.networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
// TODO: Try to verify something works. Do all gateways respond to pings?
transitionTo(mValidatedState);
+ return HANDLED;
}
// Kick off a thread to perform internet connectivity evaluation.
Thread thread = new EvaluateInternetConnectivity(mReevaluateToken);
thread.run();
- break;
+ return HANDLED;
case EVENT_REEVALUATION_COMPLETE:
if (message.arg1 != mReevaluateToken)
- break;
+ return HANDLED;
int httpResponseCode = message.arg2;
if (httpResponseCode == 204) {
transitionTo(mValidatedState);
@@ -375,11 +375,10 @@
Message msg = obtainMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
sendMessageDelayed(msg, mReevaluateDelayMs);
}
- break;
+ return HANDLED;
default:
return NOT_HANDLED;
}
- return HANDLED;
}
}
@@ -432,17 +431,16 @@
switch (message.what) {
case EVENT_APP_BYPASSED_CAPTIVE_PORTAL:
transitionTo(mValidatedState);
- break;
+ return HANDLED;
case EVENT_APP_INDICATES_SIGN_IN_IMPOSSIBLE:
transitionTo(mOfflineState);
- break;
+ return HANDLED;
case EVENT_NO_APP_RESPONSE:
transitionTo(mUserPromptedState);
- break;
+ return HANDLED;
default:
return NOT_HANDLED;
}
- return HANDLED;
}
public void exit() {
mReceiver.cancel();
@@ -488,13 +486,12 @@
switch (message.what) {
case CMD_USER_WANTS_SIGN_IN:
if (message.arg1 != mUserPromptedToken)
- break;
+ return HANDLED;
transitionTo(mInteractiveAppsPromptedState);
- break;
+ return HANDLED;
default:
return NOT_HANDLED;
}
- return HANDLED;
}
@Override
@@ -520,17 +517,16 @@
switch (message.what) {
case EVENT_APP_BYPASSED_CAPTIVE_PORTAL:
transitionTo(mValidatedState);
- break;
+ return HANDLED;
case EVENT_APP_INDICATES_SIGN_IN_IMPOSSIBLE:
transitionTo(mOfflineState);
- break;
+ return HANDLED;
case EVENT_NO_APP_RESPONSE:
transitionTo(mCaptivePortalState);
- break;
+ return HANDLED;
default:
return NOT_HANDLED;
}
- return HANDLED;
}
public void exit() {
mReceiver.cancel();
@@ -581,18 +577,17 @@
switch (message.what) {
case CMD_CAPTIVE_PORTAL_LOGGED_IN:
if (message.arg1 != mCaptivePortalLoggedInToken)
- break;
+ return HANDLED;
if (message.arg2 == 0) {
// TODO: Should teardown network.
transitionTo(mOfflineState);
} else {
transitionTo(mValidatedState);
}
- break;
+ return HANDLED;
default:
return NOT_HANDLED;
}
- return HANDLED;
}
@Override
@@ -616,17 +611,16 @@
case CMD_NETWORK_CONNECTED:
// Go straight to active as we've already evaluated.
transitionTo(mValidatedState);
- break;
+ return HANDLED;
case CMD_LINGER_EXPIRED:
if (message.arg1 != mLingerToken)
- break;
+ return HANDLED;
mConnectivityServiceHandler.sendMessage(
obtainMessage(EVENT_NETWORK_LINGER_COMPLETE, mNetworkAgentInfo));
- break;
+ return HANDLED;
default:
return NOT_HANDLED;
}
- return HANDLED;
}
}
@@ -645,8 +639,7 @@
log("Checking " + url.toString() + " on " +
mNetworkAgentInfo.networkInfo.getExtraInfo());
}
- url = mNetworkAgentInfo.network.getBoundURL(url);
- urlConnection = (HttpURLConnection) url.openConnection();
+ urlConnection = (HttpURLConnection) mNetworkAgentInfo.network.openConnection(url);
urlConnection.setInstanceFollowRedirects(false);
urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
@@ -775,6 +768,7 @@
latencyBroadcast.putExtra(EXTRA_IS_CAPTIVE_PORTAL, isCaptivePortal);
latencyBroadcast.putExtra(EXTRA_RESPONSE_TIMESTAMP_MS, responseTimestampMs);
}
- mContext.sendBroadcast(latencyBroadcast, PERMISSION_ACCESS_NETWORK_CONDITIONS);
+ mContext.sendBroadcastAsUser(latencyBroadcast, UserHandle.CURRENT,
+ PERMISSION_ACCESS_NETWORK_CONDITIONS);
}
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 0f6b3ad..69caab9 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -21,9 +21,7 @@
import static android.system.OsConstants.AF_INET6;
import android.app.AppGlobals;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
+import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -35,10 +33,6 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.net.BaseNetworkStateTracker;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver;
@@ -51,7 +45,6 @@
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkMisc;
-import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.net.UidRange;
import android.os.Binder;
@@ -70,15 +63,15 @@
import android.security.Credentials;
import android.security.KeyStore;
import android.util.Log;
-import android.util.SparseBooleanArray;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.R;
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnProfile;
import com.android.server.net.BaseNetworkObserver;
+import libcore.io.IoUtils;
+
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -92,8 +85,6 @@
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
-import libcore.io.IoUtils;
-
/**
* @hide
*/
@@ -114,8 +105,6 @@
private boolean mAllowIPv6;
private Connection mConnection;
private LegacyVpnRunner mLegacyVpnRunner;
- private PendingIntent mStatusIntent;
- private volatile boolean mEnableNotif = true;
private volatile boolean mEnableTeardown = true;
private final IConnectivityManager mConnService;
private final INetworkManagementService mNetd;
@@ -180,14 +169,6 @@
}
/**
- * Set if this object is responsible for showing its own notifications. When
- * {@code false}, notifications are handled externally by someone else.
- */
- public void setEnableNotifications(boolean enableNotif) {
- mEnableNotif = enableNotif;
- }
-
- /**
* Set if this object is responsible for watching for {@link NetworkInfo}
* teardown. When {@code false}, teardown is handled externally by someone
* else.
@@ -228,6 +209,20 @@
public synchronized boolean prepare(String oldPackage, String newPackage) {
// Return false if the package does not match.
if (oldPackage != null && !oldPackage.equals(mPackage)) {
+ // The package doesn't match. If this VPN was not previously authorized, return false
+ // to force user authorization. Otherwise, revoke the VPN anyway.
+ if (!oldPackage.equals(VpnConfig.LEGACY_VPN) && isVpnUserPreConsented(oldPackage)) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ // This looks bizarre, but it is what ConfirmDialog in VpnDialogs is doing when
+ // the user clicks through to allow the VPN to consent. So we are emulating the
+ // action of the dialog without actually showing it.
+ prepare(null, oldPackage);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return true;
+ }
return false;
}
@@ -240,11 +235,8 @@
// Check if the caller is authorized.
enforceControlPermission();
- // Reset the interface and hide the notification.
+ // Reset the interface.
if (mInterface != null) {
- for (UidRange uidRange : mVpnUsers) {
- hideNotification(uidRange.getStartUser());
- }
agentDisconnect();
jniReset(mInterface);
mInterface = null;
@@ -287,12 +279,46 @@
Binder.restoreCallingIdentity(token);
}
mConfig = null;
+
updateState(DetailedState.IDLE, "prepare");
return true;
}
+ /**
+ * Set whether the current package has the ability to launch VPNs without user intervention.
+ */
+ public void setPackageAuthorization(boolean authorized) {
+ // Check if the caller is authorized.
+ enforceControlPermission();
+
+ if (mPackage == null || VpnConfig.LEGACY_VPN.equals(mPackage)) {
+ return;
+ }
+
+ long token = Binder.clearCallingIdentity();
+ try {
+ AppOpsManager appOps =
+ (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
+ appOps.setMode(AppOpsManager.OP_ACTIVATE_VPN, mOwnerUID, mPackage,
+ authorized ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
+ } catch (Exception e) {
+ Log.wtf(TAG, "Failed to set app ops for package " + mPackage, e);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private boolean isVpnUserPreConsented(String packageName) {
+ AppOpsManager appOps =
+ (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
+
+ // Verify that the caller matches the given package and has permission to activate VPNs.
+ return appOps.noteOpNoThrow(AppOpsManager.OP_ACTIVATE_VPN, Binder.getCallingUid(),
+ packageName) == AppOpsManager.MODE_ALLOWED;
+ }
+
private int getAppUid(String app) {
- if (app == VpnConfig.LEGACY_VPN) {
+ if (VpnConfig.LEGACY_VPN.equals(app)) {
return Process.myUid();
}
PackageManager pm = mContext.getPackageManager();
@@ -355,9 +381,10 @@
try {
mNetworkAgent = new NetworkAgent(mLooper, mContext, NETWORKTYPE,
mNetworkInfo, mNetworkCapabilities, lp, 0, networkMisc) {
+ @Override
public void unwanted() {
// We are user controlled, not driven by NetworkRequest.
- };
+ }
};
} finally {
Binder.restoreCallingIdentity(token);
@@ -540,39 +567,6 @@
// add the user
mVpnUsers.add(UidRange.createForUser(user));
-
- // show the notification
- if (!mPackage.equals(VpnConfig.LEGACY_VPN)) {
- // Load everything for the user's notification
- PackageManager pm = mContext.getPackageManager();
- ApplicationInfo app = null;
- final long token = Binder.clearCallingIdentity();
- try {
- app = AppGlobals.getPackageManager().getApplicationInfo(mPackage, 0, mUserId);
- } catch (RemoteException e) {
- throw new IllegalStateException("Invalid application");
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- String label = app.loadLabel(pm).toString();
- // Load the icon and convert it into a bitmap.
- Drawable icon = app.loadIcon(pm);
- Bitmap bitmap = null;
- if (icon.getIntrinsicWidth() > 0 && icon.getIntrinsicHeight() > 0) {
- int width = mContext.getResources().getDimensionPixelSize(
- android.R.dimen.notification_large_icon_width);
- int height = mContext.getResources().getDimensionPixelSize(
- android.R.dimen.notification_large_icon_height);
- icon.setBounds(0, 0, width, height);
- bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- Canvas c = new Canvas(bitmap);
- icon.draw(c);
- c.setBitmap(null);
- }
- showNotification(label, bitmap, user);
- } else {
- showNotification(null, null, user);
- }
}
private void removeVpnUserLocked(int user) {
@@ -584,7 +578,6 @@
mNetworkAgent.removeUidRanges(new UidRange[] { uidRange });
}
mVpnUsers.remove(uidRange);
- hideNotification(user);
}
private void onUserAdded(int userId) {
@@ -652,9 +645,6 @@
public void interfaceRemoved(String interfaze) {
synchronized (Vpn.this) {
if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) {
- for (UidRange uidRange : mVpnUsers) {
- hideNotification(uidRange.getStartUser());
- }
mVpnUsers = null;
mInterface = null;
if (mConnection != null) {
@@ -712,56 +702,6 @@
}
}
- private void showNotification(String label, Bitmap icon, int user) {
- if (!mEnableNotif) return;
- final long token = Binder.clearCallingIdentity();
- try {
- mStatusIntent = VpnConfig.getIntentForStatusPanel(mContext);
-
- NotificationManager nm = (NotificationManager)
- mContext.getSystemService(Context.NOTIFICATION_SERVICE);
-
- if (nm != null) {
- String title = (label == null) ? mContext.getString(R.string.vpn_title) :
- mContext.getString(R.string.vpn_title_long, label);
- String text = (mConfig.session == null) ? mContext.getString(R.string.vpn_text) :
- mContext.getString(R.string.vpn_text_long, mConfig.session);
-
- Notification notification = new Notification.Builder(mContext)
- .setSmallIcon(R.drawable.vpn_connected)
- .setLargeIcon(icon)
- .setContentTitle(title)
- .setContentText(text)
- .setContentIntent(mStatusIntent)
- .setDefaults(0)
- .setOngoing(true)
- .setColor(mContext.getResources().getColor(
- com.android.internal.R.color.system_notification_accent_color))
- .build();
- nm.notifyAsUser(null, R.drawable.vpn_connected, notification, new UserHandle(user));
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- private void hideNotification(int user) {
- if (!mEnableNotif) return;
- mStatusIntent = null;
-
- NotificationManager nm = (NotificationManager)
- mContext.getSystemService(Context.NOTIFICATION_SERVICE);
-
- if (nm != null) {
- final long token = Binder.clearCallingIdentity();
- try {
- nm.cancelAsUser(null, R.drawable.vpn_connected, new UserHandle(user));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- }
-
public synchronized boolean addAddress(String address, int prefixLength) {
if (Binder.getCallingUid() != mOwnerUID || mInterface == null || mNetworkAgent == null) {
return false;
@@ -971,9 +911,6 @@
final LegacyVpnInfo info = new LegacyVpnInfo();
info.key = mConfig.user;
info.state = LegacyVpnInfo.stateFromNetworkInfo(mNetworkInfo);
- if (mNetworkInfo.isConnected()) {
- info.intent = mStatusIntent;
- }
return info;
}
@@ -1263,6 +1200,7 @@
}
} catch (Exception e) {
Log.i(TAG, "Aborting", e);
+ updateState(DetailedState.FAILED, e.getMessage());
exit();
} finally {
// Kill the daemons if they fail to stop.
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 46cb6c3..2a1ceaa 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -87,7 +87,7 @@
private static final int SCREEN_DIM_MINIMUM_REDUCTION = 10;
private static final int COLOR_FADE_ON_ANIMATION_DURATION_MILLIS = 250;
- private static final int COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS = 600;
+ private static final int COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS = 400;
private static final int MSG_UPDATE_POWER_STATE = 1;
private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index b43ad1b..a12e4fc 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -691,6 +691,7 @@
mActiveSource.logicalAddress = logicalAddress;
mActiveSource.physicalAddress = physicalAddress;
}
+ mService.setLastInputForMhl(Constants.INVALID_PORT_ID);
}
int getActivePath() {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 73f5cfd..4e8c46f 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -112,6 +112,10 @@
private final HdmiCecStandbyModeHandler mStandbyHandler;
+ // If true, do not do routing control/send active source for internal source.
+ // Set to true when the device was woken up by <Text/Image View On>.
+ private boolean mSkipRoutingControl;
+
// Set of physical addresses of CEC switches on the CEC bus. Managed independently from
// other CEC devices since they might not have logical address.
private final ArraySet<Integer> mCecSwitches = new ArraySet<Integer>();
@@ -134,6 +138,7 @@
mService.sendCecCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
mAddress, mService.getVendorId()));
mCecSwitches.add(mService.getPhysicalAddress()); // TV is a CEC switch too.
+ mSkipRoutingControl = (reason == HdmiControlService.INITIATED_BY_WAKE_UP_MESSAGE);
launchRoutingControl(reason != HdmiControlService.INITIATED_BY_ENABLE_CEC &&
reason != HdmiControlService.INITIATED_BY_BOOT_UP);
launchDeviceDiscovery();
@@ -207,7 +212,10 @@
// Seq #18
if (mService.isControlEnabled() && mActiveSource.logicalAddress != mAddress) {
updateActiveSource(mAddress, mService.getPhysicalAddress());
- // TODO: Check if this comes from <Text/Image View On> - if true, do nothing.
+ if (mSkipRoutingControl) {
+ mSkipRoutingControl = false;
+ return;
+ }
HdmiCecMessage activeSource = HdmiCecMessageBuilder.buildActiveSource(
mAddress, mService.getPhysicalAddress());
mService.sendCecCommand(activeSource);
@@ -304,17 +312,19 @@
invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE);
return;
}
- // TODO: Return immediately if the operation is triggered by <Text/Image View On>
- // and this is the first notification about the active input after power-on
- // (switch to HDMI didn't happen so far but is expected to happen soon).
int oldPath = getActivePortId() != Constants.INVALID_PORT_ID
? mService.portIdToPath(getActivePortId()) : getDeviceInfo().getPhysicalAddress();
+ setActivePath(oldPath);
+ if (mSkipRoutingControl) {
+ mSkipRoutingControl = false;
+ return;
+ }
int newPath = mService.portIdToPath(portId);
HdmiCecMessage routingChange =
HdmiCecMessageBuilder.buildRoutingChange(mAddress, oldPath, newPath);
mService.sendCecCommand(routingChange);
removeAction(RoutingControlAction.class);
- addAndStartAction(new RoutingControlAction(this, newPath, false, callback));
+ addAndStartAction(new RoutingControlAction(this, newPath, true, callback));
}
int getPowerStatus() {
@@ -566,8 +576,6 @@
if (mService.isPowerStandbyOrTransient() && mAutoWakeup) {
mService.wakeUp();
}
- // TODO: Connect to Hardware input manager to invoke TV App with the appropriate channel
- // that represents the source device.
return true;
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
index 4c88ce0..8b345cf 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
@@ -17,7 +17,6 @@
package com.android.server.hdmi;
import android.hardware.hdmi.HdmiDeviceInfo;
-import android.util.Slog;
import android.util.SparseArray;
/**
@@ -52,6 +51,7 @@
}
final SparseArray<ValidationInfo> mValidationInfo = new SparseArray<>();
+ private final HdmiLogger mSpamSafeLogger = new HdmiLogger(TAG);
public HdmiCecMessageValidator(HdmiControlService service) {
mService = service;
@@ -183,32 +183,32 @@
int opcode = message.getOpcode();
ValidationInfo info = mValidationInfo.get(opcode);
if (info == null) {
- Slog.w(TAG, "No validation information for the message: " + message);
+ mSpamSafeLogger.warning("No validation information for the message: " + message);
return true;
}
// Check the source field.
if (message.getSource() == Constants.ADDR_UNREGISTERED &&
(info.addressType & SRC_UNREGISTERED) == 0) {
- Slog.w(TAG, "Unexpected source: " + message);
+ mSpamSafeLogger.warning("Unexpected source: " + message);
return false;
}
// Check the destination field.
if (message.getDestination() == Constants.ADDR_BROADCAST) {
if ((info.addressType & DEST_BROADCAST) == 0) {
- Slog.w(TAG, "Unexpected broadcast message: " + message);
+ mSpamSafeLogger.warning("Unexpected broadcast message: " + message);
return false;
}
} else { // Direct addressing.
if ((info.addressType & DEST_DIRECT) == 0) {
- Slog.w(TAG, "Unexpected direct message: " + message);
+ mSpamSafeLogger.warning("Unexpected direct message: " + message);
return false;
}
}
// Check the parameter type.
if (!info.parameterValidator.isValid(message.getParams())) {
- Slog.w(TAG, "Unexpected parameters: " + message);
+ mSpamSafeLogger.warning("Unexpected parameters: " + message);
return false;
}
return true;
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 5b99f14..3dabc11 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -43,6 +43,7 @@
import android.hardware.hdmi.IHdmiDeviceEventListener;
import android.hardware.hdmi.IHdmiHotplugEventListener;
import android.hardware.hdmi.IHdmiInputChangeListener;
+import android.hardware.hdmi.IHdmiMhlScratchpadCommandListener;
import android.hardware.hdmi.IHdmiRecordListener;
import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener;
import android.hardware.hdmi.IHdmiVendorCommandListener;
@@ -159,41 +160,32 @@
// Type of logical devices hosted in the system. Stored in the unmodifiable list.
private final List<Integer> mLocalDevices;
- // List of listeners registered by callers that want to get notified of
- // hotplug events.
- @GuardedBy("mLock")
- private final ArrayList<IHdmiHotplugEventListener> mHotplugEventListeners = new ArrayList<>();
+ private final HdmiLogger mSpamSafeLogger = new HdmiLogger(TAG);
// List of records for hotplug event listener to handle the the caller killed in action.
@GuardedBy("mLock")
private final ArrayList<HotplugEventListenerRecord> mHotplugEventListenerRecords =
new ArrayList<>();
- // List of listeners registered by callers that want to get notified of
- // device status events.
- @GuardedBy("mLock")
- private final ArrayList<IHdmiDeviceEventListener> mDeviceEventListeners = new ArrayList<>();
-
- // List of records for device event listener to handle the the caller killed in action.
+ // List of records for device event listener to handle the caller killed in action.
@GuardedBy("mLock")
private final ArrayList<DeviceEventListenerRecord> mDeviceEventListenerRecords =
new ArrayList<>();
- // List of records for vendor command listener to handle the the caller killed in action.
+ // List of records for vendor command listener to handle the caller killed in action.
@GuardedBy("mLock")
private final ArrayList<VendorCommandListenerRecord> mVendorCommandListenerRecords =
new ArrayList<>();
+ // List of records for MHL Scratchpad command listener to handle the caller killed in action.
@GuardedBy("mLock")
- private IHdmiInputChangeListener mInputChangeListener;
+ private final ArrayList<HdmiMhlScratchpadCommandListenerRecord>
+ mScratchpadCommandListenerRecords = new ArrayList<>();
@GuardedBy("mLock")
private InputChangeListenerRecord mInputChangeListenerRecord;
@GuardedBy("mLock")
- private IHdmiRecordListener mRecordListener;
-
- @GuardedBy("mLock")
private HdmiRecordListenerRecord mRecordListenerRecord;
// Set to true while HDMI control is enabled. If set to false, HDMI-CEC/MHL protocol
@@ -214,10 +206,6 @@
@GuardedBy("mLock")
private List<HdmiDeviceInfo> mMhlDevices;
- // List of listeners registered by callers that want to get notified of
- // system audio mode changes.
- private final ArrayList<IHdmiSystemAudioModeChangeListener>
- mSystemAudioModeChangeListeners = new ArrayList<>();
// List of records for system audio mode change to handle the the caller killed in action.
private final ArrayList<SystemAudioModeChangeListenerRecord>
mSystemAudioModeChangeListenerRecords = new ArrayList<>();
@@ -227,6 +215,9 @@
private final SettingsObserver mSettingsObserver;
+ private final HdmiControlBroadcastReceiver
+ mHdmiControlBroadcastReceiver = new HdmiControlBroadcastReceiver();
+
@Nullable
private HdmiCecController mCecController;
@@ -243,10 +234,10 @@
// Map from port ID to HdmiPortInfo.
private UnmodifiableSparseArray<HdmiPortInfo> mPortInfoMap;
- private HdmiCecMessageValidator mMessageValidator;
+ // Map from port ID to HdmiDeviceInfo.
+ private UnmodifiableSparseArray<HdmiDeviceInfo> mPortDeviceMap;
- private final HdmiControlBroadcastReceiver
- mHdmiControlBroadcastReceiver = new HdmiControlBroadcastReceiver();
+ private HdmiCecMessageValidator mMessageValidator;
@ServiceThreadOnly
private int mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
@@ -263,6 +254,12 @@
@ServiceThreadOnly
private int mActivePortId = Constants.INVALID_PORT_ID;
+ // Last input port before switching to the MHL port by way of incoming request RAP[ContentOn].
+ // Should switch back to this port when the device sends RAP[ContentOff].
+ // Gets invalidated if we go to other port/input.
+ @ServiceThreadOnly
+ private int mLastInputMhl = Constants.INVALID_PORT_ID;
+
public HdmiControlService(Context context) {
super(context);
mLocalDevices = getIntList(SystemProperties.get(Constants.PROPERTY_DEVICE_TYPE));
@@ -474,12 +471,15 @@
SparseArray<HdmiPortInfo> portInfoMap = new SparseArray<>();
SparseIntArray portIdMap = new SparseIntArray();
+ SparseArray<HdmiDeviceInfo> portDeviceMap = new SparseArray<>();
for (HdmiPortInfo info : cecPortInfo) {
portIdMap.put(info.getAddress(), info.getId());
portInfoMap.put(info.getId(), info);
+ portDeviceMap.put(info.getId(), new HdmiDeviceInfo(info.getAddress(), info.getId()));
}
mPortIdMap = new UnmodifiableSparseIntArray(portIdMap);
mPortInfoMap = new UnmodifiableSparseArray<>(portInfoMap);
+ mPortDeviceMap = new UnmodifiableSparseArray<>(portDeviceMap);
if (mMhlController == null) {
mPortInfo = Collections.unmodifiableList(Arrays.asList(cecPortInfo));
@@ -636,7 +636,7 @@
if (mMessageValidator.isValid(command)) {
mCecController.sendCommand(command, callback);
} else {
- Slog.e(TAG, "Invalid message type:" + command);
+ mSpamSafeLogger.error("Invalid message type:" + command);
if (callback != null) {
callback.onSendCompleted(Constants.SEND_RESULT_FAILURE);
}
@@ -697,7 +697,7 @@
}
if (message.getDestination() != Constants.ADDR_BROADCAST) {
- Slog.w(TAG, "Unhandled cec command:" + message);
+ mSpamSafeLogger.warning("Unhandled cec command:" + message);
}
return false;
}
@@ -776,8 +776,11 @@
}
void announceSystemAudioModeChange(boolean enabled) {
- for (IHdmiSystemAudioModeChangeListener listener : mSystemAudioModeChangeListeners) {
- invokeSystemAudioModeChange(listener, enabled);
+ synchronized (mLock) {
+ for (SystemAudioModeChangeListenerRecord record :
+ mSystemAudioModeChangeListenerRecords) {
+ invokeSystemAudioModeChangeLocked(record.mListener, enabled);
+ }
}
}
@@ -902,7 +905,6 @@
public void binderDied() {
synchronized (mLock) {
mHotplugEventListenerRecords.remove(this);
- mHotplugEventListeners.remove(mListener);
}
}
}
@@ -918,7 +920,6 @@
public void binderDied() {
synchronized (mLock) {
mDeviceEventListenerRecords.remove(this);
- mDeviceEventListeners.remove(mListener);
}
}
}
@@ -934,7 +935,6 @@
public void binderDied() {
synchronized (mLock) {
mSystemAudioModeChangeListenerRecords.remove(this);
- mSystemAudioModeChangeListeners.remove(mListener);
}
}
}
@@ -957,14 +957,33 @@
}
private class HdmiRecordListenerRecord implements IBinder.DeathRecipient {
+ private final IHdmiRecordListener mListener;
+
+ public HdmiRecordListenerRecord(IHdmiRecordListener listener) {
+ mListener = listener;
+ }
+
@Override
public void binderDied() {
synchronized (mLock) {
- mRecordListener = null;
+ mRecordListenerRecord = null;
}
}
}
+ private class HdmiMhlScratchpadCommandListenerRecord implements IBinder.DeathRecipient {
+ private final IHdmiMhlScratchpadCommandListener mListener;
+
+ public HdmiMhlScratchpadCommandListenerRecord(IHdmiMhlScratchpadCommandListener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public void binderDied() {
+ mScratchpadCommandListenerRecords.remove(this);
+ }
+ }
+
private void enforceAccessPermission() {
getContext().enforceCallingOrSelfPermission(PERMISSION, TAG);
}
@@ -1020,6 +1039,10 @@
if (mMhlController != null) {
HdmiMhlLocalDevice device = mMhlController.getLocalDeviceById(deviceId);
if (device != null) {
+ if (device.getPortId() == tv.getActivePortId()) {
+ invokeCallback(callback, HdmiControlManager.RESULT_SUCCESS);
+ return;
+ }
// Upon selecting MHL device, we send RAP[Content On] to wake up
// the connected mobile device, start routing control to switch ports.
// callback is handled by MHL action.
@@ -1104,34 +1127,19 @@
@Override
public void addHotplugEventListener(final IHdmiHotplugEventListener listener) {
enforceAccessPermission();
- runOnServiceThread(new Runnable() {
- @Override
- public void run() {
- HdmiControlService.this.addHotplugEventListener(listener);
- }
- });
+ HdmiControlService.this.addHotplugEventListener(listener);
}
@Override
public void removeHotplugEventListener(final IHdmiHotplugEventListener listener) {
enforceAccessPermission();
- runOnServiceThread(new Runnable() {
- @Override
- public void run() {
- HdmiControlService.this.removeHotplugEventListener(listener);
- }
- });
+ HdmiControlService.this.removeHotplugEventListener(listener);
}
@Override
public void addDeviceEventListener(final IHdmiDeviceEventListener listener) {
enforceAccessPermission();
- runOnServiceThread(new Runnable() {
- @Override
- public void run() {
- HdmiControlService.this.addDeviceEventListener(listener);
- }
- });
+ HdmiControlService.this.addDeviceEventListener(listener);
}
@Override
@@ -1272,12 +1280,7 @@
public void addVendorCommandListener(final IHdmiVendorCommandListener listener,
final int deviceType) {
enforceAccessPermission();
- runOnServiceThread(new Runnable() {
- @Override
- public void run() {
- HdmiControlService.this.addVendorCommandListener(listener, deviceType);
- }
- });
+ HdmiControlService.this.addVendorCommandListener(listener, deviceType);
}
@Override
@@ -1366,6 +1369,38 @@
}
});
}
+
+ @Override
+ public void sendScratchpadCommand(final int portId, final int offset, final int length,
+ final byte[] data) {
+ enforceAccessPermission();
+ runOnServiceThread(new Runnable() {
+ @Override
+ public void run() {
+ if (mMhlController == null) {
+ Slog.w(TAG, "No Mhl controller available.");
+ return;
+ }
+ if (!isControlEnabled()) {
+ Slog.w(TAG, "Hdmi control is disabled.");
+ return ;
+ }
+ HdmiMhlLocalDevice device = mMhlController.getLocalDevice(portId);
+ if (device == null) {
+ Slog.w(TAG, "Invalid port id:" + portId);
+ return;
+ }
+ mMhlController.sendScratchpadCommand(portId, offset, length, data);
+ }
+ });
+ }
+
+ @Override
+ public void addHdmiMhlScratchpadCommandListener(
+ IHdmiMhlScratchpadCommandListener listener) {
+ enforceAccessPermission();
+ HdmiControlService.this.addHdmiMhlScratchpadCommandListener(listener);
+ }
}
@ServiceThreadOnly
@@ -1402,7 +1437,6 @@
}
synchronized (mLock) {
mHotplugEventListenerRecords.add(record);
- mHotplugEventListeners.add(listener);
}
}
@@ -1415,7 +1449,6 @@
break;
}
}
- mHotplugEventListeners.remove(listener);
}
}
@@ -1428,16 +1461,15 @@
return;
}
synchronized (mLock) {
- mDeviceEventListeners.add(listener);
mDeviceEventListenerRecords.add(record);
}
}
void invokeDeviceEventListeners(HdmiDeviceInfo device, int status) {
synchronized (mLock) {
- for (IHdmiDeviceEventListener listener : mDeviceEventListeners) {
+ for (DeviceEventListenerRecord record : mDeviceEventListenerRecords) {
try {
- listener.onStatusChanged(device, status);
+ record.mListener.onStatusChanged(device, status);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to report device event:" + e);
}
@@ -1455,7 +1487,6 @@
return;
}
synchronized (mLock) {
- mSystemAudioModeChangeListeners.add(listener);
mSystemAudioModeChangeListenerRecords.add(record);
}
}
@@ -1470,37 +1501,41 @@
break;
}
}
- mSystemAudioModeChangeListeners.remove(listener);
}
}
private final class InputChangeListenerRecord implements IBinder.DeathRecipient {
+ private final IHdmiInputChangeListener mListener;
+
+ public InputChangeListenerRecord(IHdmiInputChangeListener listener) {
+ mListener = listener;
+ }
+
@Override
public void binderDied() {
synchronized (mLock) {
- mInputChangeListener = null;
+ mInputChangeListenerRecord = null;
}
}
}
private void setInputChangeListener(IHdmiInputChangeListener listener) {
synchronized (mLock) {
- mInputChangeListenerRecord = new InputChangeListenerRecord();
+ mInputChangeListenerRecord = new InputChangeListenerRecord(listener);
try {
listener.asBinder().linkToDeath(mInputChangeListenerRecord, 0);
} catch (RemoteException e) {
Slog.w(TAG, "Listener already died");
return;
}
- mInputChangeListener = listener;
}
}
void invokeInputChangeListener(HdmiDeviceInfo info) {
synchronized (mLock) {
- if (mInputChangeListener != null) {
+ if (mInputChangeListenerRecord != null) {
try {
- mInputChangeListener.onChanged(info);
+ mInputChangeListenerRecord.mListener.onChanged(info);
} catch (RemoteException e) {
Slog.w(TAG, "Exception thrown by IHdmiInputChangeListener: " + e);
}
@@ -1510,21 +1545,20 @@
private void setHdmiRecordListener(IHdmiRecordListener listener) {
synchronized (mLock) {
- mRecordListenerRecord = new HdmiRecordListenerRecord();
+ mRecordListenerRecord = new HdmiRecordListenerRecord(listener);
try {
listener.asBinder().linkToDeath(mRecordListenerRecord, 0);
} catch (RemoteException e) {
Slog.w(TAG, "Listener already died.", e);
}
- mRecordListener = listener;
}
}
byte[] invokeRecordRequestListener(int recorderAddress) {
synchronized (mLock) {
- if (mRecordListener != null) {
+ if (mRecordListenerRecord != null) {
try {
- return mRecordListener.getOneTouchRecordSource(recorderAddress);
+ return mRecordListenerRecord.mListener.getOneTouchRecordSource(recorderAddress);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to start record.", e);
}
@@ -1535,9 +1569,9 @@
void invokeOneTouchRecordResult(int result) {
synchronized (mLock) {
- if (mRecordListener != null) {
+ if (mRecordListenerRecord != null) {
try {
- mRecordListener.onOneTouchRecordResult(result);
+ mRecordListenerRecord.mListener.onOneTouchRecordResult(result);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onOneTouchRecordResult.", e);
}
@@ -1547,9 +1581,9 @@
void invokeTimerRecordingResult(int result) {
synchronized (mLock) {
- if (mRecordListener != null) {
+ if (mRecordListenerRecord != null) {
try {
- mRecordListener.onTimerRecordingResult(result);
+ mRecordListenerRecord.mListener.onTimerRecordingResult(result);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onTimerRecordingResult.", e);
}
@@ -1559,9 +1593,9 @@
void invokeClearTimerRecordingResult(int result) {
synchronized (mLock) {
- if (mRecordListener != null) {
+ if (mRecordListenerRecord != null) {
try {
- mRecordListener.onClearTimerRecordingResult(result);
+ mRecordListenerRecord.mListener.onClearTimerRecordingResult(result);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onClearTimerRecordingResult.", e);
}
@@ -1577,7 +1611,7 @@
}
}
- private void invokeSystemAudioModeChange(IHdmiSystemAudioModeChangeListener listener,
+ private void invokeSystemAudioModeChangeLocked(IHdmiSystemAudioModeChangeListener listener,
boolean enabled) {
try {
listener.onStatusChanged(enabled);
@@ -1589,8 +1623,8 @@
private void announceHotplugEvent(int portId, boolean connected) {
HdmiHotplugEvent event = new HdmiHotplugEvent(portId, connected);
synchronized (mLock) {
- for (IHdmiHotplugEventListener listener : mHotplugEventListeners) {
- invokeHotplugEventListenerLocked(listener, event);
+ for (HotplugEventListenerRecord record : mHotplugEventListenerRecords) {
+ invokeHotplugEventListenerLocked(record.mListener, event);
}
}
}
@@ -1789,6 +1823,34 @@
}
}
+ private void addHdmiMhlScratchpadCommandListener(IHdmiMhlScratchpadCommandListener listener) {
+ HdmiMhlScratchpadCommandListenerRecord record =
+ new HdmiMhlScratchpadCommandListenerRecord(listener);
+ try {
+ listener.asBinder().linkToDeath(record, 0);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Listener already died.");
+ return;
+ }
+
+ synchronized (mLock) {
+ mScratchpadCommandListenerRecords.add(record);
+ }
+ }
+
+ void invokeScratchpadCommandListeners(int portId, int offest, int length, byte[] data) {
+ synchronized (mLock) {
+ for (HdmiMhlScratchpadCommandListenerRecord record :
+ mScratchpadCommandListenerRecords) {
+ try {
+ record.mListener.onReceived(portId, offest, length, data);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to notify scratchpad command", e);
+ }
+ }
+ }
+ }
+
boolean isProhibitMode() {
synchronized (mLock) {
return mProhibitMode;
@@ -1838,9 +1900,60 @@
void setActivePortId(int portId) {
assertRunOnServiceThread();
mActivePortId = portId;
+
+ // Resets last input for MHL, which stays valid only after the MHL device was selected,
+ // and no further switching is done.
+ setLastInputForMhl(Constants.INVALID_PORT_ID);
}
- void setMhlInputChangeEnabled(boolean enabled) {
+ @ServiceThreadOnly
+ void setLastInputForMhl(int portId) {
+ assertRunOnServiceThread();
+ mLastInputMhl = portId;
+ }
+
+ @ServiceThreadOnly
+ int getLastInputForMhl() {
+ assertRunOnServiceThread();
+ return mLastInputMhl;
+ }
+
+ /**
+ * Performs input change, routing control for MHL device.
+ *
+ * @param portId MHL port, or the last port to go back to if {@code contentOn} is false
+ * @param contentOn {@code true} if RAP data is content on; otherwise false
+ */
+ @ServiceThreadOnly
+ void changeInputForMhl(int portId, boolean contentOn) {
+ assertRunOnServiceThread();
+ final int lastInput = contentOn ? tv().getActivePortId() : Constants.INVALID_PORT_ID;
+ tv().doManualPortSwitching(portId, new IHdmiControlCallback.Stub() {
+ @Override
+ public void onComplete(int result) throws RemoteException {
+ // Keep the last input to switch back later when RAP[ContentOff] is received.
+ // This effectively sets the port to invalid one if the switching is for
+ // RAP[ContentOff].
+ setLastInputForMhl(lastInput);
+ }
+ });
+
+ // MHL device is always directly connected to the port. Update the active port ID to avoid
+ // unnecessary post-routing control task.
+ tv().setActivePortId(portId);
+
+ // The port is either the MHL-enabled port where the mobile device is connected, or
+ // the last port to go back to when RAP[ContentOff] is received. Note that the last port
+ // may not be the MHL-enabled one. In this case the device info to be passed to
+ // input change listener should be the one describing the corresponding HDMI port.
+ HdmiMhlLocalDevice device = mMhlController.getLocalDevice(portId);
+ HdmiDeviceInfo info = (device != null && device.getInfo() != null)
+ ? device.getInfo()
+ : mPortDeviceMap.get(portId);
+ invokeInputChangeListener(info);
+ }
+
+ void setMhlInputChangeEnabled(boolean enabled) {
if (mMhlController != null) {
mMhlController.setOption(OPTION_MHL_INPUT_SWITCHING, toInt(enabled));
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiLogger.java b/services/core/java/com/android/server/hdmi/HdmiLogger.java
new file mode 100644
index 0000000..36159cb
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiLogger.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import android.os.SystemClock;
+import android.util.Pair;
+import android.util.Slog;
+
+import java.util.HashMap;
+
+/**
+ * A logger that prevents spammy log. For the same log message, it logs once every 20seconds.
+ * This class is not thread-safe.
+ */
+final class HdmiLogger {
+ // Logging duration for same error message.
+ private static final long ERROR_LOG_DURATTION_MILLIS = 20 * 1000; // 20s
+
+ // Key (String): log message.
+ // Value (Pair(Long, Integer)): a pair of last log time millis and the number of logMessage.
+ // Cache for warning.
+ private final HashMap<String, Pair<Long, Integer>> mWarningTimingCache = new HashMap<>();
+ // Cache for error.
+ private final HashMap<String, Pair<Long, Integer>> mErrorTimingCache = new HashMap<>();
+
+ private final String mTag;
+
+ HdmiLogger(String tag) {
+ mTag = tag;
+ }
+
+ void warning(String logMessage) {
+ long curTime = SystemClock.uptimeMillis();
+ Pair<Long, Integer> timing = mWarningTimingCache.get(logMessage);
+ if (shouldLogNow(timing, curTime)) {
+ Slog.w(mTag, buildMessage(logMessage, timing));
+ mWarningTimingCache.put(logMessage, new Pair<>(curTime, 1));
+ } else {
+ increaseLogCount(mWarningTimingCache, logMessage);
+ }
+ }
+
+ void error(String logMessage) {
+ long curTime = SystemClock.uptimeMillis();
+ Pair<Long, Integer> timing = mErrorTimingCache.get(logMessage);
+ if (shouldLogNow(timing, curTime)) {
+ Slog.e(mTag, buildMessage(logMessage, timing));
+ mErrorTimingCache.put(logMessage, new Pair<>(curTime, 1));
+ } else {
+ increaseLogCount(mErrorTimingCache, logMessage);
+ }
+ }
+
+ private String buildMessage(String message, Pair<Long, Integer> timing) {
+ return new StringBuilder()
+ .append("[").append(timing.second).append("]:").append(message)
+ .toString();
+ }
+
+ private void increaseLogCount(HashMap<String, Pair<Long, Integer>> cache, String message) {
+ Pair<Long, Integer> timing = cache.get(message);
+ if (timing != null) {
+ cache.put(message, new Pair<>(timing.first, timing.second + 1));
+ }
+ }
+
+ private boolean shouldLogNow(Pair<Long, Integer> timing, long curTime) {
+ return timing == null || curTime - timing.first > ERROR_LOG_DURATTION_MILLIS;
+ }
+}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 14457ec..6771cce 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -162,6 +162,7 @@
JobStatus jobStatus = new JobStatus(job, uId);
cancelJob(uId, job.getId());
startTrackingJob(jobStatus);
+ mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
return JobScheduler.RESULT_SUCCESS;
}
@@ -507,7 +508,9 @@
case MSG_JOB_EXPIRED:
synchronized (mJobs) {
JobStatus runNow = (JobStatus) message.obj;
- if (!mPendingJobs.contains(runNow)) {
+ // runNow can be null, which is a controller's way of indicating that its
+ // state is such that all ready jobs should be run immediately.
+ if (runNow != null && !mPendingJobs.contains(runNow)) {
mPendingJobs.add(runNow);
}
}
diff --git a/services/core/java/com/android/server/job/StateChangedListener.java b/services/core/java/com/android/server/job/StateChangedListener.java
index 90c203a..97dfad3 100644
--- a/services/core/java/com/android/server/job/StateChangedListener.java
+++ b/services/core/java/com/android/server/job/StateChangedListener.java
@@ -33,7 +33,8 @@
/**
* Called by the controller to notify the JobManager that regardless of the state of the task,
* it must be run immediately.
- * @param jobStatus The state of the task which is to be run immediately.
+ * @param jobStatus The state of the task which is to be run immediately. <strong>null
+ * indicates to the scheduler that any ready jobs should be flushed.</strong>
*/
public void onRunJobNow(JobStatus jobStatus);
}
diff --git a/services/core/java/com/android/server/job/controllers/BatteryController.java b/services/core/java/com/android/server/job/controllers/BatteryController.java
index 538a252..309e034 100644
--- a/services/core/java/com/android/server/job/controllers/BatteryController.java
+++ b/services/core/java/com/android/server/job/controllers/BatteryController.java
@@ -84,15 +84,15 @@
@Override
public void maybeStartTrackingJob(JobStatus taskStatus) {
+ final boolean isOnStablePower = mChargeTracker.isOnStablePower();
if (taskStatus.hasChargingConstraint()) {
- final boolean isOnStablePower = mChargeTracker.isOnStablePower();
synchronized (mTrackedTasks) {
mTrackedTasks.add(taskStatus);
taskStatus.chargingConstraintSatisfied.set(isOnStablePower);
}
- if (isOnStablePower) {
- mStateChangedListener.onControllerStateChanged();
- }
+ }
+ if (isOnStablePower) {
+ mChargeTracker.setStableChargingAlarm();
}
}
@@ -119,9 +119,15 @@
}
}
}
+ // Let the scheduler know that state has changed. This may or may not result in an
+ // execution.
if (reportChange) {
mStateChangedListener.onControllerStateChanged();
}
+ // Also tell the scheduler that any ready jobs should be flushed.
+ if (stablePower) {
+ mStateChangedListener.onRunJobNow(null);
+ }
}
public class ChargingTracker extends BroadcastReceiver {
@@ -196,9 +202,7 @@
}
// Set up an alarm for ACTION_CHARGING_STABLE - we don't want to kick off tasks
// here if the user unplugs the phone immediately.
- mAlarm.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- SystemClock.elapsedRealtime() + STABLE_CHARGING_THRESHOLD_MILLIS,
- mStableChargingTriggerIntent);
+ setStableChargingAlarm();
mCharging = true;
} else if (Intent.ACTION_POWER_DISCONNECTED.equals(action)) {
if (DEBUG) {
@@ -211,7 +215,7 @@
}else if (ACTION_CHARGING_STABLE.equals(action)) {
// Here's where we actually do the notify for a task being ready.
if (DEBUG) {
- Slog.d(TAG, "Battery connected fired @ " + SystemClock.elapsedRealtime()
+ Slog.d(TAG, "Stable charging fired @ " + SystemClock.elapsedRealtime()
+ " charging: " + mCharging);
}
if (mCharging) { // Should never receive this intent if mCharging is false.
@@ -219,6 +223,17 @@
}
}
}
+
+ void setStableChargingAlarm() {
+ final long alarmTriggerElapsed =
+ SystemClock.elapsedRealtime() + STABLE_CHARGING_THRESHOLD_MILLIS;
+ if (DEBUG) {
+ Slog.d(TAG, "Setting stable alarm to go off in " +
+ (STABLE_CHARGING_THRESHOLD_MILLIS / 1000) + "s");
+ }
+ mAlarm.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTriggerElapsed,
+ mStableChargingTriggerIntent);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 84027e2..978a9f4 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -31,6 +31,7 @@
import android.media.session.ISessionController;
import android.media.session.ISessionControllerCallback;
import android.media.session.MediaController;
+import android.media.session.MediaController.PlaybackInfo;
import android.media.session.MediaSession;
import android.media.session.ParcelableVolumeInfo;
import android.media.session.PlaybackState;
@@ -111,7 +112,7 @@
private AudioAttributes mAudioAttrs;
private AudioManager mAudioManager;
private AudioManagerInternal mAudioManagerInternal;
- private int mVolumeType = MediaSession.PLAYBACK_TYPE_LOCAL;
+ private int mVolumeType = PlaybackInfo.PLAYBACK_TYPE_LOCAL;
private int mVolumeControlType = VolumeProvider.VOLUME_CONTROL_ABSOLUTE;
private int mMaxVolume = 0;
private int mCurrentVolume = 0;
@@ -237,7 +238,7 @@
} else if (direction < -1) {
direction = -1;
}
- if (mVolumeType == MediaSession.PLAYBACK_TYPE_LOCAL) {
+ if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags, packageName,
uid);
@@ -265,7 +266,7 @@
}
public void setVolumeTo(int value, int flags, String packageName, int uid) {
- if (mVolumeType == MediaSession.PLAYBACK_TYPE_LOCAL) {
+ if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
mAudioManagerInternal.setStreamVolumeForUid(stream, value, flags, packageName, uid);
} else {
@@ -748,8 +749,8 @@
public void setPlaybackToLocal(AudioAttributes attributes) {
boolean typeChanged;
synchronized (mLock) {
- typeChanged = mVolumeType == MediaSession.PLAYBACK_TYPE_REMOTE;
- mVolumeType = MediaSession.PLAYBACK_TYPE_LOCAL;
+ typeChanged = mVolumeType == PlaybackInfo.PLAYBACK_TYPE_REMOTE;
+ mVolumeType = PlaybackInfo.PLAYBACK_TYPE_LOCAL;
if (attributes != null) {
mAudioAttrs = attributes;
} else {
@@ -765,8 +766,8 @@
public void setPlaybackToRemote(int control, int max) {
boolean typeChanged;
synchronized (mLock) {
- typeChanged = mVolumeType == MediaSession.PLAYBACK_TYPE_LOCAL;
- mVolumeType = MediaSession.PLAYBACK_TYPE_REMOTE;
+ typeChanged = mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL;
+ mVolumeType = PlaybackInfo.PLAYBACK_TYPE_REMOTE;
mVolumeControlType = control;
mMaxVolume = max;
}
@@ -998,7 +999,7 @@
int type;
int max;
int current;
- if (mVolumeType == MediaSession.PLAYBACK_TYPE_REMOTE) {
+ if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_REMOTE) {
type = mVolumeControlType;
max = mMaxVolume;
current = mOptimisticVolume != -1 ? mOptimisticVolume
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 1221aa4..0c6d46c 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -37,6 +37,7 @@
import android.media.session.ISession;
import android.media.session.ISessionCallback;
import android.media.session.ISessionManager;
+import android.media.session.MediaController.PlaybackInfo;
import android.media.session.MediaSession;
import android.net.Uri;
import android.os.Binder;
@@ -814,7 +815,7 @@
} else {
session.adjustVolume(direction, flags, getContext().getPackageName(),
UserHandle.myUserId());
- if (session.getPlaybackType() == MediaSession.PLAYBACK_TYPE_REMOTE
+ if (session.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE
&& mRvc != null) {
try {
mRvc.remoteVolumeChanged(session.getControllerBinder(), flags);
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index fec11fba..a9bc818 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -16,6 +16,7 @@
package com.android.server.media;
+import android.media.session.MediaController.PlaybackInfo;
import android.media.session.PlaybackState;
import android.media.session.MediaSession;
import android.os.UserHandle;
@@ -209,7 +210,7 @@
int size = records.size();
for (int i = 0; i < size; i++) {
MediaSessionRecord record = records.get(i);
- if (record.getPlaybackType() == MediaSession.PLAYBACK_TYPE_REMOTE) {
+ if (record.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE) {
return record;
}
}
diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java
index 52e741b..04df3e7 100644
--- a/services/core/java/com/android/server/net/LockdownVpnTracker.java
+++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java
@@ -205,7 +205,6 @@
private void initLocked() {
Slog.d(TAG, "initLocked()");
- mVpn.setEnableNotifications(false);
mVpn.setEnableTeardown(false);
final IntentFilter resetFilter = new IntentFilter(ACTION_LOCKDOWN_RESET);
@@ -249,7 +248,6 @@
hideNotification();
mContext.unregisterReceiver(mResetReceiver);
- mVpn.setEnableNotifications(true);
mVpn.setEnableTeardown(true);
}
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index 4a7a971..3d13d21 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -46,8 +46,13 @@
* {@hide}
*/
public class NotificationUsageStats {
+ // WARNING: Aggregated stats can grow unboundedly with pkg+id+tag.
+ // Don't enable on production builds.
+ private static final boolean ENABLE_AGGREGATED_IN_MEMORY_STATS = false;
private static final boolean ENABLE_SQLITE_LOG = true;
+ private static final AggregatedStats[] EMPTY_AGGREGATED_STATS = new AggregatedStats[0];
+
// Guarded by synchronized(this).
private final Map<String, AggregatedStats> mStats = new HashMap<String, AggregatedStats>();
private final SQLiteLog mSQLiteLog;
@@ -147,6 +152,10 @@
// Locked by this.
private AggregatedStats[] getAggregatedStatsLocked(NotificationRecord record) {
+ if (!ENABLE_AGGREGATED_IN_MEMORY_STATS) {
+ return EMPTY_AGGREGATED_STATS;
+ }
+
StatusBarNotification n = record.sbn;
String user = String.valueOf(n.getUserId());
@@ -171,9 +180,12 @@
}
public synchronized void dump(PrintWriter pw, String indent, DumpFilter filter) {
- for (AggregatedStats as : mStats.values()) {
- if (filter != null && !filter.matches(as.key)) continue;
- as.dump(pw, indent);
+ if (ENABLE_AGGREGATED_IN_MEMORY_STATS) {
+ for (AggregatedStats as : mStats.values()) {
+ if (filter != null && !filter.matches(as.key))
+ continue;
+ as.dump(pw, indent);
+ }
}
if (ENABLE_SQLITE_LOG) {
mSQLiteLog.dump(pw, indent, filter);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 0393518..5e802de 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -56,6 +56,7 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
+import android.os.Environment.UserEnvironment;
import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
@@ -484,16 +485,22 @@
if (params.mode == SessionParams.MODE_FULL_INSTALL) {
// Brand new install, use best resolved location. This also verifies
// that target has enough free space for the install.
- final int resolved = PackageHelper.resolveInstallLocation(mContext,
- params.installLocation, params.sizeBytes, params.installFlags);
- if (resolved == PackageHelper.RECOMMEND_INSTALL_INTERNAL) {
- stageInternal = true;
- } else if (resolved == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
- stageInternal = false;
- } else {
- throw new IOException("No storage with enough free space; res=" + resolved);
- }
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ final int resolved = PackageHelper.resolveInstallLocation(mContext,
+ params.appPackageName, params.installLocation, params.sizeBytes,
+ params.installFlags);
+ if (resolved == PackageHelper.RECOMMEND_INSTALL_INTERNAL) {
+ stageInternal = true;
+ } else if (resolved == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
+ stageInternal = false;
+ } else {
+ throw new IOException("No storage with enough free space; res=" + resolved);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
} else if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
// We always stage inheriting sessions on internal storage first,
// since we don't want to grow containers until we're sure that
@@ -568,7 +575,8 @@
private void checkExternalStorage(long sizeBytes) throws IOException {
if (sizeBytes <= 0) return;
- final File target = Environment.getExternalStorageDirectory();
+ final File target = new UserEnvironment(UserHandle.USER_OWNER)
+ .getExternalStorageDirectory();
final long targetBytes = sizeBytes + mStorage.getStorageLowBytes(target);
if (target.getUsableSpace() < targetBytes) {
@@ -696,7 +704,7 @@
mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "uninstall");
final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
- statusReceiver);
+ statusReceiver, packageName);
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES)
== PackageManager.PERMISSION_GRANTED) {
// Sweet, call straight through!
@@ -773,15 +781,19 @@
static class PackageDeleteObserverAdapter extends PackageDeleteObserver {
private final Context mContext;
private final IntentSender mTarget;
+ private final String mPackageName;
- public PackageDeleteObserverAdapter(Context context, IntentSender target) {
+ public PackageDeleteObserverAdapter(Context context, IntentSender target,
+ String packageName) {
mContext = context;
mTarget = target;
+ mPackageName = packageName;
}
@Override
public void onUserActionRequired(Intent intent) {
final Intent fillIn = new Intent();
+ fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, mPackageName);
fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
PackageInstaller.STATUS_PENDING_USER_ACTION);
fillIn.putExtra(Intent.EXTRA_INTENT, intent);
@@ -794,6 +806,7 @@
@Override
public void onPackageDeleted(String basePackageName, int returnCode, String msg) {
final Intent fillIn = new Intent();
+ fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, mPackageName);
fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
PackageManager.deleteStatusToPublicStatus(returnCode));
fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
@@ -809,15 +822,18 @@
static class PackageInstallObserverAdapter extends PackageInstallObserver {
private final Context mContext;
private final IntentSender mTarget;
+ private final int mSessionId;
- public PackageInstallObserverAdapter(Context context, IntentSender target) {
+ public PackageInstallObserverAdapter(Context context, IntentSender target, int sessionId) {
mContext = context;
mTarget = target;
+ mSessionId = sessionId;
}
@Override
public void onUserActionRequired(Intent intent) {
final Intent fillIn = new Intent();
+ fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId);
fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
PackageInstaller.STATUS_PENDING_USER_ACTION);
fillIn.putExtra(Intent.EXTRA_INTENT, intent);
@@ -831,6 +847,7 @@
public void onPackageInstalled(String basePackageName, int returnCode, String msg,
Bundle extras) {
final Intent fillIn = new Intent();
+ fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId);
fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
PackageManager.installStatusToPublicStatus(returnCode));
fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
@@ -840,8 +857,7 @@
final String existing = extras.getString(
PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
if (!TextUtils.isEmpty(existing)) {
- fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAMES, new String[] {
- existing });
+ fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, existing);
}
}
try {
@@ -986,5 +1002,12 @@
}
writeSessionsAsync();
}
+
+ public void onSessionSealed(PackageInstallerSession session) {
+ // It's very important that we block until we've recorded the
+ // session as being sealed, since we never want to allow mutation
+ // after sealing.
+ writeSessionsLocked();
+ }
}
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 0616460..38a2016 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -195,6 +195,11 @@
this.internalStageDir = internalStageDir;
this.externalStageCid = externalStageCid;
+ if ((internalStageDir == null) == (externalStageCid == null)) {
+ throw new IllegalArgumentException(
+ "Exactly one of internal or external stage must be set");
+ }
+
mSealed = sealed;
// Always derived at runtime
@@ -395,7 +400,7 @@
Preconditions.checkNotNull(statusReceiver);
final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(mContext,
- statusReceiver);
+ statusReceiver, sessionId);
mHandler.obtainMessage(MSG_COMMIT, adapter.getBinder()).sendToTarget();
}
@@ -414,8 +419,9 @@
}
mSealed = true;
- // TODO: persist disabled mutations before going forward, since
- // beyond this point we may have hardlinks to the valid install
+ // Persist the fact that we've sealed ourselves to prevent mutations
+ // of any hard links we create below.
+ mCallback.onSessionSealed(this);
}
final File stageDir;
@@ -476,9 +482,8 @@
}
};
- // TODO: send ASEC cid if that's where we staged things
- mPm.installStage(mPackageName, this.internalStageDir, null, localObserver, params,
- installerPackageName, installerUid, new UserHandle(userId));
+ mPm.installStage(mPackageName, this.internalStageDir, this.externalStageCid, localObserver,
+ params, installerPackageName, installerUid, new UserHandle(userId));
}
/**
@@ -486,6 +491,9 @@
* consistent package name, version code, and signing certificates.
* <p>
* Renames package files in stage to match split names defined inside.
+ * <p>
+ * Note that upgrade compatibility is still performed by
+ * {@link PackageManagerService}.
*/
private void validateInstallLocked(File stageDir) throws PackageManagerException {
mPackageName = null;
@@ -498,13 +506,17 @@
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
}
- final ArraySet<String> seenSplits = new ArraySet<>();
-
// Verify that all staged packages are internally consistent
+ final ArraySet<String> seenSplits = new ArraySet<>();
for (File file : files) {
+
+ // Installers can't stage directories, so it's fine to ignore
+ // entries like "lost+found".
+ if (file.isDirectory()) continue;
+
final ApkLite info;
try {
- info = PackageParser.parseApkLite(file, PackageParser.PARSE_GET_SIGNATURES);
+ info = PackageParser.parseApkLite(file, PackageParser.PARSE_COLLECT_CERTIFICATES);
} catch (PackageParserException e) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
"Failed to parse " + file + ": " + e);
@@ -550,10 +562,6 @@
}
}
- // TODO: shift package signature verification to installer; we're
- // currently relying on PMS to do this.
- // TODO: teach about compatible upgrade keysets.
-
if (params.mode == SessionParams.MODE_FULL_INSTALL) {
// Full installs must include a base package
if (!seenSplits.contains(null)) {
@@ -577,7 +585,7 @@
final ApkLite info;
try {
info = PackageParser.parseApkLite(new File(app.getBaseCodePath()),
- PackageParser.PARSE_GET_SIGNATURES);
+ PackageParser.PARSE_COLLECT_CERTIFICATES);
} catch (PackageParserException e) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
"Failed to parse existing base " + app.getBaseCodePath() + ": " + e);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f47e64f..aa49b27 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -48,11 +48,6 @@
import static android.os.Process.SYSTEM_UID;
import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.O_RDWR;
-import static android.system.OsConstants.S_IRGRP;
-import static android.system.OsConstants.S_IROTH;
-import static android.system.OsConstants.S_IRWXU;
-import static android.system.OsConstants.S_IXGRP;
-import static android.system.OsConstants.S_IXOTH;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_USER_OWNER;
import static com.android.internal.util.ArrayUtils.appendInt;
@@ -70,7 +65,6 @@
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.Preconditions;
import com.android.server.EventLogTags;
import com.android.server.IntentResolver;
import com.android.server.LocalServices;
@@ -255,10 +249,6 @@
// package apks to install directory.
private static final String INSTALL_PACKAGE_SUFFIX = "-";
- // Special value for {@code PackageParser.Package#cpuAbiOverride} to indicate
- // that the cpuAbiOverride must be clear.
- private static final String CLEAR_ABI_OVERRIDE = "-";
-
static final int SCAN_MONITOR = 1<<0;
static final int SCAN_NO_DEX = 1<<1;
static final int SCAN_FORCE_DEX = 1<<2;
@@ -5022,7 +5012,7 @@
private static String deriveAbiOverride(String abiOverride, PackageSetting settings) {
String cpuAbiOverride = null;
- if (CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
+ if (NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
cpuAbiOverride = null;
} else if (abiOverride != null) {
cpuAbiOverride = abiOverride;
@@ -5526,7 +5516,8 @@
// Warn if we've set an abiOverride for multi-lib packages..
// By definition, we need to copy both 32 and 64 bit libraries for
// such packages.
- if (pkg.cpuAbiOverride != null && !CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) {
+ if (pkg.cpuAbiOverride != null
+ && !NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) {
Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
}
@@ -5536,7 +5527,7 @@
if (isAsec) {
abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
} else {
- abi32 = copyNativeLibrariesForInternalApp(handle,
+ abi32 = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS, useIsaSpecificSubdirs);
}
}
@@ -5548,7 +5539,7 @@
if (isAsec) {
abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
} else {
- abi64 = copyNativeLibrariesForInternalApp(handle,
+ abi64 = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS, useIsaSpecificSubdirs);
}
}
@@ -5587,8 +5578,8 @@
if (isAsec) {
copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList);
} else {
- copyRet = copyNativeLibrariesForInternalApp(handle, nativeLibraryRoot, abiList,
- useIsaSpecificSubdirs);
+ copyRet = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
+ nativeLibraryRoot, abiList, useIsaSpecificSubdirs);
}
if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
@@ -6471,58 +6462,6 @@
}
}
- private static void createNativeLibrarySubdir(File path) throws IOException {
- if (!path.isDirectory()) {
- path.delete();
-
- if (!path.mkdir()) {
- throw new IOException("Cannot create " + path.getPath());
- }
-
- try {
- Os.chmod(path.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
- } catch (ErrnoException e) {
- throw new IOException("Cannot chmod native library directory "
- + path.getPath(), e);
- }
- } else if (!SELinux.restorecon(path)) {
- throw new IOException("Cannot set SELinux context for " + path.getPath());
- }
- }
-
- private static int copyNativeLibrariesForInternalApp(NativeLibraryHelper.Handle handle,
- final File nativeLibraryRoot, String[] abiList, boolean useIsaSubdir) throws IOException {
- createNativeLibrarySubdir(nativeLibraryRoot);
-
- /*
- * If this is an internal application or our nativeLibraryPath points to
- * the app-lib directory, unpack the libraries if necessary.
- */
- int abi = NativeLibraryHelper.findSupportedAbi(handle, abiList);
- if (abi >= 0) {
- /*
- * If we have a matching instruction set, construct a subdir under the native
- * library root that corresponds to this instruction set.
- */
- final String instructionSet = VMRuntime.getInstructionSet(abiList[abi]);
- final File subDir;
- if (useIsaSubdir) {
- final File isaSubdir = new File(nativeLibraryRoot, instructionSet);
- createNativeLibrarySubdir(isaSubdir);
- subDir = isaSubdir;
- } else {
- subDir = nativeLibraryRoot;
- }
-
- int copyRet = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, subDir, abiList[abi]);
- if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
- return copyRet;
- }
- }
-
- return abi;
- }
-
private void killApplication(String pkgName, int appId, String reason) {
// Request the ActivityManager to kill the process(only for existing packages)
// so that we do not end up in a confused state while the user is still using the older
@@ -8667,6 +8606,20 @@
*/
public void handleStartCopy() throws RemoteException {
int ret = PackageManager.INSTALL_SUCCEEDED;
+
+ // If we're already staged, we've firmly committed to an install location
+ if (originStaged) {
+ if (originFile != null) {
+ flags |= PackageManager.INSTALL_INTERNAL;
+ flags &= ~PackageManager.INSTALL_EXTERNAL;
+ } else if (originCid != null) {
+ flags |= PackageManager.INSTALL_EXTERNAL;
+ flags &= ~PackageManager.INSTALL_INTERNAL;
+ } else {
+ throw new IllegalStateException("Invalid stage location");
+ }
+ }
+
final boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
final boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
PackageInfoLite pkgLite = null;
@@ -8690,7 +8643,7 @@
* If we have too little free space, try to free cache
* before giving up.
*/
- if (pkgLite.recommendedInstallLocation
+ if (!originStaged && pkgLite.recommendedInstallLocation
== PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
// TODO: focus freeing disk space on the target device
final StorageManager storage = StorageManager.from(mContext);
@@ -9287,49 +9240,11 @@
NativeLibraryHelper.Handle handle = null;
try {
handle = NativeLibraryHelper.Handle.create(codeFile);
- if (multiArch) {
- // Warn if we've set an abiOverride for multi-lib packages..
- // By definition, we need to copy both 32 and 64 bit libraries for
- // such packages.
- if (abiOverride != null && !CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
- Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
- }
-
- int copyRet = PackageManager.NO_NATIVE_LIBRARIES;
- if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
- copyRet = copyNativeLibrariesForInternalApp(handle, libraryRoot,
- Build.SUPPORTED_32_BIT_ABIS, true /* use isa specific subdirs */);
- maybeThrowExceptionForMultiArchCopy("Failure copying 32 bit native libraries", copyRet);
- }
-
- if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
- copyRet = copyNativeLibrariesForInternalApp(handle, libraryRoot,
- Build.SUPPORTED_64_BIT_ABIS, true /* use isa specific subdirs */);
- maybeThrowExceptionForMultiArchCopy("Failure copying 64 bit native libraries", copyRet);
- }
- } else {
- final String cpuAbiOverride = deriveAbiOverride(this.abiOverride, null /* package setting */);
- String[] abiList = (cpuAbiOverride != null) ?
- new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
-
- if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
- NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
- abiList = Build.SUPPORTED_32_BIT_ABIS;
- }
-
- int copyRet = copyNativeLibrariesForInternalApp(handle, libraryRoot, abiList,
- true /* use isa specific subdirs */);
- if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
- Slog.w(TAG, "Failure copying native libraries [errorCode=" + copyRet + "]");
- return copyRet;
- }
- }
+ ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, libraryRoot,
+ abiOverride, multiArch);
} catch (IOException e) {
Slog.e(TAG, "Copying native libraries failed", e);
ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
- } catch (PackageManagerException pme) {
- Slog.e(TAG, "Copying native libraries failed", pme);
- ret = pme.error;
} finally {
IoUtils.closeQuietly(handle);
}
@@ -9504,8 +9419,6 @@
* renaming logic.
*/
class AsecInstallArgs extends InstallArgs {
- // TODO: teach about handling cluster directories
-
static final String RES_FILE_NAME = "pkg.apk";
static final String PUBLIC_RES_FILE_NAME = "res.zip";
@@ -9528,12 +9441,17 @@
super(null, false, null, (isExternal ? INSTALL_EXTERNAL : 0)
| (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
instructionSets, null, isMultiArch);
+ // Hackily pretend we're still looking at a full code path
+ if (!fullCodePath.endsWith(RES_FILE_NAME)) {
+ fullCodePath = new File(fullCodePath, RES_FILE_NAME).getAbsolutePath();
+ }
+
// Extract cid from fullCodePath
int eidx = fullCodePath.lastIndexOf("/");
String subStr1 = fullCodePath.substring(0, eidx);
int sidx = subStr1.lastIndexOf("/");
cid = subStr1.substring(sidx+1, eidx);
- setCachePath(subStr1);
+ setMountPath(subStr1);
}
AsecInstallArgs(String cid, String[] instructionSets, boolean isForwardLocked,
@@ -9542,7 +9460,7 @@
| (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
instructionSets, null, isMultiArch);
this.cid = cid;
- setCachePath(PackageHelper.getSdDir(cid));
+ setMountPath(PackageHelper.getSdDir(cid));
}
/** New install from existing */
@@ -9564,7 +9482,7 @@
final File target;
if (isExternal()) {
- target = Environment.getExternalStorageDirectory();
+ target = new UserEnvironment(UserHandle.USER_OWNER).getExternalStorageDirectory();
} else {
target = Environment.getDataDirectory();
}
@@ -9578,6 +9496,7 @@
}
int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
+ // TODO: if already staged, we only need to extract native code
if (temp) {
createCopyFile();
} else {
@@ -9588,12 +9507,12 @@
PackageHelper.destroySdDir(cid);
}
- final String newCachePath = imcs.copyPackageToContainer(
+ final String newMountPath = imcs.copyPackageToContainer(
originFile.getAbsolutePath(), cid, getEncryptKey(), isExternal(),
isFwdLocked(), deriveAbiOverride(abiOverride, null /* settings */));
- if (newCachePath != null) {
- setCachePath(newCachePath);
+ if (newMountPath != null) {
+ setMountPath(newMountPath);
return PackageManager.INSTALL_SUCCEEDED;
} else {
return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
@@ -9622,10 +9541,10 @@
} else {
boolean mounted = PackageHelper.isContainerMounted(cid);
if (!mounted) {
- String newCachePath = PackageHelper.mountSdDir(cid, getEncryptKey(),
+ String newMountPath = PackageHelper.mountSdDir(cid, getEncryptKey(),
Process.SYSTEM_UID);
- if (newCachePath != null) {
- setCachePath(newCachePath);
+ if (newMountPath != null) {
+ setMountPath(newMountPath);
} else {
return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
}
@@ -9636,7 +9555,7 @@
boolean doRename(int status, PackageParser.Package pkg, String oldCodePath) {
String newCacheId = getNextCodePath(oldCodePath, pkg.packageName, "/" + RES_FILE_NAME);
- String newCachePath = null;
+ String newMountPath = null;
if (PackageHelper.isContainerMounted(cid)) {
// Unmount the container
if (!PackageHelper.unMountSdDir(cid)) {
@@ -9661,46 +9580,59 @@
}
if (!PackageHelper.isContainerMounted(newCacheId)) {
Slog.w(TAG, "Mounting container " + newCacheId);
- newCachePath = PackageHelper.mountSdDir(newCacheId,
+ newMountPath = PackageHelper.mountSdDir(newCacheId,
getEncryptKey(), Process.SYSTEM_UID);
} else {
- newCachePath = PackageHelper.getSdDir(newCacheId);
+ newMountPath = PackageHelper.getSdDir(newCacheId);
}
- if (newCachePath == null) {
+ if (newMountPath == null) {
Slog.w(TAG, "Failed to get cache path for " + newCacheId);
return false;
}
Log.i(TAG, "Succesfully renamed " + cid +
" to " + newCacheId +
- " at new path: " + newCachePath);
+ " at new path: " + newMountPath);
cid = newCacheId;
- setCachePath(newCachePath);
- // TODO: extend to support split APKs
- pkg.codePath = getCodePath();
- pkg.baseCodePath = getCodePath();
- pkg.splitCodePaths = null;
+ final File beforeCodeFile = new File(packagePath);
+ setMountPath(newMountPath);
+ final File afterCodeFile = new File(packagePath);
- pkg.applicationInfo.setCodePath(getCodePath());
- pkg.applicationInfo.setBaseCodePath(getCodePath());
- pkg.applicationInfo.setSplitCodePaths(null);
- pkg.applicationInfo.setResourcePath(getResourcePath());
- pkg.applicationInfo.setBaseResourcePath(getResourcePath());
- pkg.applicationInfo.setSplitResourcePaths(null);
+ // Reflect the rename in scanned details
+ pkg.codePath = afterCodeFile.getAbsolutePath();
+ pkg.baseCodePath = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile,
+ pkg.baseCodePath);
+ pkg.splitCodePaths = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile,
+ pkg.splitCodePaths);
+
+ // Reflect the rename in app info
+ pkg.applicationInfo.setCodePath(pkg.codePath);
+ pkg.applicationInfo.setBaseCodePath(pkg.baseCodePath);
+ pkg.applicationInfo.setSplitCodePaths(pkg.splitCodePaths);
+ pkg.applicationInfo.setResourcePath(pkg.codePath);
+ pkg.applicationInfo.setBaseResourcePath(pkg.baseCodePath);
+ pkg.applicationInfo.setSplitResourcePaths(pkg.splitCodePaths);
return true;
}
- private void setCachePath(String newCachePath) {
- File cachePath = new File(newCachePath);
- legacyNativeLibraryDir = new File(cachePath, LIB_DIR_NAME).getPath();
- packagePath = new File(cachePath, RES_FILE_NAME).getPath();
+ private void setMountPath(String mountPath) {
+ final File mountFile = new File(mountPath);
- if (isFwdLocked()) {
- resourcePath = new File(cachePath, PUBLIC_RES_FILE_NAME).getPath();
+ final File monolithicFile = new File(mountFile, RES_FILE_NAME);
+ if (monolithicFile.exists()) {
+ packagePath = monolithicFile.getAbsolutePath();
+ if (isFwdLocked()) {
+ resourcePath = new File(mountFile, PUBLIC_RES_FILE_NAME).getAbsolutePath();
+ } else {
+ resourcePath = packagePath;
+ }
} else {
+ packagePath = mountFile.getAbsolutePath();
resourcePath = packagePath;
}
+
+ legacyNativeLibraryDir = new File(mountFile, LIB_DIR_NAME).getAbsolutePath();
}
int doPostInstall(int status, int uid) {
@@ -9739,23 +9671,43 @@
PackageHelper.destroySdDir(cid);
}
- void cleanUpResourcesLI() {
- String sourceFile = getCodePath();
- // Remove dex file
- if (instructionSets == null) {
- throw new IllegalStateException("instructionSet == null");
- }
- String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
- for (String dexCodeInstructionSet : dexCodeInstructionSets) {
- int retCode = mInstaller.rmdex(sourceFile, dexCodeInstructionSet);
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't remove dex file for package: "
- + " at location "
- + sourceFile.toString() + ", retcode=" + retCode);
- // we don't consider this to be a failure of the core package deletion
+ private List<String> getAllCodePaths() {
+ final File codeFile = new File(getCodePath());
+ if (codeFile != null && codeFile.exists()) {
+ try {
+ final PackageLite pkg = PackageParser.parsePackageLite(codeFile, 0);
+ return pkg.getAllCodePaths();
+ } catch (PackageParserException e) {
+ // Ignored; we tried our best
}
}
+ return Collections.EMPTY_LIST;
+ }
+
+ void cleanUpResourcesLI() {
+ // Enumerate all code paths before deleting
+ cleanUpResourcesLI(getAllCodePaths());
+ }
+
+ private void cleanUpResourcesLI(List<String> allCodePaths) {
cleanUp();
+
+ if (!allCodePaths.isEmpty()) {
+ if (instructionSets == null) {
+ throw new IllegalStateException("instructionSet == null");
+ }
+ String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
+ for (String codePath : allCodePaths) {
+ for (String dexCodeInstructionSet : dexCodeInstructionSets) {
+ int retCode = mInstaller.rmdex(codePath, dexCodeInstructionSet);
+ if (retCode < 0) {
+ Slog.w(TAG, "Couldn't remove dex file for package: "
+ + " at location " + codePath + ", retcode=" + retCode);
+ // we don't consider this to be a failure of the core package deletion
+ }
+ }
+ }
+ }
}
boolean matchContainer(String app) {
@@ -9770,16 +9722,19 @@
}
boolean doPostDeleteLI(boolean delete) {
- boolean ret = false;
+ if (DEBUG_SD_INSTALL) Slog.i(TAG, "doPostDeleteLI() del=" + delete);
+ final List<String> allCodePaths = getAllCodePaths();
boolean mounted = PackageHelper.isContainerMounted(cid);
if (mounted) {
// Unmount first
- ret = PackageHelper.unMountSdDir(cid);
+ if (PackageHelper.unMountSdDir(cid)) {
+ mounted = false;
+ }
}
- if (ret && delete) {
- cleanUpResourcesLI();
+ if (!mounted && delete) {
+ cleanUpResourcesLI(allCodePaths);
}
- return ret;
+ return !mounted;
}
@Override
@@ -10966,6 +10921,7 @@
outInfo.args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
getAppDexInstructionSets(ps), isMultiArch(ps));
+ if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.args);
}
return true;
}
@@ -12772,7 +12728,8 @@
getAppDexInstructionSets(ps), isForwardLocked(ps), isMultiArch(ps));
// The package status is changed only if the code path
// matches between settings and the container id.
- if (ps.codePathString != null && ps.codePathString.equals(args.getCodePath())) {
+ if (ps.codePathString != null
+ && ps.codePathString.startsWith(args.getCodePath())) {
if (DEBUG_SD_INSTALL) {
Log.i(TAG, "Container : " + cid + " corresponds to pkg : " + pkgName
+ " at code path: " + ps.codePathString);
@@ -12851,7 +12808,7 @@
continue;
}
// Check code path here.
- if (codePath == null || !codePath.equals(args.getCodePath())) {
+ if (codePath == null || !codePath.startsWith(args.getCodePath())) {
Slog.e(TAG, "Container " + args.cid + " cachepath " + args.getCodePath()
+ " does not match one in settings " + codePath);
continue;
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 5f3da07..da11387 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -430,10 +430,10 @@
}
try {
- radioOff = phone == null || !phone.isRadioOn();
+ radioOff = phone == null || !phone.needMobileRadioShutdown();
if (!radioOff) {
- Log.w(TAG, "Turning off radio...");
- phone.setRadio(false);
+ Log.w(TAG, "Turning off cellular radios...");
+ phone.shutdownMobileRadios();
}
} catch (RemoteException ex) {
Log.e(TAG, "RemoteException during radio shutdown", ex);
@@ -456,7 +456,7 @@
}
if (!radioOff) {
try {
- radioOff = !phone.isRadioOn();
+ radioOff = !phone.needMobileRadioShutdown();
} catch (RemoteException ex) {
Log.e(TAG, "RemoteException during radio shutdown", ex);
radioOff = true;
@@ -472,7 +472,7 @@
Log.e(TAG, "RemoteException during NFC shutdown", ex);
nfcOff = true;
}
- if (radioOff) {
+ if (nfcOff) {
Log.i(TAG, "NFC turned off.");
}
}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 490536e..98c3381 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -168,6 +168,8 @@
obsoleteAgents.addAll(mActiveAgents);
for (UserInfo userInfo : userInfos) {
+ if (lockPatternUtils.getKeyguardStoredPasswordQuality()
+ == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) continue;
DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
final boolean disableTrustAgents =
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index a084cab..6481944 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -283,7 +283,6 @@
userState.inputMap = inputMap;
userState.ratingSystemXmlUriSet.clear();
- userState.ratingSystemXmlUriSet.add(TvContentRating.SYSTEM_CONTENT_RATING_SYSTEM_XML);
for (TvInputState state : userState.inputMap.values()) {
Uri ratingSystemXmlUri = state.mInfo.getRatingSystemXmlUri();
if (ratingSystemXmlUri != null) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b57a090..32f3707 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -5801,6 +5801,29 @@
SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
}
+ private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) {
+ if (rot == Surface.ROTATION_90) {
+ final int tmp = crop.top;
+ crop.top = dw - crop.right;
+ crop.right = crop.bottom;
+ crop.bottom = dw - crop.left;
+ crop.left = tmp;
+ } else if (rot == Surface.ROTATION_180) {
+ int tmp = crop.top;
+ crop.top = dh - crop.bottom;
+ crop.bottom = dh - tmp;
+ tmp = crop.right;
+ crop.right = dw - crop.left;
+ crop.left = dw - tmp;
+ } else if (rot == Surface.ROTATION_270) {
+ final int tmp = crop.top;
+ crop.top = crop.left;
+ crop.left = dh - crop.bottom;
+ crop.bottom = crop.right;
+ crop.right = dh - tmp;
+ }
+ }
+
/**
* Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
* In portrait mode, it grabs the upper region of the screen based on the vertical dimension
@@ -5962,21 +5985,31 @@
// Constrain frame to the screen size.
frame.intersect(0, 0, dw, dh);
- // Constrain thumbnail to smaller of screen width or height. Assumes aspect
- // of thumbnail is the same as the screen (in landscape) or square.
- scale = Math.max(width / (float) frame.width(), height / (float) frame.height());
- dw = (int)(dw * scale);
- dh = (int)(dh * scale);
+
+ // Tell surface flinger what part of the image to crop. Take the top
+ // right part of the application, and crop the larger dimension to fit.
+ Rect crop = new Rect(frame);
+ if (width / (float) frame.width() < height / (float) frame.height()) {
+ int cropWidth = (int)((float)width / (float)height * frame.height());
+ crop.right = crop.left + cropWidth;
+ } else {
+ int cropHeight = (int)((float)height / (float)width * frame.width());
+ crop.bottom = crop.top + cropHeight;
+ }
// The screenshot API does not apply the current screen rotation.
rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
- final int tmp = dw;
- dw = dh;
- dh = tmp;
+ final int tmp = width;
+ width = height;
+ height = tmp;
rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
}
+ // Surfaceflinger is not aware of orientation, so convert our logical
+ // crop to surfaceflinger's portrait orientation.
+ convertCropForSurfaceFlinger(crop, rot, dw, dh);
+
if (DEBUG_SCREENSHOT) {
Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
+ maxLayer + " appToken=" + appToken);
@@ -5995,7 +6028,7 @@
if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG,
"Taking screenshot while rotating");
- rawss = SurfaceControl.screenshot(new Rect(), dw, dh, minLayer, maxLayer,
+ rawss = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
inRotation);
if (rawss == null) {
Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
@@ -6012,11 +6045,8 @@
if (DEBUG_SCREENSHOT) {
bm.eraseColor(0xFF000000);
}
- frame.scale(scale);
Matrix matrix = new Matrix();
- ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix);
- // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left
- matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top));
+ ScreenRotationAnimation.createRotationMatrix(rot, width, height, matrix);
Canvas canvas = new Canvas(bm);
canvas.drawBitmap(rawss, matrix, null);
canvas.setBitmap(null);
@@ -6042,6 +6072,7 @@
}
rawss.recycle();
+
return bm;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
index 4b60c9f..5938819 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
@@ -267,6 +267,9 @@
if (mDeviceOwner != null) {
out.startTag(null, TAG_DEVICE_OWNER);
out.attribute(null, ATTR_PACKAGE, mDeviceOwner.packageName);
+ if (mDeviceOwner.name != null) {
+ out.attribute(null, ATTR_NAME, mDeviceOwner.name);
+ }
out.endTag(null, TAG_DEVICE_OWNER);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 2c3c510..7baa258 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -18,18 +18,7 @@
import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
-import android.app.admin.DevicePolicyManagerInternal;
-
-import com.android.internal.R;
-import com.android.internal.os.storage.ExternalStorageFormatter;
-import com.android.internal.util.FastXmlSerializer;
-import com.android.internal.util.JournaledFile;
-import com.android.internal.util.XmlUtils;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.org.conscrypt.TrustedCertificateStore;
-import com.android.server.LocalServices;
-import com.android.server.SystemService;
-
+import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.Activity;
import android.app.ActivityManagerNative;
import android.app.AlarmManager;
@@ -41,6 +30,7 @@
import android.app.admin.DeviceAdminInfo;
import android.app.admin.DeviceAdminReceiver;
import android.app.admin.DevicePolicyManager;
+import android.app.admin.DevicePolicyManagerInternal;
import android.app.admin.IDevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -50,14 +40,15 @@
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.media.AudioManager;
import android.media.IAudioService;
import android.net.ConnectivityManager;
import android.net.Uri;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.database.ContentObserver;
import android.hardware.usb.UsbManager;
import android.net.ProxyInfo;
@@ -88,8 +79,22 @@
import android.util.Slog;
import android.util.SparseArray;
import android.util.Xml;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.IAccessibilityManager;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
import android.view.IWindowManager;
+import com.android.internal.R;
+import com.android.internal.os.storage.ExternalStorageFormatter;
+import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.JournaledFile;
+import com.android.internal.util.XmlUtils;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.org.conscrypt.TrustedCertificateStore;
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
+
import org.xmlpull.v1.XmlPullParser;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
@@ -147,10 +152,27 @@
private static final String ATTR_PERMISSION_PROVIDER = "permission-provider";
private static final String ATTR_SETUP_COMPLETE = "setup-complete";
+ private static final Set<String> DEVICE_OWNER_USER_RESTRICTIONS;
+ static {
+ DEVICE_OWNER_USER_RESTRICTIONS = new HashSet();
+ DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_USB_FILE_TRANSFER);
+ DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_CONFIG_TETHERING);
+ DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_FACTORY_RESET);
+ DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_ADD_USER);
+ DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS);
+ DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
+ DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
+ DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_UNMUTE_MICROPHONE);
+ DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_ADJUST_VOLUME);
+ DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_SMS);
+ }
+
final Context mContext;
final UserManager mUserManager;
final PowerManager.WakeLock mWakeLock;
+ final LocalService mLocalService;
+
IPowerManager mIPowerManager;
IWindowManager mIWindowManager;
NotificationManager mNotificationManager;
@@ -266,6 +288,8 @@
private static final String TAG_DISABLE_SCREEN_CAPTURE = "disable-screen-capture";
private static final String TAG_DISABLE_ACCOUNT_MANAGEMENT = "disable-account-management";
private static final String TAG_ACCOUNT_TYPE = "account-type";
+ private static final String TAG_PERMITTED_ACCESSIBILITY_SERVICES
+ = "permitted-accessiblity-services";
private static final String TAG_ENCRYPTION_REQUESTED = "encryption-requested";
private static final String TAG_MANAGE_TRUST_AGENT_FEATURES = "manage-trust-agent-features";
private static final String TAG_TRUST_AGENT_FEATURE = "feature";
@@ -275,6 +299,7 @@
private static final String TAG_GLOBAL_PROXY_EXCLUSION_LIST = "global-proxy-exclusion-list";
private static final String TAG_GLOBAL_PROXY_SPEC = "global-proxy-spec";
private static final String TAG_SPECIFIES_GLOBAL_PROXY = "specifies-global-proxy";
+ private static final String TAG_PERMITTED_IMES = "permitted-imes";
private static final String TAG_MAX_FAILED_PASSWORD_WIPE = "max-failed-password-wipe";
private static final String TAG_MAX_TIME_TO_UNLOCK = "max-time-to-unlock";
private static final String TAG_MIN_PASSWORD_NONLETTER = "min-password-nonletter";
@@ -291,6 +316,7 @@
private static final String TAG_CROSS_PROFILE_WIDGET_PROVIDERS =
"cross-profile-widget-providers";
private static final String TAG_PROVIDER = "provider";
+ private static final String TAG_PACKAGE_LIST_ITEM = "item";
final DeviceAdminInfo info;
@@ -342,6 +368,16 @@
Set<String> accountTypesWithManagementDisabled = new HashSet<String>();
+ // The list of permitted accessibility services package namesas set by a profile
+ // or device owner. Null means all accessibility services are allowed, empty means
+ // none except system services are allowed.
+ List<String> permittedAccessiblityServices;
+
+ // The list of permitted input methods package names as set by a profile or device owner.
+ // Null means all input methods are allowed, empty means none except system imes are
+ // allowed.
+ List<String> permittedInputMethods;
+
// TODO: review implementation decisions with frameworks team
boolean specifiesGlobalProxy = false;
String globalProxySpec = null;
@@ -505,6 +541,25 @@
}
out.endTag(null, TAG_CROSS_PROFILE_WIDGET_PROVIDERS);
}
+ writePackageListToXml(out, TAG_PERMITTED_ACCESSIBILITY_SERVICES,
+ permittedAccessiblityServices);
+ writePackageListToXml(out, TAG_PERMITTED_IMES, permittedInputMethods);
+ }
+
+ void writePackageListToXml(XmlSerializer out, String outerTag,
+ List<String> packageList)
+ throws IllegalArgumentException, IllegalStateException, IOException {
+ if (packageList == null) {
+ return;
+ }
+
+ out.startTag(null, outerTag);
+ for (String packageName : packageList) {
+ out.startTag(null, TAG_PACKAGE_LIST_ITEM);
+ out.attribute(null, ATTR_VALUE, packageName);
+ out.endTag(null, TAG_PACKAGE_LIST_ITEM);
+ }
+ out.endTag(null, outerTag);
}
void readFromXml(XmlPullParser parser)
@@ -588,6 +643,10 @@
trustAgentFeatures = getAllTrustAgentFeatures(parser, tag);
} else if (TAG_CROSS_PROFILE_WIDGET_PROVIDERS.equals(tag)) {
crossProfileWidgetProviders = getCrossProfileWidgetProviders(parser, tag);
+ } else if (TAG_PERMITTED_ACCESSIBILITY_SERVICES.equals(tag)) {
+ permittedAccessiblityServices = readPackageList(parser, tag);
+ } else if (TAG_PERMITTED_IMES.equals(tag)) {
+ permittedInputMethods = readPackageList(parser, tag);
} else {
Slog.w(LOG_TAG, "Unknown admin tag: " + tag);
}
@@ -595,6 +654,31 @@
}
}
+ private List<String> readPackageList(XmlPullParser parser,
+ String tag) throws XmlPullParserException, IOException {
+ List<String> result = new ArrayList<String>();
+ int outerDepth = parser.getDepth();
+ int outerType;
+ while ((outerType=parser.next()) != XmlPullParser.END_DOCUMENT
+ && (outerType != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (outerType == XmlPullParser.END_TAG || outerType == XmlPullParser.TEXT) {
+ continue;
+ }
+ String outerTag = parser.getName();
+ if (TAG_PACKAGE_LIST_ITEM.equals(outerTag)) {
+ String packageName = parser.getAttributeValue(null, ATTR_VALUE);
+ if (packageName != null) {
+ result.add(packageName);
+ } else {
+ Slog.w(LOG_TAG, "Package name missing under " + outerTag);
+ }
+ } else {
+ Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + outerTag);
+ }
+ }
+ return result;
+ }
+
private Set<String> readDisableAccountInfo(XmlPullParser parser, String tag)
throws XmlPullParserException, IOException {
int outerDepthDAM = parser.getDepth();
@@ -738,6 +822,14 @@
pw.println(disabledKeyguardFeatures);
pw.print(prefix); pw.print("crossProfileWidgetProviders=");
pw.println(crossProfileWidgetProviders);
+ if (!(permittedAccessiblityServices == null)) {
+ pw.print(prefix); pw.print("permittedAccessibilityServices=");
+ pw.println(permittedAccessiblityServices.toString());
+ }
+ if (!(permittedInputMethods == null)) {
+ pw.print(prefix); pw.print("permittedInputMethods=");
+ pw.println(permittedInputMethods.toString());
+ }
}
}
@@ -776,6 +868,7 @@
PackageManager.FEATURE_DEVICE_ADMIN);
mWakeLock = ((PowerManager)context.getSystemService(Context.POWER_SERVICE))
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DPM");
+ mLocalService = new LocalService();
if (!mHasFeature) {
// Skip the rest of the initialization
return;
@@ -796,7 +889,7 @@
filter.addDataScheme("package");
context.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
- LocalServices.addService(DevicePolicyManagerInternal.class, new LocalService());
+ LocalServices.addService(DevicePolicyManagerInternal.class, mLocalService);
}
/**
@@ -1885,44 +1978,71 @@
@Override
public boolean addCrossProfileWidgetProvider(ComponentName admin, String packageName) {
- ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- if (activeAdmin.crossProfileWidgetProviders == null) {
- activeAdmin.crossProfileWidgetProviders = new ArrayList<>();
+ final int userId = UserHandle.getCallingUserId();
+ List<String> changedProviders = null;
+
+ synchronized (this) {
+ ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin,
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ if (activeAdmin.crossProfileWidgetProviders == null) {
+ activeAdmin.crossProfileWidgetProviders = new ArrayList<>();
+ }
+ List<String> providers = activeAdmin.crossProfileWidgetProviders;
+ if (!providers.contains(packageName)) {
+ providers.add(packageName);
+ changedProviders = new ArrayList<>(providers);
+ saveSettingsLocked(userId);
+ }
}
- if (activeAdmin.crossProfileWidgetProviders.add(packageName)) {
- saveSettingsLocked(UserHandle.getCallingUserId());
+
+ if (changedProviders != null) {
+ mLocalService.notifyCrossProfileProvidersChanged(userId, changedProviders);
return true;
}
+
return false;
}
@Override
public boolean removeCrossProfileWidgetProvider(ComponentName admin, String packageName) {
- ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- if (activeAdmin.crossProfileWidgetProviders == null) {
- return false;
+ final int userId = UserHandle.getCallingUserId();
+ List<String> changedProviders = null;
+
+ synchronized (this) {
+ ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin,
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ if (activeAdmin.crossProfileWidgetProviders == null) {
+ return false;
+ }
+ List<String> providers = activeAdmin.crossProfileWidgetProviders;
+ if (providers.remove(packageName)) {
+ changedProviders = new ArrayList<>(providers);
+ saveSettingsLocked(userId);
+ }
}
- if (activeAdmin.crossProfileWidgetProviders.remove(packageName)) {
- saveSettingsLocked(UserHandle.getCallingUserId());
+
+ if (changedProviders != null) {
+ mLocalService.notifyCrossProfileProvidersChanged(userId, changedProviders);
return true;
}
+
return false;
}
@Override
public List<String> getCrossProfileWidgetProviders(ComponentName admin) {
- ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- if (activeAdmin.crossProfileWidgetProviders == null
- || activeAdmin.crossProfileWidgetProviders.isEmpty()) {
- return null;
- }
- if (Binder.getCallingUid() == Process.myUid()) {
- return new ArrayList<>(activeAdmin.crossProfileWidgetProviders);
- } else {
- return activeAdmin.crossProfileWidgetProviders;
+ synchronized (this) {
+ ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin,
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ if (activeAdmin.crossProfileWidgetProviders == null
+ || activeAdmin.crossProfileWidgetProviders.isEmpty()) {
+ return null;
+ }
+ if (Binder.getCallingUid() == Process.myUid()) {
+ return new ArrayList<>(activeAdmin.crossProfileWidgetProviders);
+ } else {
+ return activeAdmin.crossProfileWidgetProviders;
+ }
}
}
@@ -3927,6 +4047,343 @@
}
}
+ /**
+ * @return true if all packages in enabledPackages are either in the list
+ * permittedList or are a system app.
+ */
+ private boolean checkPackagesInPermittedListOrSystem(List<String> enabledPackages,
+ List<String> permittedList) {
+ int userIdToCheck = UserHandle.getCallingUserId();
+ long id = Binder.clearCallingIdentity();
+ try {
+ // If we have an enabled packages list for a managed profile the packages
+ // we should check are installed for the parent user.
+ UserInfo user = mUserManager.getUserInfo(userIdToCheck);
+ if (user.isManagedProfile()) {
+ userIdToCheck = user.profileGroupId;
+ }
+
+ IPackageManager pm = AppGlobals.getPackageManager();
+ for (String enabledPackage : enabledPackages) {
+ boolean systemService = false;
+ try {
+ ApplicationInfo applicationInfo = pm.getApplicationInfo(enabledPackage,
+ PackageManager.GET_UNINSTALLED_PACKAGES, userIdToCheck);
+ systemService = (applicationInfo.flags
+ & ApplicationInfo.FLAG_SYSTEM) != 0;
+ } catch (RemoteException e) {
+ Log.i(LOG_TAG, "Can't talk to package managed", e);
+ }
+ if (!systemService && !permittedList.contains(enabledPackage)) {
+ return false;
+ }
+ }
+ } finally {
+ restoreCallingIdentity(id);
+ }
+ return true;
+ }
+
+ private AccessibilityManager getAccessibilityManagerForUser(int userId) {
+ // Not using AccessibilityManager.getInstance because that guesses
+ // at the user you require based on callingUid and caches for a given
+ // process.
+ IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
+ IAccessibilityManager service = iBinder == null
+ ? null : IAccessibilityManager.Stub.asInterface(iBinder);
+ return new AccessibilityManager(mContext, service, userId);
+ }
+
+ @Override
+ public boolean setPermittedAccessibilityServices(ComponentName who, List packageList) {
+ if (!mHasFeature) {
+ return false;
+ }
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+
+ if (packageList != null) {
+ int userId = UserHandle.getCallingUserId();
+ List<AccessibilityServiceInfo> enabledServices = null;
+ long id = Binder.clearCallingIdentity();
+ try {
+ UserInfo user = mUserManager.getUserInfo(userId);
+ if (user.isManagedProfile()) {
+ userId = user.profileGroupId;
+ }
+ AccessibilityManager accessibilityManager = getAccessibilityManagerForUser(userId);
+ enabledServices = accessibilityManager.getEnabledAccessibilityServiceList(
+ AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
+ } finally {
+ restoreCallingIdentity(id);
+ }
+
+ if (enabledServices != null) {
+ List<String> enabledPackages = new ArrayList<String>();
+ for (AccessibilityServiceInfo service : enabledServices) {
+ enabledPackages.add(service.getResolveInfo().serviceInfo.packageName);
+ }
+ if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList)) {
+ Slog.e(LOG_TAG, "Cannot set permitted accessibility services, "
+ + "because it contains already enabled accesibility services.");
+ return false;
+ }
+ }
+ }
+
+ synchronized (this) {
+ ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ admin.permittedAccessiblityServices = packageList;
+ saveSettingsLocked(UserHandle.getCallingUserId());
+ }
+ return true;
+ }
+
+ @Override
+ public List getPermittedAccessibilityServices(ComponentName who) {
+ if (!mHasFeature) {
+ return null;
+ }
+
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+
+ synchronized (this) {
+ ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ return admin.permittedAccessiblityServices;
+ }
+ }
+
+ @Override
+ public List getPermittedAccessibilityServicesForUser(int userId) {
+ if (!mHasFeature) {
+ return null;
+ }
+ synchronized (this) {
+ List<String> result = null;
+ // If we have multiple profiles we return the intersection of the
+ // permitted lists. This can happen in cases where we have a device
+ // and profile owner.
+ List<UserInfo> profiles = mUserManager.getProfiles(userId);
+ final int PROFILES_SIZE = profiles.size();
+ for (int i = 0; i < PROFILES_SIZE; ++i) {
+ // Just loop though all admins, only device or profiles
+ // owners can have permitted lists set.
+ DevicePolicyData policy = getUserData(profiles.get(i).id);
+ final int N = policy.mAdminList.size();
+ for (int j = 0; j < N; j++) {
+ ActiveAdmin admin = policy.mAdminList.get(j);
+ List<String> fromAdmin = admin.permittedAccessiblityServices;
+ if (fromAdmin != null) {
+ if (result == null) {
+ result = new ArrayList<String>(fromAdmin);
+ } else {
+ result.retainAll(fromAdmin);
+ }
+ }
+ }
+ }
+
+ // If we have a permitted list add all system accessibility services.
+ if (result != null) {
+ long id = Binder.clearCallingIdentity();
+ try {
+ UserInfo user = mUserManager.getUserInfo(userId);
+ if (user.isManagedProfile()) {
+ userId = user.profileGroupId;
+ }
+ AccessibilityManager accessibilityManager =
+ getAccessibilityManagerForUser(userId);
+ List<AccessibilityServiceInfo> installedServices =
+ accessibilityManager.getInstalledAccessibilityServiceList();
+
+ IPackageManager pm = AppGlobals.getPackageManager();
+ if (installedServices != null) {
+ for (AccessibilityServiceInfo service : installedServices) {
+ String packageName = service.getResolveInfo().serviceInfo.packageName;
+ try {
+ ApplicationInfo applicationInfo = pm.getApplicationInfo(packageName,
+ PackageManager.GET_UNINSTALLED_PACKAGES, userId);
+ if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ result.add(packageName);
+ }
+ } catch (RemoteException e) {
+ Log.i(LOG_TAG, "Accessibility service in missing package", e);
+ }
+ }
+ }
+ } finally {
+ restoreCallingIdentity(id);
+ }
+ }
+
+ return result;
+ }
+ }
+
+ private boolean checkCallerIsCurrentUserOrProfile() {
+ int callingUserId = UserHandle.getCallingUserId();
+ long token = Binder.clearCallingIdentity();
+ try {
+ UserInfo currentUser;
+ UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
+ try {
+ currentUser = ActivityManagerNative.getDefault().getCurrentUser();
+ } catch (RemoteException e) {
+ Slog.e(LOG_TAG, "Failed to talk to activity managed.", e);
+ return false;
+ }
+
+ if (callingUser.isManagedProfile() && callingUser.profileGroupId != currentUser.id) {
+ Slog.e(LOG_TAG, "Cannot set permitted input methods for managed profile "
+ + "of a user that isn't the foreground user.");
+ return false;
+ }
+ if (!callingUser.isManagedProfile() && callingUserId != currentUser.id ) {
+ Slog.e(LOG_TAG, "Cannot set permitted input methods "
+ + "of a user that isn't the foreground user.");
+ return false;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean setPermittedInputMethods(ComponentName who, List packageList) {
+ if (!mHasFeature) {
+ return false;
+ }
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+
+ // TODO When InputMethodManager supports per user calls remove
+ // this restriction.
+ if (!checkCallerIsCurrentUserOrProfile()) {
+ return false;
+ }
+
+ if (packageList != null) {
+ // InputMethodManager fetches input methods for current user.
+ // So this can only be set when calling user is the current user
+ // or parent is current user in case of managed profiles.
+ InputMethodManager inputMethodManager = (InputMethodManager) mContext
+ .getSystemService(Context.INPUT_METHOD_SERVICE);
+ List<InputMethodInfo> enabledImes = inputMethodManager.getEnabledInputMethodList();
+
+ if (enabledImes != null) {
+ List<String> enabledPackages = new ArrayList<String>();
+ for (InputMethodInfo ime : enabledImes) {
+ enabledPackages.add(ime.getPackageName());
+ }
+ if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList)) {
+ Slog.e(LOG_TAG, "Cannot set permitted input methods, "
+ + "because it contains already enabled input method.");
+ return false;
+ }
+ }
+ }
+
+ synchronized (this) {
+ ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ admin.permittedInputMethods = packageList;
+ saveSettingsLocked(UserHandle.getCallingUserId());
+ }
+ return true;
+ }
+
+ @Override
+ public List getPermittedInputMethods(ComponentName who) {
+ if (!mHasFeature) {
+ return null;
+ }
+
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+
+ synchronized (this) {
+ ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ return admin.permittedInputMethods;
+ }
+ }
+
+ @Override
+ public List getPermittedInputMethodsForCurrentUser() {
+ UserInfo currentUser;
+ try {
+ currentUser = ActivityManagerNative.getDefault().getCurrentUser();
+ } catch (RemoteException e) {
+ Slog.e(LOG_TAG, "Failed to make remote calls to get current user", e);
+ // Activity managed is dead, just allow all IMEs
+ return null;
+ }
+
+ int userId = currentUser.id;
+ synchronized (this) {
+ List<String> result = null;
+ // If we have multiple profiles we return the intersection of the
+ // permitted lists. This can happen in cases where we have a device
+ // and profile owner.
+ List<UserInfo> profiles = mUserManager.getProfiles(userId);
+ final int PROFILES_SIZE = profiles.size();
+ for (int i = 0; i < PROFILES_SIZE; ++i) {
+ // Just loop though all admins, only device or profiles
+ // owners can have permitted lists set.
+ DevicePolicyData policy = getUserData(profiles.get(i).id);
+ final int N = policy.mAdminList.size();
+ for (int j = 0; j < N; j++) {
+ ActiveAdmin admin = policy.mAdminList.get(j);
+ List<String> fromAdmin = admin.permittedInputMethods;
+ if (fromAdmin != null) {
+ if (result == null) {
+ result = new ArrayList<String>(fromAdmin);
+ } else {
+ result.retainAll(fromAdmin);
+ }
+ }
+ }
+ }
+
+ // If we have a permitted list add all system input methods.
+ if (result != null) {
+ InputMethodManager inputMethodManager = (InputMethodManager) mContext
+ .getSystemService(Context.INPUT_METHOD_SERVICE);
+ List<InputMethodInfo> imes = inputMethodManager.getInputMethodList();
+ long id = Binder.clearCallingIdentity();
+ try {
+ IPackageManager pm = AppGlobals.getPackageManager();
+ if (imes != null) {
+ for (InputMethodInfo ime : imes) {
+ String packageName = ime.getPackageName();
+ try {
+ ApplicationInfo applicationInfo = pm.getApplicationInfo(
+ packageName, PackageManager.GET_UNINSTALLED_PACKAGES,
+ userId);
+ if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ result.add(packageName);
+ }
+ } catch (RemoteException e) {
+ Log.i(LOG_TAG, "Input method for missing package", e);
+ }
+ }
+ }
+ } finally {
+ restoreCallingIdentity(id);
+ }
+ }
+ return result;
+ }
+ }
+
@Override
public UserHandle createUser(ComponentName who, String name) {
synchronized (this) {
@@ -4046,7 +4503,12 @@
if (who == null) {
throw new NullPointerException("ComponentName is null");
}
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin activeAdmin =
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ boolean isDeviceOwner = isDeviceOwner(activeAdmin.info.getPackageName());
+ if (!isDeviceOwner && DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) {
+ throw new SecurityException("Profile owners cannot set user restriction " + key);
+ }
long id = Binder.clearCallingIdentity();
try {
@@ -4132,46 +4594,6 @@
}
@Override
- public int setApplicationsHidden(ComponentName who, Intent intent, boolean hidden) {
- int callingUserId = UserHandle.getCallingUserId();
- synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-
- long id = Binder.clearCallingIdentity();
- try {
- IPackageManager pm = AppGlobals.getPackageManager();
- List<ResolveInfo> activitiesToEnable = pm.queryIntentActivities(intent,
- intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- PackageManager.GET_DISABLED_COMPONENTS
- | PackageManager.GET_UNINSTALLED_PACKAGES,
- callingUserId);
-
- if (DBG) Slog.d(LOG_TAG, "Enabling activities: " + activitiesToEnable);
- int numberOfAppsUnhidden = 0;
- if (activitiesToEnable != null) {
- for (ResolveInfo info : activitiesToEnable) {
- if (info.activityInfo != null) {
- numberOfAppsUnhidden++;
- pm.setApplicationHiddenSettingAsUser(info.activityInfo.packageName,
- hidden, callingUserId);
- }
- }
- }
- return numberOfAppsUnhidden;
- } catch (RemoteException re) {
- // shouldn't happen
- Slog.e(LOG_TAG, "Failed to setApplicationsHiddenSettingsWithIntent", re);
- } finally {
- restoreCallingIdentity(id);
- }
- return 0;
- }
- }
-
- @Override
public boolean isApplicationHidden(ComponentName who, String packageName) {
int callingUserId = UserHandle.getCallingUserId();
synchronized (this) {
@@ -4347,7 +4769,8 @@
}
@Override
- public void setBlockUninstall(ComponentName who, String packageName, boolean blockUninstall) {
+ public void setUninstallBlocked(ComponentName who, String packageName,
+ boolean uninstallBlocked) {
final int userId = UserHandle.getCallingUserId();
synchronized (this) {
@@ -4359,7 +4782,7 @@
long id = Binder.clearCallingIdentity();
try {
IPackageManager pm = AppGlobals.getPackageManager();
- pm.setBlockUninstallForUser(packageName, blockUninstall, userId);
+ pm.setBlockUninstallForUser(packageName, uninstallBlocked, userId);
} catch (RemoteException re) {
// Shouldn't happen.
Slog.e(LOG_TAG, "Failed to setBlockUninstallForUser", re);
@@ -4370,7 +4793,7 @@
}
@Override
- public boolean getBlockUninstall(ComponentName who, String packageName) {
+ public boolean getUninstallBlocked(ComponentName who, String packageName) {
final int userId = UserHandle.getCallingUserId();
synchronized (this) {
@@ -4655,26 +5078,51 @@
}
private final class LocalService extends DevicePolicyManagerInternal {
+ private List<OnCrossProfileWidgetProvidersChangeListener> mWidgetProviderListeners;
+
@Override
public List<String> getCrossProfileWidgetProviders(int profileId) {
- ComponentName ownerComponent = mDeviceOwner.getProfileOwnerComponent(profileId);
- if (ownerComponent == null) {
- return Collections.emptyList();
+ synchronized (DevicePolicyManagerService.this) {
+ ComponentName ownerComponent = mDeviceOwner.getProfileOwnerComponent(profileId);
+ if (ownerComponent == null) {
+ return Collections.emptyList();
+ }
+
+ DevicePolicyData policy = getUserData(profileId);
+ ActiveAdmin admin = policy.mAdminMap.get(ownerComponent);
+
+ if (admin == null || admin.crossProfileWidgetProviders == null
+ || admin.crossProfileWidgetProviders.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ return admin.crossProfileWidgetProviders;
}
+ }
- DevicePolicyData policy = getUserData(profileId);
- ActiveAdmin admin = policy.mAdminMap.get(ownerComponent);
-
- if (admin == null) {
- return Collections.emptyList();
+ @Override
+ public void addOnCrossProfileWidgetProvidersChangeListener(
+ OnCrossProfileWidgetProvidersChangeListener listener) {
+ synchronized (DevicePolicyManagerService.this) {
+ if (mWidgetProviderListeners == null) {
+ mWidgetProviderListeners = new ArrayList<>();
+ }
+ if (!mWidgetProviderListeners.contains(listener)) {
+ mWidgetProviderListeners.add(listener);
+ }
}
+ }
- if (admin.crossProfileWidgetProviders == null
- || admin.crossProfileWidgetProviders.isEmpty()) {
- return Collections.emptyList();
+ private void notifyCrossProfileProvidersChanged(int userId, List<String> packages) {
+ final List<OnCrossProfileWidgetProvidersChangeListener> listeners;
+ synchronized (DevicePolicyManagerService.this) {
+ listeners = new ArrayList<>(mWidgetProviderListeners);
}
-
- return admin.crossProfileWidgetProviders;
+ final int listenerCount = listeners.size();
+ for (int i = 0; i < listenerCount; i++) {
+ OnCrossProfileWidgetProvidersChangeListener listener = listeners.get(i);
+ listener.onCrossProfileWidgetProvidersChanged(userId, packages);
+ }
}
}
}
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 4ff3899..f25fc62 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -8,11 +8,13 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_STATIC_JAVA_LIBRARIES := \
+ services.core \
+ services.devicepolicy \
easymocklib \
guava \
mockito-target
-LOCAL_JAVA_LIBRARIES := android.test.runner services
+LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_PACKAGE_NAME := FrameworksServicesTests
diff --git a/telecomm/java/android/telecomm/AudioState.java b/telecomm/java/android/telecomm/AudioState.java
index 491af14..a5fda79 100644
--- a/telecomm/java/android/telecomm/AudioState.java
+++ b/telecomm/java/android/telecomm/AudioState.java
@@ -26,25 +26,25 @@
*/
public final class AudioState implements Parcelable {
/** Direct the audio stream through the device's earpiece. */
- public static int ROUTE_EARPIECE = 0x00000001;
+ public static final int ROUTE_EARPIECE = 0x00000001;
/** Direct the audio stream through Bluetooth. */
- public static int ROUTE_BLUETOOTH = 0x00000002;
+ public static final int ROUTE_BLUETOOTH = 0x00000002;
/** Direct the audio stream through a wired headset. */
- public static int ROUTE_WIRED_HEADSET = 0x00000004;
+ public static final int ROUTE_WIRED_HEADSET = 0x00000004;
/** Direct the audio stream through the device's spakerphone. */
- public static int ROUTE_SPEAKER = 0x00000008;
+ public static final int ROUTE_SPEAKER = 0x00000008;
/**
* Direct the audio stream through the device's earpiece or wired headset if one is
* connected.
*/
- public static int ROUTE_WIRED_OR_EARPIECE = ROUTE_EARPIECE | ROUTE_WIRED_HEADSET;
+ public static final int ROUTE_WIRED_OR_EARPIECE = ROUTE_EARPIECE | ROUTE_WIRED_HEADSET;
/** Bit mask of all possible audio routes. */
- public static int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
+ public static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
ROUTE_SPEAKER;
/** True if the call is muted, false otherwise. */
diff --git a/telecomm/java/android/telecomm/Call.java b/telecomm/java/android/telecomm/Call.java
index 63f85e9..a71f739 100644
--- a/telecomm/java/android/telecomm/Call.java
+++ b/telecomm/java/android/telecomm/Call.java
@@ -329,6 +329,7 @@
*
* @param call The {@code Call} invoking this method.
* @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
+ * @hide
*/
public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
@@ -582,6 +583,7 @@
* Obtains an object that can be used to display video from this {@code Call}.
*
* @return An {@code Call.VideoCall}.
+ * @hide
*/
public InCallService.VideoCall getVideoCall() {
return mVideoCall;
diff --git a/telecomm/java/android/telecomm/Conference.java b/telecomm/java/android/telecomm/Conference.java
index 34b9dae..44accb7 100644
--- a/telecomm/java/android/telecomm/Conference.java
+++ b/telecomm/java/android/telecomm/Conference.java
@@ -163,6 +163,7 @@
* @return True if the connection was successfully removed.
*/
public void removeConnection(Connection connection) {
+ Log.d(this, "removing %s from %s", connection, mChildConnections);
if (connection != null && mChildConnections.remove(connection)) {
connection.resetConference();
for (Listener l : mListeners) {
@@ -177,7 +178,7 @@
public void destroy() {
Log.d(this, "destroying conference : %s", this);
// Tear down the children.
- for (Connection connection : new ArrayList<>(mChildConnections)) {
+ for (Connection connection : mChildConnections) {
Log.d(this, "removing connection %s", connection);
removeConnection(connection);
}
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index c1d5715..d8f487f 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -65,8 +65,6 @@
// Flag controlling whether PII is emitted into the logs
private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
- private static Connection sNullConnection;
-
/** @hide */
public abstract static class Listener {
public void onStateChanged(Connection c, int state) {}
@@ -89,6 +87,7 @@
public void onConferenceChanged(Connection c, Conference conference) {}
}
+ /** @hide */
public static abstract class VideoProvider {
/**
@@ -476,9 +475,8 @@
private boolean mAudioModeIsVoip;
private StatusHints mStatusHints;
private int mVideoState;
- private int mFailureCode;
- private String mFailureMessage;
- private boolean mIsCanceled;
+ private int mDisconnectCause;
+ private String mDisconnectMessage;
private Conference mConference;
private ConnectionService mConnectionService;
@@ -531,6 +529,7 @@
* {@link VideoProfile.VideoState#RX_ENABLED}.
*
* @return The video state of the call.
+ * @hide
*/
public final int getVideoState() {
return mVideoState;
@@ -604,17 +603,17 @@
}
/**
- * @return The failure code ({@see DisconnectCause}) associated with this failed connection.
+ * @return The {@link DisconnectCause} for this connection.
*/
- public final int getFailureCode() {
- return mFailureCode;
+ public final int getDisconnectCause() {
+ return mDisconnectCause;
}
/**
- * @return The reason for the connection failure. This will not be displayed to the user.
+ * @return The disconnect message for this connection.
*/
- public final String getFailureMessage() {
- return mFailureMessage;
+ public final String getDisconnectMessage() {
+ return mDisconnectMessage;
}
/**
@@ -702,6 +701,7 @@
* {@link VideoProfile.VideoState#RX_ENABLED}.
*
* @param videoState The new video state.
+ * @hide
*/
public final void setVideoState(int videoState) {
Log.d(this, "setVideoState %d", videoState);
@@ -758,6 +758,7 @@
/**
* Sets the video call provider.
* @param videoProvider The video provider.
+ * @hide
*/
public final void setVideoProvider(VideoProvider videoProvider) {
mVideoProvider = videoProvider;
@@ -766,6 +767,7 @@
}
}
+ /** @hide */
public final VideoProvider getVideoProvider() {
return mVideoProvider;
}
@@ -778,6 +780,8 @@
* @param message Optional call-service-provided message about the disconnect.
*/
public final void setDisconnected(int cause, String message) {
+ mDisconnectCause = cause;
+ mDisconnectMessage = message;
setState(STATE_DISCONNECTED);
Log.d(this, "Disconnected with cause %d message %s", cause, message);
for (Listener l : mListeners) {
@@ -915,10 +919,11 @@
*/
public final boolean setConference(Conference conference) {
// We check to see if it is already part of another conference.
- if (mConference == null && mConnectionService != null &&
- mConnectionService.containsConference(conference)) {
+ if (mConference == null) {
mConference = conference;
- fireConferenceChanged();
+ if (mConnectionService != null && mConnectionService.containsConference(conference)) {
+ fireConferenceChanged();
+ }
return true;
}
return false;
@@ -930,6 +935,7 @@
*/
public final void resetConference() {
if (mConference != null) {
+ Log.d(this, "Conference reset");
mConference = null;
fireConferenceChanged();
}
@@ -1060,13 +1066,6 @@
return builder.toString();
}
- static synchronized Connection getNullConnection() {
- if (sNullConnection == null) {
- sNullConnection = new Connection() {};
- }
- return sNullConnection;
- }
-
private void setState(int state) {
if (mState == STATE_DISCONNECTED && mState != state) {
Log.d(this, "Connection already DISCONNECTED; cannot transition out of this state.");
@@ -1082,31 +1081,29 @@
}
}
- static class FailureSignalingConnection extends Connection {
- public FailureSignalingConnection(int code, String message) {
- setDisconnected(code, message);
+ private static class FailureSignalingConnection extends Connection {
+ public FailureSignalingConnection(int cause, String message) {
+ setDisconnected(cause, message);
}
}
/**
* Return a {@code Connection} which represents a failed connection attempt. The returned
- * {@code Connection} will have a {@link #getFailureCode()} and {@link #getFailureMessage()}
- * as specified, a {@link #getState()} of {@link #STATE_DISCONNECTED}.
+ * {@code Connection} will have a {@link #getDisconnectCause()} and
+ * {@link #getDisconnectMessage()} as specified, and a {@link #getState()} of
+ * {@link #STATE_DISCONNECTED}.
* <p>
* The returned {@code Connection} can be assumed to {@link #destroy()} itself when appropriate,
* so users of this method need not maintain a reference to its return value to destroy it.
*
- * @param code The failure code ({@see DisconnectCause}).
+ * @param cause The disconnect cause, ({@see DisconnectCause}).
* @param message A reason for why the connection failed (not intended to be shown to the user).
* @return A {@code Connection} which indicates failure.
*/
- public static Connection createFailedConnection(final int code, final String message) {
- return new FailureSignalingConnection(code, message);
+ public static Connection createFailedConnection(int cause, String message) {
+ return new FailureSignalingConnection(cause, message);
}
- private static final Connection CANCELED_CONNECTION =
- new FailureSignalingConnection(DisconnectCause.OUTGOING_CANCELED, null);
-
/**
* Return a {@code Connection} which represents a canceled connection attempt. The returned
* {@code Connection} will have state {@link #STATE_DISCONNECTED}, and cannot be moved out of
@@ -1119,7 +1116,7 @@
* @return A {@code Connection} which indicates that the underlying call should be canceled.
*/
public static Connection createCanceledConnection() {
- return CANCELED_CONNECTION;
+ return new FailureSignalingConnection(DisconnectCause.OUTGOING_CANCELED, null);
}
private final void fireOnConferenceableConnectionsChanged() {
diff --git a/telecomm/java/android/telecomm/ConnectionRequest.java b/telecomm/java/android/telecomm/ConnectionRequest.java
index 5ea1d1a..b991af1 100644
--- a/telecomm/java/android/telecomm/ConnectionRequest.java
+++ b/telecomm/java/android/telecomm/ConnectionRequest.java
@@ -93,6 +93,7 @@
* {@link VideoProfile.VideoState#RX_ENABLED}.
*
* @return The video state for the connection.
+ * @hide
*/
public int getVideoState() {
return mVideoState;
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index 03b6c7b..b77bb18 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -73,6 +73,8 @@
private static final int MSG_ON_PHONE_ACCOUNT_CLICKED = 15;
private static final int MSG_REMOVE_CONNECTION_SERVICE_ADAPTER = 16;
+ private static Connection sNullConnection;
+
private final Map<String, Connection> mConnectionById = new HashMap<>();
private final Map<Connection, String> mIdByConnection = new HashMap<>();
private final Map<String, Conference> mConferenceById = new HashMap<>();
@@ -82,6 +84,7 @@
private final ConnectionServiceAdapter mAdapter = new ConnectionServiceAdapter();
private boolean mAreAccountsInitialized = false;
+ private Conference sNullConference;
private final IBinder mBinder = new IConnectionService.Stub() {
@Override
@@ -498,36 +501,29 @@
final String callId,
final ConnectionRequest request,
boolean isIncoming) {
- Log.d(this, "call %s", request);
+ Log.d(this, "createConnection, callManagerAccount: %s, callId: %s, request: %s, " +
+ "isIncoming: %b", callManagerAccount, callId, request, isIncoming);
- Connection createdConnection = isIncoming
+ Connection connection = isIncoming
? onCreateIncomingConnection(callManagerAccount, request)
: onCreateOutgoingConnection(callManagerAccount, request);
-
- if (createdConnection == null) {
- Log.d(this, "adapter handleCreateConnectionComplete CANCELED %s", callId);
- // Tell telecomm to try a different service.
- createdConnection = Connection.createCanceledConnection();
+ Log.d(this, "createConnection, connection: %s", connection);
+ if (connection == null) {
+ connection = Connection.createFailedConnection(DisconnectCause.OUTGOING_FAILURE, null);
}
- connectionCreated(callId, request, createdConnection);
- }
- private void connectionCreated(
- String callId,
- ConnectionRequest request,
- Connection connection) {
- if (!(connection instanceof Connection.FailureSignalingConnection)) {
+ if (connection.getState() != Connection.STATE_DISCONNECTED) {
addConnection(callId, connection);
}
Uri handle = connection.getHandle();
String number = handle == null ? "null" : handle.getSchemeSpecificPart();
- Log.v(this, "connectionCreated, parcelableconnection: %s, %d, %s",
+ Log.v(this, "createConnection, number: %s, state: %s, capabilities: %s",
Connection.toLogSafePhoneNumber(number),
- connection.getState(),
+ Connection.stateToString(connection.getState()),
PhoneCapabilities.toString(connection.getCallCapabilities()));
- Log.d(this, "adapter handleCreateConnectionSuccessful %s", callId);
+ Log.d(this, "createConnection, calling handleCreateConnectionSuccessful %s", callId);
mAdapter.handleCreateConnectionComplete(
callId,
request,
@@ -545,8 +541,8 @@
connection.isRequestingRingback(),
connection.getAudioModeIsVoip(),
connection.getStatusHints(),
- connection.getFailureCode(),
- connection.getFailureMessage()));
+ connection.getDisconnectCause(),
+ connection.getDisconnectMessage()));
}
private void abort(String callId) {
@@ -566,17 +562,29 @@
private void disconnect(String callId) {
Log.d(this, "disconnect %s", callId);
- findConnectionForAction(callId, "disconnect").onDisconnect();
+ if (mConnectionById.containsKey(callId)) {
+ findConnectionForAction(callId, "disconnect").onDisconnect();
+ } else {
+ findConferenceForAction(callId, "disconnect").onDisconnect();
+ }
}
private void hold(String callId) {
Log.d(this, "hold %s", callId);
- findConnectionForAction(callId, "hold").onHold();
+ if (mConnectionById.containsKey(callId)) {
+ findConnectionForAction(callId, "hold").onHold();
+ } else {
+ findConferenceForAction(callId, "hold").onHold();
+ }
}
private void unhold(String callId) {
Log.d(this, "unhold %s", callId);
- findConnectionForAction(callId, "unhold").onUnhold();
+ if (mConnectionById.containsKey(callId)) {
+ findConnectionForAction(callId, "unhold").onUnhold();
+ } else {
+ findConferenceForAction(callId, "unhold").onUnhold();
+ }
}
private void onAudioStateChanged(String callId, AudioState audioState) {
@@ -598,13 +606,13 @@
Log.d(this, "conference %s, %s", callId1, callId2);
Connection connection1 = findConnectionForAction(callId1, "conference");
- if (connection1 == Connection.getNullConnection()) {
+ if (connection1 == getNullConnection()) {
Log.w(this, "Connection1 missing in conference request %s.", callId1);
return;
}
Connection connection2 = findConnectionForAction(callId2, "conference");
- if (connection2 == Connection.getNullConnection()) {
+ if (connection2 == getNullConnection()) {
Log.w(this, "Connection2 missing in conference request %s.", callId2);
return;
}
@@ -616,12 +624,15 @@
Log.d(this, "splitFromConference(%s)", callId);
Connection connection = findConnectionForAction(callId, "splitFromConference");
- if (connection == Connection.getNullConnection()) {
+ if (connection == getNullConnection()) {
Log.w(this, "Connection missing in conference request %s.", callId);
return;
}
- // TODO: Find existing conference call and invoke split(connection).
+ Conference conference = connection.getConference();
+ if (conference != null) {
+ conference.onSeparate(connection);
+ }
}
private void onPostDialContinue(String callId, boolean proceed) {
@@ -881,6 +892,28 @@
return mConnectionById.get(callId);
}
Log.w(this, "%s - Cannot find Connection %s", action, callId);
- return Connection.getNullConnection();
+ return getNullConnection();
+ }
+
+ static synchronized Connection getNullConnection() {
+ if (sNullConnection == null) {
+ sNullConnection = new Connection() {};
+ }
+ return sNullConnection;
+ }
+
+ private Conference findConferenceForAction(String conferenceId, String action) {
+ if (mConferenceById.containsKey(conferenceId)) {
+ return mConferenceById.get(conferenceId);
+ }
+ Log.w(this, "%s - Cannot find conference %s", action, conferenceId);
+ return getNullConference();
+ }
+
+ private Conference getNullConference() {
+ if (sNullConference == null) {
+ sNullConference = new Conference(null) {};
+ }
+ return sNullConference;
}
}
diff --git a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
index 41c6360..cb63646 100644
--- a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
@@ -197,6 +197,7 @@
void setIsConferenced(String callId, String conferenceCallId) {
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
+ Log.d(this, "sending connection %s with conference %s", callId, conferenceCallId);
adapter.setIsConferenced(callId, conferenceCallId);
} catch (RemoteException ignored) {
}
diff --git a/telecomm/java/android/telecomm/InCallService.java b/telecomm/java/android/telecomm/InCallService.java
index 794ec41..a062632 100644
--- a/telecomm/java/android/telecomm/InCallService.java
+++ b/telecomm/java/android/telecomm/InCallService.java
@@ -198,6 +198,7 @@
/**
* Class to invoke functionality related to video calls.
+ * @hide
*/
public static abstract class VideoCall {
@@ -294,6 +295,7 @@
/**
* Listener class which invokes callbacks after video call actions occur.
+ * @hide
*/
public static abstract class Listener {
/**
diff --git a/telecomm/java/android/telecomm/ParcelableConnection.java b/telecomm/java/android/telecomm/ParcelableConnection.java
index 30ff5be..812ee55 100644
--- a/telecomm/java/android/telecomm/ParcelableConnection.java
+++ b/telecomm/java/android/telecomm/ParcelableConnection.java
@@ -41,8 +41,8 @@
private boolean mRequestingRingback;
private boolean mAudioModeIsVoip;
private StatusHints mStatusHints;
- private int mFailureCode;
- private String mFailureMessage;
+ private int mDisconnectCause;
+ private String mDisconnectMessage;
/** @hide */
public ParcelableConnection(
@@ -58,8 +58,8 @@
boolean requestingRingback,
boolean audioModeIsVoip,
StatusHints statusHints,
- int failureCode,
- String failureMessage) {
+ int disconnectCause,
+ String disconnectMessage) {
mPhoneAccount = phoneAccount;
mState = state;
mCapabilities = capabilities;
@@ -72,8 +72,8 @@
mRequestingRingback = requestingRingback;
mAudioModeIsVoip = audioModeIsVoip;
mStatusHints = statusHints;
- mFailureCode = failureCode;
- mFailureMessage = failureMessage;
+ mDisconnectCause = disconnectCause;
+ mDisconnectMessage = disconnectMessage;
}
public PhoneAccountHandle getPhoneAccount() {
@@ -125,12 +125,12 @@
return mStatusHints;
}
- public final int getFailureCode() {
- return mFailureCode;
+ public final int getDisconnectCause() {
+ return mDisconnectCause;
}
- public final String getFailureMessage() {
- return mFailureMessage;
+ public final String getDisconnectMessage() {
+ return mDisconnectMessage;
}
@Override
@@ -212,7 +212,7 @@
destination.writeByte((byte) (mRequestingRingback ? 1 : 0));
destination.writeByte((byte) (mAudioModeIsVoip ? 1 : 0));
destination.writeParcelable(mStatusHints, 0);
- destination.writeInt(mFailureCode);
- destination.writeString(mFailureMessage);
+ destination.writeInt(mDisconnectCause);
+ destination.writeString(mDisconnectMessage);
}
}
diff --git a/telecomm/java/android/telecomm/RemoteConnection.java b/telecomm/java/android/telecomm/RemoteConnection.java
index 30cfdde..70db6f5 100644
--- a/telecomm/java/android/telecomm/RemoteConnection.java
+++ b/telecomm/java/android/telecomm/RemoteConnection.java
@@ -158,6 +158,7 @@
*
* @param connection The {@code RemoteConnection} invoking this method.
* @param videoState The new video state of the {@code RemoteConnection}.
+ * @hide
*/
public void onVideoStateChanged(RemoteConnection connection, int videoState) {}
@@ -357,6 +358,7 @@
/**
* @return The video state of the {@code RemoteConnection}. See
* {@link VideoProfile.VideoState}.
+ * @hide
*/
public int getVideoState() {
return mVideoState;
diff --git a/telecomm/java/android/telecomm/TelecommManager.java b/telecomm/java/android/telecomm/TelecommManager.java
index 5192b0f..e59fea1 100644
--- a/telecomm/java/android/telecomm/TelecommManager.java
+++ b/telecomm/java/android/telecomm/TelecommManager.java
@@ -76,6 +76,7 @@
* {@link VideoProfile.VideoState#BIDIRECTIONAL},
* {@link VideoProfile.VideoState#RX_ENABLED},
* {@link VideoProfile.VideoState#TX_ENABLED}.
+ * @hide
*/
public static final String EXTRA_START_CALL_WITH_VIDEO_STATE =
"android.intent.extra.START_CALL_WITH_VIDEO_STATE";
diff --git a/telecomm/java/android/telecomm/VideoProfile.java b/telecomm/java/android/telecomm/VideoProfile.java
index b147978..028d24e 100644
--- a/telecomm/java/android/telecomm/VideoProfile.java
+++ b/telecomm/java/android/telecomm/VideoProfile.java
@@ -21,6 +21,8 @@
/**
* Represents attributes of video calls.
+ *
+ * {@hide}
*/
public class VideoProfile implements Parcelable {
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index d4f8362..71b796a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -617,6 +617,37 @@
}
/**
+ * Returns the IMEI. Return null if IMEI is not available.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ */
+ /** {@hide} */
+ public String getImei() {
+ return getImei(getDefaultSim());
+ }
+
+ /**
+ * Returns the IMEI. Return null if IMEI is not available.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ *
+ * @param slotId of which deviceID is returned
+ */
+ /** {@hide} */
+ public String getImei(int slotId) {
+ long[] subId = SubscriptionManager.getSubId(slotId);
+ try {
+ return getSubscriberInfo().getImeiUsingSubId(subId[0]);
+ } catch (RemoteException ex) {
+ return null;
+ } catch (NullPointerException ex) {
+ return null;
+ }
+ }
+
+ /**
* Returns the current location of the device.
*<p>
* If there is only one radio in the device and that radio has an LTE connection,
@@ -3025,6 +3056,42 @@
/** @hide */
@SystemApi
+ public String getCdmaMdn() {
+ return getCdmaMdn(getDefaultSubscription());
+ }
+
+ /** @hide */
+ @SystemApi
+ public String getCdmaMdn(long subId) {
+ try {
+ return getITelephony().getCdmaMdn(subId);
+ } catch (RemoteException ex) {
+ return null;
+ } catch (NullPointerException ex) {
+ return null;
+ }
+ }
+
+ /** @hide */
+ @SystemApi
+ public String getCdmaMin() {
+ return getCdmaMin(getDefaultSubscription());
+ }
+
+ /** @hide */
+ @SystemApi
+ public String getCdmaMin(long subId) {
+ try {
+ return getITelephony().getCdmaMin(subId);
+ } catch (RemoteException ex) {
+ return null;
+ } catch (NullPointerException ex) {
+ return null;
+ }
+ }
+
+ /** @hide */
+ @SystemApi
public int checkCarrierPrivilegesForPackage(String pkgname) {
try {
return getITelephony().checkCarrierPrivilegesForPackage(pkgname);
diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/com/android/ims/ImsCallProfile.java
index dcd0b79..767ecf9 100644
--- a/telephony/java/com/android/ims/ImsCallProfile.java
+++ b/telephony/java/com/android/ims/ImsCallProfile.java
@@ -21,6 +21,8 @@
import android.os.Parcelable;
import android.telecomm.VideoProfile;
+import com.android.internal.telephony.PhoneConstants;
+
/**
* Parcelable object to handle IMS call profile.
* It is created from GSMA IR.92/IR.94, 3GPP TS 24.229/TS 26.114/TS26.111.
@@ -337,6 +339,38 @@
}
/**
+ * Translate presentation value to OIR value
+ * @param presentation
+ * @return OIR valuse
+ */
+ public static int presentationToOIR(int presentation) {
+ switch (presentation) {
+ case PhoneConstants.PRESENTATION_RESTRICTED:
+ return ImsCallProfile.OIR_PRESENTATION_RESTRICTED;
+ case PhoneConstants.PRESENTATION_ALLOWED:
+ return ImsCallProfile.OIR_PRESENTATION_NOT_RESTRICTED;
+ default:
+ return ImsCallProfile.OIR_DEFAULT;
+ }
+ }
+
+ /**
+ * Translate OIR value to presentation value
+ * @param oir value
+ * @return presentation value
+ */
+ public static int OIRToPresentation(int oir) {
+ switch(oir) {
+ case ImsCallProfile.OIR_PRESENTATION_RESTRICTED:
+ return PhoneConstants.PRESENTATION_RESTRICTED;
+ case ImsCallProfile.OIR_PRESENTATION_NOT_RESTRICTED:
+ return PhoneConstants.PRESENTATION_ALLOWED;
+ default:
+ return PhoneConstants.PRESENTATION_UNKNOWN;
+ }
+ }
+
+ /**
* Determines if a video state is set in a video state bit-mask.
*
* @param videoState The video state bit mask.
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index 4734965..552abaf 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -33,6 +33,10 @@
*/
String getDeviceIdUsingSubId(long subId);
+ /**
+ * Retrieves the IMEI.
+ */
+ String getImeiUsingSubId(long subId);
/**
* Retrieves the software version number for the device, e.g., IMEI/SV
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index d256f9d..b1c3c4a 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -677,6 +677,18 @@
void setImsRegistrationState(boolean registered);
/**
+ * Return MDN string for CDMA phone.
+ * @param subId user preferred subId.
+ */
+ String getCdmaMdn(long subId);
+
+ /**
+ * Return MIN string for CDMA phone.
+ * @param subId user preferred subId.
+ */
+ String getCdmaMin(long subId);
+
+ /**
* Has the calling application been granted special privileges by the carrier.
*
* If any of the packages in the calling UID has carrier privileges, the
@@ -781,5 +793,16 @@
* positive value success, data length of response
*/
int invokeOemRilRequestRaw(in byte[] oemReq, out byte[] oemResp);
-}
+ /**
+ * Check if any mobile Radios need to be shutdown.
+ *
+ * @return true is any mobile radio needs to be shutdown
+ */
+ boolean needMobileRadioShutdown();
+
+ /**
+ * Shutdown Mobile Radios
+ */
+ void shutdownMobileRadios();
+}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index a8a9057..e730bde 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -287,7 +287,10 @@
int RIL_REQUEST_ALLOW_DATA = 123;
int RIL_REQUEST_GET_HARDWARE_CONFIG = 124;
int RIL_REQUEST_SIM_AUTHENTICATION = 125;
+ int RIL_REQUEST_GET_DC_RT_INFO = 126;
+ int RIL_REQUEST_SET_DC_RT_INFO_RATE = 127;
int RIL_REQUEST_SET_DATA_PROFILE = 128;
+ int RIL_REQUEST_SHUTDOWN = 129;
int RIL_UNSOL_RESPONSE_BASE = 1000;
int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000;
diff --git a/tests/ActivityTests/res/drawable-hdpi/icon.png b/tests/ActivityTests/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..2eab6f2
--- /dev/null
+++ b/tests/ActivityTests/res/drawable-hdpi/icon.png
Binary files differ
diff --git a/tests/ActivityTests/res/drawable-mdpi/icon.png b/tests/ActivityTests/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..63aec6f
--- /dev/null
+++ b/tests/ActivityTests/res/drawable-mdpi/icon.png
Binary files differ
diff --git a/tests/ActivityTests/res/drawable-xhdpi/icon.png b/tests/ActivityTests/res/drawable-xhdpi/icon.png
new file mode 100644
index 0000000..8ea9c48
--- /dev/null
+++ b/tests/ActivityTests/res/drawable-xhdpi/icon.png
Binary files differ
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index 9002125..7f3aa77 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -28,6 +28,7 @@
import android.content.ContentProviderClient;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
@@ -219,7 +220,7 @@
@Override public boolean onMenuItemClick(MenuItem item) {
Intent intent = new Intent(ActivityTestMain.this, UserTarget.class);
sendOrderedBroadcastAsUser(intent, new UserHandle(mSecondUser), null,
- new BroadcastResultReceiver(),
+ new BroadcastResultReceiver(),
null, Activity.RESULT_OK, null, null);
return true;
}
@@ -291,6 +292,30 @@
return true;
}
});
+ menu.add("Add App Recent").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override public boolean onMenuItemClick(MenuItem item) {
+ addAppRecents(1);
+ return true;
+ }
+ });
+ menu.add("Add App 10x Recent").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override public boolean onMenuItemClick(MenuItem item) {
+ addAppRecents(10);
+ return true;
+ }
+ });
+ menu.add("Exclude!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override public boolean onMenuItemClick(MenuItem item) {
+ setExclude(true);
+ return true;
+ }
+ });
+ menu.add("Include!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override public boolean onMenuItemClick(MenuItem item) {
+ setExclude(false);
+ return true;
+ }
+ });
return true;
}
@@ -317,7 +342,36 @@
mConnections.clear();
}
- private View scrollWrap(View view) {
+ void addAppRecents(int count) {
+ ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
+ intent.setComponent(new ComponentName(this, ActivityTestMain.class));
+ for (int i=0; i<count; i++) {
+ ActivityManager.TaskDescription desc = new ActivityManager.TaskDescription();
+ desc.setLabel("Added #" + i);
+ Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
+ if ((i&1) == 0) {
+ desc.setIcon(bitmap);
+ }
+ int taskId = am.addAppTask(this, intent, desc, bitmap);
+ Log.i(TAG, "Added new task id #" + taskId);
+ }
+ }
+
+ void setExclude(boolean exclude) {
+ ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
+ List<ActivityManager.AppTask> tasks = am.getAppTasks();
+ int taskId = getTaskId();
+ for (int i=0; i<tasks.size(); i++) {
+ ActivityManager.AppTask task = tasks.get(i);
+ if (task.getTaskInfo().id == taskId) {
+ task.setExcludeFromRecents(exclude);
+ }
+ }
+ }
+ private View scrollWrap(View view) {
ScrollView scroller = new ScrollView(this);
scroller.addView(view, new ScrollView.LayoutParams(ScrollView.LayoutParams.MATCH_PARENT,
ScrollView.LayoutParams.MATCH_PARENT));
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java
index 08d7667..d402699 100644
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java
+++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java
@@ -54,7 +54,7 @@
for (int i = 0; i < rowIndices.length; i++)
rowIndices[i] = i * REGION_SIZE;
- mScript = new ScriptC_errorCalculator(mRS, resources, R.raw.errorcalculator);
+ mScript = new ScriptC_errorCalculator(mRS);
mScript.set_HEIGHT(height);
mScript.set_WIDTH(width);
mScript.set_REGION_SIZE(REGION_SIZE);
diff --git a/tests/RenderScriptTests/FountainFbo/Android.mk b/tests/RenderScriptTests/FountainFbo/Android.mk
index 4535eb1..c0f3323 100644
--- a/tests/RenderScriptTests/FountainFbo/Android.mk
+++ b/tests/RenderScriptTests/FountainFbo/Android.mk
@@ -25,5 +25,6 @@
# LOCAL_SDK_VERSION := current
LOCAL_PACKAGE_NAME := RsFountainFbo
+LOCAL_SDK_VERSION := 14
include $(BUILD_PACKAGE)
diff --git a/tests/Split/Android.mk b/tests/Split/Android.mk
index 7884d4d..b068bef 100644
--- a/tests/Split/Android.mk
+++ b/tests/Split/Android.mk
@@ -20,8 +20,7 @@
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := Split
-LOCAL_AAPT_FLAGS := --split fr,de
-LOCAL_AAPT_FLAGS += -v
+LOCAL_PACKAGE_SPLITS := mdpi-v4 hdpi-v4 xhdpi-v4 xxhdpi-v4
LOCAL_MODULE_TAGS := tests
diff --git a/tests/Split/AndroidManifest.xml b/tests/Split/AndroidManifest.xml
index a4956a7..0de8344 100644
--- a/tests/Split/AndroidManifest.xml
+++ b/tests/Split/AndroidManifest.xml
@@ -16,7 +16,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.example.split">
- <application android:label="@string/app_title">
+ <application android:label="@string/app_title"
+ android:icon="@mipmap/ic_app">
<activity android:name="ActivityMain">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/tests/Split/res/drawable-hdpi/image.png b/tests/Split/res/drawable-hdpi/image.png
new file mode 100644
index 0000000..dcf4242
--- /dev/null
+++ b/tests/Split/res/drawable-hdpi/image.png
Binary files differ
diff --git a/tests/Split/res/drawable-mdpi/image.png b/tests/Split/res/drawable-mdpi/image.png
new file mode 100644
index 0000000..3437952
--- /dev/null
+++ b/tests/Split/res/drawable-mdpi/image.png
Binary files differ
diff --git a/tests/Split/res/drawable-xhdpi/image.png b/tests/Split/res/drawable-xhdpi/image.png
new file mode 100644
index 0000000..68b2f8e
--- /dev/null
+++ b/tests/Split/res/drawable-xhdpi/image.png
Binary files differ
diff --git a/tests/Split/res/drawable-xxhdpi/image.png b/tests/Split/res/drawable-xxhdpi/image.png
new file mode 100644
index 0000000..4bff9b9
--- /dev/null
+++ b/tests/Split/res/drawable-xxhdpi/image.png
Binary files differ
diff --git a/tests/Split/res/layout/main.xml b/tests/Split/res/layout/main.xml
index 36992a2..607cdb0 100644
--- a/tests/Split/res/layout/main.xml
+++ b/tests/Split/res/layout/main.xml
@@ -14,6 +14,12 @@
limitations under the License.
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent"/>
+ android:layout_height="match_parent">
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerInParent="true"
+ android:src="@drawable/image"/>
+</RelativeLayout>
diff --git a/tests/Split/res/mipmap-hdpi/ic_app.png b/tests/Split/res/mipmap-hdpi/ic_app.png
new file mode 100644
index 0000000..ffcb9e5
--- /dev/null
+++ b/tests/Split/res/mipmap-hdpi/ic_app.png
Binary files differ
diff --git a/tests/Split/res/mipmap-mdpi/ic_app.png b/tests/Split/res/mipmap-mdpi/ic_app.png
new file mode 100644
index 0000000..35f5b45
--- /dev/null
+++ b/tests/Split/res/mipmap-mdpi/ic_app.png
Binary files differ
diff --git a/tests/Split/res/mipmap-xhdpi/ic_app.png b/tests/Split/res/mipmap-xhdpi/ic_app.png
new file mode 100644
index 0000000..bfe71fe
--- /dev/null
+++ b/tests/Split/res/mipmap-xhdpi/ic_app.png
Binary files differ
diff --git a/tests/Split/res/mipmap-xxhdpi/ic_app.png b/tests/Split/res/mipmap-xxhdpi/ic_app.png
new file mode 100644
index 0000000..b65532c
--- /dev/null
+++ b/tests/Split/res/mipmap-xxhdpi/ic_app.png
Binary files differ
diff --git a/tests/Split/res/mipmap-xxxhdpi/ic_app.png b/tests/Split/res/mipmap-xxxhdpi/ic_app.png
new file mode 100644
index 0000000..2679b49
--- /dev/null
+++ b/tests/Split/res/mipmap-xxxhdpi/ic_app.png
Binary files differ
diff --git a/tests/Split/src/java/com/android/example/split/ActivityMain.java b/tests/Split/src/java/com/android/example/split/ActivityMain.java
index a15fb3c..63963a2 100644
--- a/tests/Split/src/java/com/android/example/split/ActivityMain.java
+++ b/tests/Split/src/java/com/android/example/split/ActivityMain.java
@@ -24,8 +24,6 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- TextView text = new TextView(this);
- text.setText(R.string.test);
- setContentView(text);
+ setContentView(R.layout.main);
}
}
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index eead68c..b44e2d1 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -561,15 +561,17 @@
return NO_ERROR;
}
-#if 0
- printf("Error adding file %s: group %s already exists in leaf=%s path=%s\n",
- file->getSourceFile().string(),
- file->getGroupEntry().toDirName(String8()).string(),
- mLeaf.string(), mPath.string());
-#endif
+ // Check if the version is automatically applied. This is a common source of
+ // error.
+ ConfigDescription withoutVersion = file->getGroupEntry().toParams();
+ withoutVersion.version = 0;
+ AaptConfig::applyVersionForCompatibility(&withoutVersion);
- SourcePos(file->getSourceFile(), -1).error("Duplicate file.\n%s: Original is here.",
- getPrintableSource().string());
+ const sp<AaptFile>& originalFile = mFiles.valueAt(index);
+ SourcePos(file->getSourceFile(), -1)
+ .error("Duplicate file.\n%s: Original is here. %s",
+ originalFile->getPrintableSource().string(),
+ (withoutVersion.version != 0) ? "The version qualifier may be implied." : "");
return UNKNOWN_ERROR;
}
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 0a80805..1d93b89 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -770,7 +770,14 @@
if (!addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionCode",
bundle->getVersionCode(), errorOnFailedInsert, replaceVersion)) {
return UNKNOWN_ERROR;
+ } else {
+ const XMLNode::attribute_entry* attr = root->getAttribute(
+ String16(RESOURCES_ANDROID_NAMESPACE), String16("versionCode"));
+ if (attr != NULL) {
+ bundle->setVersionCode(strdup(String8(attr->string).string()));
+ }
}
+
if (!addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionName",
bundle->getVersionName(), errorOnFailedInsert, replaceVersion)) {
return UNKNOWN_ERROR;
@@ -1392,7 +1399,8 @@
sp<ApkSplit>& split = splits.editItemAt(i);
sp<AaptFile> flattenedTable = new AaptFile(String8("resources.arsc"),
AaptGroupEntry(), String8());
- err = table.flatten(bundle, split->getResourceFilter(), flattenedTable);
+ err = table.flatten(bundle, split->getResourceFilter(),
+ flattenedTable, split->isBase());
if (err != NO_ERROR) {
fprintf(stderr, "Failed to generate resource table for split '%s'\n",
split->getPrintableName().string());
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index c98808f..b3c364b 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -2074,10 +2074,11 @@
return mNumLocal > 0;
}
-sp<AaptFile> ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>& filter)
+sp<AaptFile> ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
+ const bool isBase)
{
sp<AaptFile> data = new AaptFile(String8(), AaptGroupEntry(), String8());
- status_t err = flatten(bundle, filter, data);
+ status_t err = flatten(bundle, filter, data, isBase);
return err == NO_ERROR ? data : NULL;
}
@@ -2699,7 +2700,9 @@
return err;
}
-status_t ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>& filter, const sp<AaptFile>& dest)
+status_t ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
+ const sp<AaptFile>& dest,
+ const bool isBase)
{
const ConfigDescription nullConfig;
@@ -2712,6 +2715,16 @@
// The libraries this table references.
Vector<sp<Package> > libraryPackages;
+ const ResTable& table = mAssets->getIncludedResources();
+ const size_t basePackageCount = table.getBasePackageCount();
+ for (size_t i = 0; i < basePackageCount; i++) {
+ size_t packageId = table.getBasePackageId(i);
+ String16 packageName(table.getBasePackageName(i));
+ if (packageId > 0x01 && packageId != 0x7f &&
+ packageName != String16("android")) {
+ libraryPackages.add(sp<Package>(new Package(packageName, packageId)));
+ }
+ }
// Iterate through all data, collecting all values (strings,
// references, etc).
@@ -2720,22 +2733,7 @@
for (pi=0; pi<N; pi++) {
sp<Package> p = mOrderedPackages.itemAt(pi);
if (p->getTypes().size() == 0) {
- // Empty, this is an imported package being used as
- // a shared library. We do not flatten this package.
- if (p->getAssignedId() != 0x01 && p->getName() != String16("android")) {
- // This is not the base Android package, and it is a library
- // so we must add a reference to the library when flattening.
- libraryPackages.add(p);
- }
continue;
- } else if (p->getAssignedId() == 0x00) {
- if (mPackageType != SharedLibrary) {
- fprintf(stderr, "ERROR: Package %s can not have ID=0x00 unless building a shared library.",
- String8(p->getName()).string());
- return UNKNOWN_ERROR;
- }
- // If this is a shared library, we also include ourselves as an entry.
- libraryPackages.add(p);
}
StringPool typeStrings(useUTF8);
@@ -2773,6 +2771,13 @@
configTypeName = "2value";
}
+ // mipmaps don't get filtered, so they will
+ // allways end up in the base. Make sure they
+ // don't end up in a split.
+ if (typeName == mipmap16 && !isBase) {
+ continue;
+ }
+
const bool filterable = (typeName != mipmap16);
const size_t N = t->getOrderedConfigs().size();
@@ -2876,10 +2881,12 @@
return amt;
}
- status_t err = flattenLibraryTable(data, libraryPackages);
- if (err != NO_ERROR) {
- fprintf(stderr, "ERROR: failed to write library table\n");
- return err;
+ if (isBase) {
+ status_t err = flattenLibraryTable(data, libraryPackages);
+ if (err != NO_ERROR) {
+ fprintf(stderr, "ERROR: failed to write library table\n");
+ return err;
+ }
}
// Build the type chunks inside of this package.
@@ -2895,6 +2902,7 @@
continue;
}
const bool filterable = (typeName != mipmap16);
+ const bool skipEntireType = (typeName == mipmap16 && !isBase);
const size_t N = t != NULL ? t->getOrderedConfigs().size() : 0;
@@ -2932,6 +2940,11 @@
if (cl->getPublic()) {
typeSpecFlags[ei] |= htodl(ResTable_typeSpec::SPEC_PUBLIC);
}
+
+ if (skipEntireType) {
+ continue;
+ }
+
const size_t CN = cl->getEntries().size();
for (size_t ci=0; ci<CN; ci++) {
if (filterable && !filter->match(cl->getEntries().keyAt(ci))) {
@@ -2948,6 +2961,10 @@
}
}
+ if (skipEntireType) {
+ continue;
+ }
+
// We need to write one type chunk for each configuration for
// which we have entries in this type.
const size_t NC = t->getUniqueConfigs().size();
@@ -3147,7 +3164,8 @@
const size_t libStart = dest->getSize();
const size_t count = libs.size();
- ResTable_lib_header* libHeader = (ResTable_lib_header*) dest->editDataInRange(libStart, sizeof(ResTable_lib_header));
+ ResTable_lib_header* libHeader = (ResTable_lib_header*) dest->editDataInRange(
+ libStart, sizeof(ResTable_lib_header));
memset(libHeader, 0, sizeof(*libHeader));
libHeader->header.type = htods(RES_TABLE_LIBRARY_TYPE);
@@ -3163,7 +3181,8 @@
String8(libPackage->getName()).string(),
(uint8_t)libPackage->getAssignedId()));
- ResTable_lib_entry* entry = (ResTable_lib_entry*) dest->editDataInRange(entryStart, sizeof(ResTable_lib_entry));
+ ResTable_lib_entry* entry = (ResTable_lib_entry*) dest->editDataInRange(
+ entryStart, sizeof(ResTable_lib_entry));
memset(entry, 0, sizeof(*entry));
entry->packageId = htodl(libPackage->getAssignedId());
strcpy16_htod(entry->packageName, libPackage->getName().string());
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index d4f47ef..3721de4 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -165,7 +165,8 @@
size_t numLocalResources() const;
bool hasResources() const;
- sp<AaptFile> flatten(Bundle* bundle, const sp<const ResourceFilter>& filter);
+ sp<AaptFile> flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
+ const bool isBase);
static inline uint32_t makeResId(uint32_t packageId,
uint32_t typeId,
@@ -206,7 +207,8 @@
void addLocalization(const String16& name, const String8& locale, const SourcePos& src);
status_t validateLocalizations(void);
- status_t flatten(Bundle* bundle, const sp<const ResourceFilter>& filter, const sp<AaptFile>& dest);
+ status_t flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
+ const sp<AaptFile>& dest, const bool isBase);
status_t flattenLibraryTable(const sp<AaptFile>& dest, const Vector<sp<Package> >& libs);
void writePublicDefinitions(const String16& package, FILE* fp);
diff --git a/tools/aapt/tests/ResourceFilter_test.cpp b/tools/aapt/tests/ResourceFilter_test.cpp
index 30697bb..b55379e 100644
--- a/tools/aapt/tests/ResourceFilter_test.cpp
+++ b/tools/aapt/tests/ResourceFilter_test.cpp
@@ -126,3 +126,38 @@
EXPECT_TRUE(filter.match(config));
}
+TEST(StrongResourceFilterTest, MatchesDensities) {
+ ConfigDescription config;
+ config.density = 160;
+ config.version = 4;
+ std::set<ConfigDescription> configs;
+ configs.insert(config);
+
+ StrongResourceFilter filter(configs);
+
+ ConfigDescription expectedConfig;
+ expectedConfig.density = 160;
+ expectedConfig.version = 4;
+ ASSERT_TRUE(filter.match(expectedConfig));
+}
+
+TEST(StrongResourceFilterTest, MatchOnlyMdpiAndExcludeAllOthers) {
+ std::set<ConfigDescription> configsToMatch;
+ ConfigDescription config;
+ config.density = 160;
+ config.version = 4;
+ configsToMatch.insert(config);
+
+ std::set<ConfigDescription> configsToNotMatch;
+ config.density = 480;
+ configsToNotMatch.insert(config);
+
+ AndResourceFilter filter;
+ filter.addFilter(new InverseResourceFilter(new StrongResourceFilter(configsToNotMatch)));
+ filter.addFilter(new StrongResourceFilter(configsToMatch));
+
+ ConfigDescription expectedConfig;
+ expectedConfig.density = 160;
+ expectedConfig.version = 4;
+ ASSERT_TRUE(filter.match(expectedConfig));
+}
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index a561dc2..f2db206 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -18,8 +18,8 @@
import android.net.wifi.passpoint.WifiPasspointInfo;
import android.net.wifi.passpoint.WifiPasspointManager;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
/**
* Describes information about a detected access point. In addition
@@ -48,7 +48,10 @@
*/
public String capabilities;
/**
- * The detected signal level in dBm.
+ * The detected signal level in dBm, also known as the RSSI.
+ *
+ * <p>Use {@link android.net.wifi.WifiManager#calculateSignalLevel} to convert this number into
+ * an absolute signal level which can be displayed to a user.
*/
public int level;
/**
@@ -103,7 +106,24 @@
* Status: indicating join status
* @hide
*/
- public int status;
+ public int autoJoinStatus;
+
+ /**
+ * @hide
+ * Last time we blacklisted the ScanResult
+ */
+ public long blackListTimestamp;
+
+ /** @hide **/
+ public void setAutoJoinStatus(int status) {
+ if (status < 0) status = 0;
+ if (status == 0) {
+ blackListTimestamp = 0;
+ } else if (status > autoJoinStatus) {
+ blackListTimestamp = System.currentTimeMillis();
+ }
+ autoJoinStatus = status;
+ }
/**
* Status: indicating the scan result is not a result
@@ -241,7 +261,7 @@
distanceSdCm = source.distanceSdCm;
seen = source.seen;
passpoint = source.passpoint;
- status = source.status;
+ autoJoinStatus = source.autoJoinStatus;
untrusted = source.untrusted;
numConnection = source.numConnection;
numUsage = source.numUsage;
@@ -279,8 +299,8 @@
append("(cm)");
sb.append(", passpoint: ").append(passpoint != null ? "yes" : "no");
- if (status != 0) {
- sb.append(", status: ").append(status);
+ if (autoJoinStatus != 0) {
+ sb.append(", status: ").append(autoJoinStatus);
}
return sb.toString();
}
@@ -306,7 +326,7 @@
dest.writeInt(distanceCm);
dest.writeInt(distanceSdCm);
dest.writeLong(seen);
- dest.writeInt(status);
+ dest.writeInt(autoJoinStatus);
dest.writeInt(untrusted ? 1 : 0);
dest.writeInt(numConnection);
dest.writeInt(numUsage);
@@ -347,7 +367,7 @@
in.readInt()
);
sr.seen = in.readLong();
- sr.status = in.readInt();
+ sr.autoJoinStatus = in.readInt();
sr.untrusted = in.readInt() != 0;
sr.numConnection = in.readInt();
sr.numUsage = in.readInt();
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index e808136..44a7108 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -323,7 +323,11 @@
/**
* Returns the received signal strength indicator of the current 802.11
* network, in dBm.
- * @return the RSSI, in the range -127 to 200
+ *
+ * <p>Use {@link android.net.wifi.WifiManager#calculateSignalLevel} to convert this number into
+ * an absolute signal level which can be displayed to a user.
+ *
+ * @return the RSSI.
*/
public int getRssi() {
return mRssi;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 3d976e7..e27bd7e 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1696,7 +1696,6 @@
*
* @hide
*/
- @SystemApi
public void connect(WifiConfiguration config, ActionListener listener) {
if (config == null) throw new IllegalArgumentException("config cannot be null");
validateChannel();
@@ -1719,7 +1718,6 @@
* initialized again
* @hide
*/
- @SystemApi
public void connect(int networkId, ActionListener listener) {
if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative");
validateChannel();
@@ -1744,7 +1742,6 @@
* initialized again
* @hide
*/
- @SystemApi
public void save(WifiConfiguration config, ActionListener listener) {
if (config == null) throw new IllegalArgumentException("config cannot be null");
validateChannel();
@@ -1764,7 +1761,6 @@
* initialized again
* @hide
*/
- @SystemApi
public void forget(int netId, ActionListener listener) {
if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
validateChannel();
@@ -1780,7 +1776,6 @@
* initialized again
* @hide
*/
- @SystemApi
public void disable(int netId, ActionListener listener) {
if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
validateChannel();
diff --git a/wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl b/wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl
index 50bec33..54237c4 100644
--- a/wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl
+++ b/wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl
@@ -31,15 +31,5 @@
Messenger getMessenger();
int getPasspointState();
-
- List<WifiPasspointPolicy> requestCredentialMatch(in List<ScanResult> requested);
-
- List<WifiPasspointCredential> getCredentials();
-
- boolean addCredential(in WifiPasspointCredential cred);
-
- boolean updateCredential(in WifiPasspointCredential cred);
-
- boolean removeCredential(in WifiPasspointCredential cred);
}