Merge "Fix invisible security method" 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 7bc30fd..547ec6c 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -222,6 +222,7 @@
$(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 73f10b8..eacc452 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1028,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
@@ -1445,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
@@ -3595,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();
@@ -3630,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 {
@@ -4367,6 +4374,7 @@
method public abstract android.app.FragmentTransaction add(android.app.Fragment, java.lang.String);
method public abstract android.app.FragmentTransaction add(int, android.app.Fragment);
method public abstract android.app.FragmentTransaction add(int, android.app.Fragment, java.lang.String);
+ method public abstract android.app.FragmentTransaction addSharedElement(android.view.View, java.lang.String);
method public abstract android.app.FragmentTransaction addToBackStack(java.lang.String);
method public abstract android.app.FragmentTransaction attach(android.app.Fragment);
method public abstract int commit();
@@ -4386,8 +4394,6 @@
method public abstract android.app.FragmentTransaction setCustomAnimations(int, int);
method public abstract android.app.FragmentTransaction setCustomAnimations(int, int, int, int);
method public abstract android.app.FragmentTransaction setCustomTransition(int, int);
- method public abstract android.app.FragmentTransaction setSharedElement(android.view.View, java.lang.String);
- method public abstract android.app.FragmentTransaction setSharedElements(android.util.Pair<android.view.View, java.lang.String>...);
method public abstract android.app.FragmentTransaction setTransition(int);
method public abstract android.app.FragmentTransaction setTransitionStyle(int);
method public abstract android.app.FragmentTransaction show(android.app.Fragment);
@@ -5500,23 +5506,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
@@ -5636,19 +5642,21 @@
method public long getIntervalMillis();
method public long getMaxExecutionDelayMillis();
method public long getMinLatencyMillis();
- method public int getNetworkCapabilities();
+ method public int getNetworkType();
method public android.content.ComponentName getService();
method public boolean isPeriodic();
method public boolean isPersisted();
method public boolean isRequireCharging();
method public boolean isRequireDeviceIdle();
method public void writeToParcel(android.os.Parcel, int);
+ field public static final int BACKOFF_POLICY_EXPONENTIAL = 1; // 0x1
+ field public static final int BACKOFF_POLICY_LINEAR = 0; // 0x0
field public static final android.os.Parcelable.Creator CREATOR;
- }
-
- public static abstract interface JobInfo.BackoffPolicy {
- field public static final int EXPONENTIAL = 1; // 0x1
- field public static final int LINEAR = 0; // 0x0
+ field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L
+ field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
+ field public static final int NETWORK_TYPE_ANY = 1; // 0x1
+ field public static final int NETWORK_TYPE_NONE = 0; // 0x0
+ field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
}
public static final class JobInfo.Builder {
@@ -5656,21 +5664,15 @@
method public android.app.job.JobInfo build();
method public android.app.job.JobInfo.Builder setBackoffCriteria(long, int);
method public android.app.job.JobInfo.Builder setExtras(android.os.PersistableBundle);
- method public android.app.job.JobInfo.Builder setIsPersisted(boolean);
method public android.app.job.JobInfo.Builder setMinimumLatency(long);
method public android.app.job.JobInfo.Builder setOverrideDeadline(long);
method public android.app.job.JobInfo.Builder setPeriodic(long);
- method public android.app.job.JobInfo.Builder setRequiredNetworkCapabilities(int);
+ method public android.app.job.JobInfo.Builder setPersisted(boolean);
+ method public android.app.job.JobInfo.Builder setRequiredNetworkType(int);
method public android.app.job.JobInfo.Builder setRequiresCharging(boolean);
method public android.app.job.JobInfo.Builder setRequiresDeviceIdle(boolean);
}
- public static abstract interface JobInfo.NetworkType {
- field public static final int ANY = 1; // 0x1
- field public static final int NONE = 0; // 0x0
- field public static final int UNMETERED = 2; // 0x2
- }
-
public class JobParameters implements android.os.Parcelable {
method public int describeContents();
method public android.os.PersistableBundle getExtras();
@@ -6325,7 +6327,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();
@@ -6339,14 +6340,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
@@ -6363,11 +6365,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);
@@ -6620,6 +6622,7 @@
method public java.util.Map<android.os.ParcelUuid, byte[]> getServiceData();
method public java.util.List<android.os.ParcelUuid> getServiceUuids();
method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
}
public static final class AdvertiseData.Builder {
@@ -6634,10 +6637,10 @@
public final class AdvertiseSettings implements android.os.Parcelable {
method public int describeContents();
- method public boolean getIsConnectable();
method public int getMode();
method public int getTimeout();
method public int getTxPowerLevel();
+ method public boolean isConnectable();
method public void writeToParcel(android.os.Parcel, int);
field public static final int ADVERTISE_MODE_BALANCED = 1; // 0x1
field public static final int ADVERTISE_MODE_LOW_LATENCY = 2; // 0x2
@@ -6646,13 +6649,14 @@
field public static final int ADVERTISE_TX_POWER_LOW = 1; // 0x1
field public static final int ADVERTISE_TX_POWER_MEDIUM = 2; // 0x2
field public static final int ADVERTISE_TX_POWER_ULTRA_LOW = 0; // 0x0
+ field public static final android.os.Parcelable.Creator CREATOR;
}
public static final class AdvertiseSettings.Builder {
ctor public AdvertiseSettings.Builder();
method public android.bluetooth.le.AdvertiseSettings build();
method public android.bluetooth.le.AdvertiseSettings.Builder setAdvertiseMode(int);
- method public android.bluetooth.le.AdvertiseSettings.Builder setIsConnectable(boolean);
+ method public android.bluetooth.le.AdvertiseSettings.Builder setConnectable(boolean);
method public android.bluetooth.le.AdvertiseSettings.Builder setTimeout(int);
method public android.bluetooth.le.AdvertiseSettings.Builder setTxPowerLevel(int);
}
@@ -6695,6 +6699,7 @@
method public android.os.ParcelUuid getServiceUuidMask();
method public boolean matches(android.bluetooth.le.ScanResult);
method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
}
public static final class ScanFilter.Builder {
@@ -6730,6 +6735,7 @@
method public android.bluetooth.le.ScanRecord getScanRecord();
method public long getTimestampNanos();
method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
}
public final class ScanSettings implements android.os.Parcelable {
@@ -6740,19 +6746,16 @@
method public int getScanResultType();
method public void writeToParcel(android.os.Parcel, int);
field public static final int CALLBACK_TYPE_ALL_MATCHES = 1; // 0x1
- field public static final int CALLBACK_TYPE_FIRST_MATCH = 2; // 0x2
- field public static final int CALLBACK_TYPE_MATCH_LOST = 4; // 0x4
+ field public static final android.os.Parcelable.Creator CREATOR;
field public static final int SCAN_MODE_BALANCED = 1; // 0x1
field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
- field public static final int SCAN_RESULT_TYPE_FULL = 0; // 0x0
}
public static final class ScanSettings.Builder {
ctor public ScanSettings.Builder();
method public android.bluetooth.le.ScanSettings build();
- method public android.bluetooth.le.ScanSettings.Builder setCallbackType(int);
- method public android.bluetooth.le.ScanSettings.Builder setReportDelayMillis(long);
+ method public android.bluetooth.le.ScanSettings.Builder setReportDelay(long);
method public android.bluetooth.le.ScanSettings.Builder setScanMode(int);
}
@@ -8673,10 +8676,12 @@
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_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME";
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";
+ field public static final java.lang.String EXTRA_STORAGE_PATH = "android.content.pm.extra.STORAGE_PATH";
field public static final int STATUS_FAILURE = 1; // 0x1
field public static final int STATUS_FAILURE_ABORTED = 3; // 0x3
field public static final int STATUS_FAILURE_BLOCKED = 2; // 0x2
@@ -12682,7 +12687,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;
@@ -12796,9 +12801,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
@@ -12974,7 +12979,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();
@@ -12989,7 +12994,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;
@@ -13061,7 +13066,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;
@@ -13567,7 +13572,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);
@@ -17208,12 +17213,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;
}
@@ -18712,7 +18717,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...);
@@ -18748,10 +18752,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);
}
@@ -22463,21 +22463,21 @@
}
public final class PowerManager {
- method public void goToSleep(long);
method public boolean isInteractive();
method public boolean isPowerSaveMode();
method public deprecated boolean isScreenOn();
+ method public boolean isWakeLockLevelSupported(int);
method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String);
method public void reboot(java.lang.String);
- method public void userActivity(long, boolean);
- method public void wakeUp(long);
field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
field public static final java.lang.String ACTION_POWER_SAVE_MODE_CHANGED = "android.os.action.POWER_SAVE_MODE_CHANGED";
field public static final deprecated int FULL_WAKE_LOCK = 26; // 0x1a
field public static final int ON_AFTER_RELEASE = 536870912; // 0x20000000
field public static final int PARTIAL_WAKE_LOCK = 1; // 0x1
+ field public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32; // 0x20
field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa
field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
+ field public static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1; // 0x1
}
public final class PowerManager.WakeLock {
@@ -22485,6 +22485,7 @@
method public void acquire(long);
method public boolean isHeld();
method public void release();
+ method public void release(int);
method public void setReferenceCounted(boolean);
method public void setWorkSource(android.os.WorkSource);
}
@@ -27461,7 +27462,7 @@
public class VoiceInteractionService extends android.app.Service {
ctor public VoiceInteractionService();
- method public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(java.lang.String, java.lang.String, android.service.voice.AlwaysOnHotwordDetector.Callback);
+ method public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(java.lang.String, java.util.Locale, android.service.voice.AlwaysOnHotwordDetector.Callback);
method public static boolean isActiveService(android.content.Context, android.content.ComponentName);
method public android.os.IBinder onBind(android.content.Intent);
method public void onReady();
@@ -28554,8 +28555,6 @@
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);
@@ -28587,8 +28586,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
@@ -28600,35 +28597,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();
@@ -28636,7 +28604,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;
}
@@ -28748,7 +28715,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);
@@ -28776,7 +28742,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 {
@@ -28815,35 +28780,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
}
}
@@ -31803,7 +31739,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);
}
@@ -31826,6 +31762,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 {
@@ -33381,6 +33321,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
@@ -35138,6 +35079,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();
@@ -35199,6 +35141,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);
@@ -36179,7 +36122,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);
@@ -36245,25 +36188,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();
@@ -36361,13 +36285,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 {
@@ -36389,7 +36315,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);
@@ -36455,7 +36381,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[]);
@@ -36473,7 +36399,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);
@@ -39762,6 +39688,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/api/removed.txt b/api/removed.txt
index 465a18d..93484de 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -6,6 +6,16 @@
}
+package android.os {
+
+ public final class PowerManager {
+ method public void goToSleep(long);
+ method public deprecated void userActivity(long, boolean);
+ method public void wakeUp(long);
+ }
+
+}
+
package android.view {
public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable {
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 46d8ade..d9b40b1 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -1004,6 +1004,10 @@
params.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
} else if (opt.equals("-p")) {
params.mode = SessionParams.MODE_INHERIT_EXISTING;
+ params.appPackageName = nextOptionData();
+ if (params.appPackageName == null) {
+ throw new IllegalArgumentException("Missing inherit package name");
+ }
} else if (opt.equals("-S")) {
params.setSize(Long.parseLong(nextOptionData()));
} else if (opt.equals("--abi")) {
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/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/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 4433a3a..67863a5 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -580,6 +580,23 @@
}
@Override
+ public FragmentTransaction addSharedElement(View sharedElement, String name) {
+ String transitionName = sharedElement.getTransitionName();
+ if (transitionName == null) {
+ throw new IllegalArgumentException("Unique transitionNames are required for all" +
+ " sharedElements");
+ }
+ if (mSharedElementSourceNames == null) {
+ mSharedElementSourceNames = new ArrayList<String>();
+ mSharedElementTargetNames = new ArrayList<String>();
+ }
+ mSharedElementSourceNames.add(transitionName);
+ mSharedElementTargetNames.add(name);
+ return this;
+ }
+
+ /** TODO: remove this */
+ @Override
public FragmentTransaction setSharedElement(View sharedElement, String name) {
String transitionName = sharedElement.getTransitionName();
if (transitionName == null) {
@@ -594,6 +611,7 @@
return this;
}
+ /** TODO: remove this */
@Override
public FragmentTransaction setSharedElements(Pair<View, String>... sharedElements) {
if (sharedElements == null || sharedElements.length == 0) {
diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java
index 0adc835..1077bac 100644
--- a/core/java/android/app/FragmentTransaction.java
+++ b/core/java/android/app/FragmentTransaction.java
@@ -190,14 +190,17 @@
* @param name The transitionName for a View in an appearing Fragment to match to the shared
* element.
*/
+ public abstract FragmentTransaction addSharedElement(View sharedElement, String name);
+
+ /**
+ * TODO: remove from API
+ * @hide
+ */
public abstract FragmentTransaction setSharedElement(View sharedElement, String name);
/**
- * Used with {@link #setCustomTransition(int, int)} to map multiple Views from removed or hidden
- * Fragments to a Views from a shown or added Fragments. Views in
- * <var>sharedElements</var> must have unique transitionNames in the View hierarchy.
- * @param sharedElements Pairs of Views in disappearing Fragments to transitionNames in
- * appearing Fragments.
+ * TODO: remove from API
+ * @hide
*/
public abstract FragmentTransaction setSharedElements(Pair<View, String>... sharedElements);
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/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index e8f6818..2b97c6b 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -62,6 +62,8 @@
void requestHintsFromListener(in INotificationListener token, int hints);
int getHintsFromListener(in INotificationListener token);
+ ComponentName getEffectsSuppressor();
+
ZenModeConfig getZenModeConfig();
boolean setZenModeConfig(in ZenModeConfig config);
oneway void notifyConditions(String pkg, in IConditionProvider provider, in Condition[] conditions);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 47967ba..f7300aa 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2579,20 +2579,35 @@
return bitmap;
}
+ private boolean addProfileBadge(RemoteViews contentView, int resId) {
+ Bitmap profileBadge = 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) {
- Bitmap profileIcon = getProfileBadge();
RemoteViews contentView = new BuilderRemoteViews(mContext.getPackageName(),
mOriginatingUserId, resId);
boolean showLine3 = false;
boolean showLine2 = false;
+ boolean contentTextInLine2 = false;
- 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);
@@ -2639,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);
}
@@ -2681,6 +2697,15 @@
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;
@@ -3347,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);
}
@@ -3507,6 +3534,9 @@
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;
}
@@ -3632,6 +3662,8 @@
applyTopPadding(contentView);
+ mBuilder.addProfileBadge(contentView, R.id.profile_badge_large_template);
+
return contentView;
}
@@ -3769,6 +3801,8 @@
applyTopPadding(contentView);
+ mBuilder.addProfileBadge(contentView, R.id.profile_badge_large_template);
+
return contentView;
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index bd9363d..fc047de 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -16,7 +16,9 @@
package android.app;
+import android.annotation.SdkConstant;
import android.app.Notification.Builder;
+import android.content.ComponentName;
import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
@@ -72,6 +74,16 @@
private static String TAG = "NotificationManager";
private static boolean localLOGV = false;
+ /**
+ * Intent that is broadcast when the state of {@link #getEffectsSuppressor()} changes.
+ * This broadcast is only sent to registered receivers.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_EFFECTS_SUPPRESSOR_CHANGED
+ = "android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED";
+
private static INotificationManager sService;
/** @hide */
@@ -227,5 +239,17 @@
}
}
+ /**
+ * @hide
+ */
+ public ComponentName getEffectsSuppressor() {
+ INotificationManager service = getService();
+ try {
+ return service.getEffectsSuppressor();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
private Context mContext;
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 8545e99..41bbb87 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -126,7 +126,7 @@
* 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
@@ -135,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
@@ -149,7 +149,7 @@
* 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
@@ -159,17 +159,17 @@
* 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 #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.
@@ -179,7 +179,7 @@
* 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
@@ -189,7 +189,7 @@
* 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}
@@ -199,7 +199,7 @@
* 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
@@ -209,7 +209,7 @@
* 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
@@ -219,7 +219,7 @@
* 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
@@ -229,7 +229,7 @@
* 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
@@ -239,7 +239,7 @@
* 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
@@ -249,7 +249,7 @@
* 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
@@ -259,7 +259,7 @@
* 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
@@ -269,7 +269,7 @@
* 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
@@ -279,7 +279,7 @@
* 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
@@ -291,7 +291,7 @@
* 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.
@@ -1373,6 +1373,8 @@
* and its profiles or a particular one.
* @param admin The name of the admin component to check, or null to aggregate
* all admins.
+ * @return time in milliseconds for the given admin or the minimum value (strictest) of
+ * all admins if admin is null.
*/
public long getMaximumTimeToLock(ComponentName admin) {
return getMaximumTimeToLock(admin, UserHandle.myUserId());
@@ -2160,6 +2162,7 @@
}
/** @hide */
+ @SystemApi
public String getDeviceOwner() {
if (mService != null) {
try {
@@ -2368,6 +2371,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());
}
diff --git a/core/java/android/app/job/IJobService.aidl b/core/java/android/app/job/IJobService.aidl
index 63f8b81..7f55d29 100644
--- a/core/java/android/app/job/IJobService.aidl
+++ b/core/java/android/app/job/IJobService.aidl
@@ -27,6 +27,6 @@
oneway interface IJobService {
/** Begin execution of application's job. */
void startJob(in JobParameters jobParams);
- /** Stop execution of application's task. */
+ /** Stop execution of application's job. */
void stopJob(in JobParameters jobParams);
}
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 936e205..0d9e778 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -17,7 +17,6 @@
package android.app.job;
import android.content.ComponentName;
-import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
@@ -26,42 +25,50 @@
* Container of data passed to the {@link android.app.job.JobScheduler} fully encapsulating the
* parameters required to schedule work against the calling application. These are constructed
* using the {@link JobInfo.Builder}.
+ * You must specify at least one sort of constraint on the JobInfo object that you are creating.
+ * The goal here is to provide the scheduler with high-level semantics about the work you want to
+ * accomplish. Doing otherwise with throw an exception in your app.
*/
public class JobInfo implements Parcelable {
- public interface NetworkType {
- /** Default. */
- public final int NONE = 0;
- /** This job requires network connectivity. */
- public final int ANY = 1;
- /** This job requires network connectivity that is unmetered. */
- public final int UNMETERED = 2;
- }
+ /** Default. */
+ public static final int NETWORK_TYPE_NONE = 0;
+ /** This job requires network connectivity. */
+ public static final int NETWORK_TYPE_ANY = 1;
+ /** This job requires network connectivity that is unmetered. */
+ public static final int NETWORK_TYPE_UNMETERED = 2;
/**
* Amount of backoff a job has initially by default, in milliseconds.
- * @hide.
*/
- public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 5000L;
+ public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 30 seconds.
+
+ /**
+ * Maximum backoff we allow for a job, in milliseconds.
+ */
+ public static final long MAX_BACKOFF_DELAY_MILLIS = 5 * 60 * 60 * 1000; // 5 hours.
+
+ /**
+ * Linearly back-off a failed job. See
+ * {@link android.app.job.JobInfo.Builder#setBackoffCriteria(long, int)}
+ * retry_time(current_time, num_failures) =
+ * current_time + initial_backoff_millis * num_failures, num_failures >= 1
+ */
+ public static final int BACKOFF_POLICY_LINEAR = 0;
+
+ /**
+ * Exponentially back-off a failed job. See
+ * {@link android.app.job.JobInfo.Builder#setBackoffCriteria(long, int)}
+ *
+ * retry_time(current_time, num_failures) =
+ * current_time + initial_backoff_millis * 2 ^ (num_failures - 1), num_failures >= 1
+ */
+ public static final int BACKOFF_POLICY_EXPONENTIAL = 1;
/**
* Default type of backoff.
* @hide
*/
- public static final int DEFAULT_BACKOFF_POLICY = BackoffPolicy.EXPONENTIAL;
- /**
- * Maximum backoff we allow for a job, in milliseconds.
- * @hide
- */
- public static final long MAX_BACKOFF_DELAY_MILLIS = 24 * 60 * 60 * 1000; // 24 hours.
-
- /**
- * Linear: retry_time(failure_time, t) = failure_time + initial_retry_delay * t, t >= 1
- * Expon: retry_time(failure_time, t) = failure_time + initial_retry_delay ^ t, t >= 1
- */
- public interface BackoffPolicy {
- public final int LINEAR = 0;
- public final int EXPONENTIAL = 1;
- }
+ public static final int DEFAULT_BACKOFF_POLICY = BACKOFF_POLICY_EXPONENTIAL;
private final int jobId;
private final PersistableBundle extras;
@@ -70,7 +77,7 @@
private final boolean requireDeviceIdle;
private final boolean hasEarlyConstraint;
private final boolean hasLateConstraint;
- private final int networkCapabilities;
+ private final int networkType;
private final long minLatencyMillis;
private final long maxExecutionDelayMillis;
private final boolean isPeriodic;
@@ -115,10 +122,12 @@
}
/**
- * See {@link android.app.job.JobInfo.NetworkType} for a description of this value.
+ * One of {@link android.app.job.JobInfo#NETWORK_TYPE_ANY},
+ * {@link android.app.job.JobInfo#NETWORK_TYPE_NONE}, or
+ * {@link android.app.job.JobInfo#NETWORK_TYPE_UNMETERED}.
*/
- public int getNetworkCapabilities() {
- return networkCapabilities;
+ public int getNetworkType() {
+ return networkType;
}
/**
@@ -169,8 +178,9 @@
}
/**
- * See {@link android.app.job.JobInfo.BackoffPolicy} for an explanation of the values this field
- * can take. This defaults to exponential.
+ * One of either {@link android.app.job.JobInfo#BACKOFF_POLICY_EXPONENTIAL}, or
+ * {@link android.app.job.JobInfo#BACKOFF_POLICY_LINEAR}, depending on which criteria you set
+ * when creating this job.
*/
public int getBackoffPolicy() {
return backoffPolicy;
@@ -200,7 +210,7 @@
service = in.readParcelable(null);
requireCharging = in.readInt() == 1;
requireDeviceIdle = in.readInt() == 1;
- networkCapabilities = in.readInt();
+ networkType = in.readInt();
minLatencyMillis = in.readLong();
maxExecutionDelayMillis = in.readLong();
isPeriodic = in.readInt() == 1;
@@ -218,7 +228,7 @@
service = b.mJobService;
requireCharging = b.mRequiresCharging;
requireDeviceIdle = b.mRequiresDeviceIdle;
- networkCapabilities = b.mNetworkCapabilities;
+ networkType = b.mNetworkType;
minLatencyMillis = b.mMinLatencyMillis;
maxExecutionDelayMillis = b.mMaxExecutionDelayMillis;
isPeriodic = b.mIsPeriodic;
@@ -242,7 +252,7 @@
out.writeParcelable(service, flags);
out.writeInt(requireCharging ? 1 : 0);
out.writeInt(requireDeviceIdle ? 1 : 0);
- out.writeInt(networkCapabilities);
+ out.writeInt(networkType);
out.writeLong(minLatencyMillis);
out.writeLong(maxExecutionDelayMillis);
out.writeInt(isPeriodic ? 1 : 0);
@@ -279,7 +289,7 @@
// Requirements.
private boolean mRequiresCharging;
private boolean mRequiresDeviceIdle;
- private int mNetworkCapabilities;
+ private int mNetworkType;
private boolean mIsPersisted;
// One-off parameters.
private long mMinLatencyMillis;
@@ -317,15 +327,15 @@
}
/**
- * Set some description of the kind of network capabilities you would like to have. This
- * will be a parameter defined in {@link android.app.job.JobInfo.NetworkType}.
- * Not calling this function means the network is not necessary.
+ * Set some description of the kind of network type your job needs to have.
+ * Not calling this function means the network is not necessary, as the default is
+ * {@link #NETWORK_TYPE_NONE}.
* Bear in mind that calling this function defines network as a strict requirement for your
- * job if the network requested is not available your job will never run. See
+ * job. If the network requested is not available your job will never run. See
* {@link #setOverrideDeadline(long)} to change this behaviour.
*/
- public Builder setRequiredNetworkCapabilities(int networkCapabilities) {
- mNetworkCapabilities = networkCapabilities;
+ public Builder setRequiredNetworkType(int networkType) {
+ mNetworkType = networkType;
return this;
}
@@ -398,8 +408,8 @@
/**
* Set up the back-off/retry policy.
- * This defaults to some respectable values: {5 seconds, Exponential}. We cap back-off at
- * 1hr.
+ * This defaults to some respectable values: {30 seconds, Exponential}. We cap back-off at
+ * 5hrs.
* Note that trying to set a backoff criteria for a job with
* {@link #setRequiresDeviceIdle(boolean)} will throw an exception when you call build().
* This is because back-off typically does not make sense for these types of jobs. See
@@ -408,7 +418,8 @@
* mode.
* @param initialBackoffMillis Millisecond time interval to wait initially when job has
* failed.
- * @param backoffPolicy is one of {@link BackoffPolicy}
+ * @param backoffPolicy is one of {@link #BACKOFF_POLICY_LINEAR} or
+ * {@link #BACKOFF_POLICY_EXPONENTIAL}
*/
public Builder setBackoffCriteria(long initialBackoffMillis, int backoffPolicy) {
mBackoffPolicySet = true;
@@ -425,7 +436,7 @@
* @param isPersisted True to indicate that the job will be written to disk and loaded at
* boot.
*/
- public Builder setIsPersisted(boolean isPersisted) {
+ public Builder setPersisted(boolean isPersisted) {
mIsPersisted = isPersisted;
return this;
}
@@ -434,6 +445,12 @@
* @return The job object to hand to the JobScheduler. This object is immutable.
*/
public JobInfo build() {
+ // Allow jobs with no constraints - What am I, a database?
+ if (!mHasEarlyConstraint && !mHasLateConstraint && !mRequiresCharging &&
+ !mRequiresDeviceIdle && mNetworkType == NETWORK_TYPE_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/app/job/JobService.java b/core/java/android/app/job/JobService.java
index eea0268..940a530 100644
--- a/core/java/android/app/job/JobService.java
+++ b/core/java/android/app/job/JobService.java
@@ -17,9 +17,6 @@
package android.app.job;
import android.app.Service;
-import android.app.job.IJobCallback;
-import android.app.job.IJobService;
-import android.app.job.IJobService.Stub;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
@@ -218,7 +215,7 @@
*
* <p>This will happen if the requirements specified at schedule time are no longer met. For
* example you may have requested WiFi with
- * {@link android.app.job.JobInfo.Builder#setRequiredNetworkCapabilities(int)}, yet while your
+ * {@link android.app.job.JobInfo.Builder#setRequiredNetworkType(int)}, yet while your
* job was executing the user toggled WiFi. Another example is if you had specified
* {@link android.app.job.JobInfo.Builder#setRequiresDeviceIdle(boolean)}, and the phone left its
* idle maintenance window. You are solely responsible for the behaviour of your application
@@ -248,8 +245,8 @@
*
* @param params Parameters specifying system-provided info about this job, this was given to
* your application in {@link #onStartJob(JobParameters)}.
- * @param needsReschedule True if this job is complete, false if you want the JobManager to
- * reschedule you.
+ * @param needsReschedule True if this job should be rescheduled according to the back-off
+ * criteria specified at schedule-time. False otherwise.
*/
public final void jobFinished(JobParameters params, boolean needsReschedule) {
ensureHandler();
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/AdvertiseData.java b/core/java/android/bluetooth/le/AdvertiseData.java
index 843cd84..c7bfae9 100644
--- a/core/java/android/bluetooth/le/AdvertiseData.java
+++ b/core/java/android/bluetooth/le/AdvertiseData.java
@@ -172,9 +172,6 @@
dest.writeByte((byte) (getIncludeDeviceName() ? 1 : 0));
}
- /**
- * @hide
- */
public static final Parcelable.Creator<AdvertiseData> CREATOR =
new Creator<AdvertiseData>() {
@Override
diff --git a/core/java/android/bluetooth/le/AdvertiseSettings.java b/core/java/android/bluetooth/le/AdvertiseSettings.java
index 71d7b5b..62c68a4 100644
--- a/core/java/android/bluetooth/le/AdvertiseSettings.java
+++ b/core/java/android/bluetooth/le/AdvertiseSettings.java
@@ -66,13 +66,13 @@
public static final int ADVERTISE_TX_POWER_HIGH = 3;
/**
- * The maximimum limited advertisement duration as specified by the Bluetooth SIG
+ * The maximum limited advertisement duration as specified by the Bluetooth SIG
*/
- private static final int LIMITED_ADVERTISING_MAX_DURATION = 180;
+ private static final int LIMITED_ADVERTISING_MAX_MILLIS = 180 * 1000;
private final int mAdvertiseMode;
private final int mAdvertiseTxPowerLevel;
- private final int mAdvertiseTimeoutSeconds;
+ private final int mAdvertiseTimeoutMillis;
private final boolean mAdvertiseConnectable;
private AdvertiseSettings(int advertiseMode, int advertiseTxPowerLevel,
@@ -80,14 +80,14 @@
mAdvertiseMode = advertiseMode;
mAdvertiseTxPowerLevel = advertiseTxPowerLevel;
mAdvertiseConnectable = advertiseConnectable;
- mAdvertiseTimeoutSeconds = advertiseTimeout;
+ mAdvertiseTimeoutMillis = advertiseTimeout;
}
private AdvertiseSettings(Parcel in) {
mAdvertiseMode = in.readInt();
mAdvertiseTxPowerLevel = in.readInt();
mAdvertiseConnectable = in.readInt() != 0 ? true : false;
- mAdvertiseTimeoutSeconds = in.readInt();
+ mAdvertiseTimeoutMillis = in.readInt();
}
/**
@@ -107,15 +107,15 @@
/**
* Returns whether the advertisement will indicate connectable.
*/
- public boolean getIsConnectable() {
+ public boolean isConnectable() {
return mAdvertiseConnectable;
}
/**
- * Returns the advertising time limit in seconds.
+ * Returns the advertising time limit in milliseconds.
*/
public int getTimeout() {
- return mAdvertiseTimeoutSeconds;
+ return mAdvertiseTimeoutMillis;
}
@Override
@@ -123,7 +123,7 @@
return "Settings [mAdvertiseMode=" + mAdvertiseMode
+ ", mAdvertiseTxPowerLevel=" + mAdvertiseTxPowerLevel
+ ", mAdvertiseConnectable=" + mAdvertiseConnectable
- + ", mAdvertiseTimeoutSeconds=" + mAdvertiseTimeoutSeconds + "]";
+ + ", mAdvertiseTimeoutMillis=" + mAdvertiseTimeoutMillis + "]";
}
@Override
@@ -136,12 +136,9 @@
dest.writeInt(mAdvertiseMode);
dest.writeInt(mAdvertiseTxPowerLevel);
dest.writeInt(mAdvertiseConnectable ? 1 : 0);
- dest.writeInt(mAdvertiseTimeoutSeconds);
+ dest.writeInt(mAdvertiseTimeoutMillis);
}
- /**
- * @hide
- */
public static final Parcelable.Creator<AdvertiseSettings> CREATOR =
new Creator<AdvertiseSettings>() {
@Override
@@ -161,7 +158,7 @@
public static final class Builder {
private int mMode = ADVERTISE_MODE_LOW_POWER;
private int mTxPowerLevel = ADVERTISE_TX_POWER_MEDIUM;
- private int mTimeoutSeconds = 0;
+ private int mTimeoutMillis = 0;
private boolean mConnectable = true;
/**
@@ -204,26 +201,26 @@
/**
* Set whether the advertisement type should be connectable or non-connectable.
*
- * @param isConnectable Controls whether the advertisment type will be connectable (true)
+ * @param connectable Controls whether the advertisment type will be connectable (true)
* or non-connectable (false).
*/
- public Builder setIsConnectable(boolean isConnectable) {
- mConnectable = isConnectable;
+ public Builder setConnectable(boolean connectable) {
+ mConnectable = connectable;
return this;
}
/**
* Limit advertising to a given amount of time.
- * @param timeoutSeconds Advertising time limit. May not exceed 180 seconds.
+ * @param timeoutMillis Advertising time limit. May not exceed 180000 milliseconds.
* A value of 0 will disable the time limit.
- * @throws IllegalArgumentException If the provided timeout is over 180s.
+ * @throws IllegalArgumentException If the provided timeout is over 180000 ms.
*/
- public Builder setTimeout(int timeoutSeconds) {
- if (timeoutSeconds < 0 || timeoutSeconds > LIMITED_ADVERTISING_MAX_DURATION) {
- throw new IllegalArgumentException("timeoutSeconds invalid (must be 0-"
- + LIMITED_ADVERTISING_MAX_DURATION + " seconds)");
+ public Builder setTimeout(int timeoutMillis) {
+ if (timeoutMillis < 0 || timeoutMillis > LIMITED_ADVERTISING_MAX_MILLIS) {
+ throw new IllegalArgumentException("timeoutMillis invalid (must be 0-"
+ + LIMITED_ADVERTISING_MAX_MILLIS + " milliseconds)");
}
- mTimeoutSeconds = timeoutSeconds;
+ mTimeoutMillis = timeoutMillis;
return this;
}
@@ -231,7 +228,7 @@
* Build the {@link AdvertiseSettings} object.
*/
public AdvertiseSettings build() {
- return new AdvertiseSettings(mMode, mTxPowerLevel, mConnectable, mTimeoutSeconds);
+ return new AdvertiseSettings(mMode, mTxPowerLevel, mConnectable, mTimeoutMillis);
}
}
}
diff --git a/core/java/android/bluetooth/le/ScanCallback.java b/core/java/android/bluetooth/le/ScanCallback.java
index 5b37384..05782a8 100644
--- a/core/java/android/bluetooth/le/ScanCallback.java
+++ b/core/java/android/bluetooth/le/ScanCallback.java
@@ -47,8 +47,8 @@
/**
* Callback when a BLE advertisement has been found.
*
- * @param callbackType Determines if this callback was triggered because of first match, a lost
- * match indication or a regular scan result.
+ * @param callbackType Determines how this callback was triggered. Currently could only be
+ * {@link ScanSettings#CALLBACK_TYPE_ALL_MATCHES}.
* @param result A Bluetooth LE scan result.
*/
public void onScanResult(int callbackType, ScanResult result) {
@@ -64,6 +64,7 @@
/**
* Callback when scan could not be started.
+ *
* @param errorCode Error code (one of SCAN_FAILED_*) for scan failure.
*/
public void onScanFailed(int errorCode) {
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index d1b93d2..5025218 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -138,8 +138,6 @@
/**
* A {@link android.os.Parcelable.Creator} to create {@link ScanFilter} from parcel.
- *
- * @hide
*/
public static final Creator<ScanFilter>
CREATOR = new Creator<ScanFilter>() {
diff --git a/core/java/android/bluetooth/le/ScanResult.java b/core/java/android/bluetooth/le/ScanResult.java
index a0bdaff..2fdfe7f 100644
--- a/core/java/android/bluetooth/le/ScanResult.java
+++ b/core/java/android/bluetooth/le/ScanResult.java
@@ -149,9 +149,6 @@
+ mTimestampNanos + '}';
}
- /**
- * @hide
- */
public static final Parcelable.Creator<ScanResult> CREATOR = new Creator<ScanResult>() {
@Override
public ScanResult createFromParcel(Parcel source) {
diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java
index b2ee6a8..7eae439 100644
--- a/core/java/android/bluetooth/le/ScanSettings.java
+++ b/core/java/android/bluetooth/le/ScanSettings.java
@@ -52,19 +52,28 @@
/**
* A result callback is only triggered for the first advertisement packet received that matches
* the filter criteria.
+ *
+ * @hide
*/
+ @SystemApi
public static final int CALLBACK_TYPE_FIRST_MATCH = 2;
/**
* Receive a callback when advertisements are no longer received from a device that has been
* previously reported by a first match callback.
+ *
+ * @hide
*/
+ @SystemApi
public static final int CALLBACK_TYPE_MATCH_LOST = 4;
/**
* Request full scan results which contain the device, rssi, advertising data, scan response as
* well as the scan timestamp.
+ *
+ * @hide
*/
+ @SystemApi
public static final int SCAN_RESULT_TYPE_FULL = 0;
/**
@@ -137,9 +146,6 @@
return 0;
}
- /**
- * @hide
- */
public static final Parcelable.Creator<ScanSettings>
CREATOR = new Creator<ScanSettings>() {
@Override
@@ -183,7 +189,9 @@
*
* @param callbackType The callback type flags for the scan.
* @throws IllegalArgumentException If the {@code callbackType} is invalid.
+ * @hide
*/
+ @SystemApi
public Builder setCallbackType(int callbackType) {
if (!isValidCallbackType(callbackType)) {
@@ -226,14 +234,14 @@
/**
* Set report delay timestamp for Bluetooth LE scan.
*
- * @param reportDelayMillis Set to 0 to be notified of results immediately. Values > 0
- * causes the scan results to be queued up and delivered after the requested
- * delay or when the internal buffers fill up.
+ * @param reportDelayMillis Delay of report in milliseconds. Set to 0 to be notified of
+ * results immediately. Values > 0 causes the scan results to be queued up and
+ * delivered after the requested delay or when the internal buffers fill up.
* @throws IllegalArgumentException If {@code reportDelayMillis} < 0.
*/
- public Builder setReportDelayMillis(long reportDelayMillis) {
+ public Builder setReportDelay(long reportDelayMillis) {
if (reportDelayMillis < 0) {
- throw new IllegalArgumentException("reportDelayMillis must be > 0");
+ throw new IllegalArgumentException("reportDelay must be > 0");
}
mReportDelayMillis = reportDelayMillis;
return this;
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 7419ebc..9afdbf7 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -45,6 +45,7 @@
import java.io.OutputStream;
import java.security.MessageDigest;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@@ -86,6 +87,8 @@
* <p>
* In some cases, a matching Activity may not exist, so ensure you safeguard
* against this.
+ * <p>
+ * The session to show details for is defined in {@link #EXTRA_SESSION_ID}.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
@@ -95,22 +98,58 @@
ACTION_CONFIRM_PERMISSIONS = "android.content.pm.action.CONFIRM_PERMISSIONS";
/**
- * An integer session ID.
+ * An integer session ID that an operation is working with.
*
- * @see #ACTION_SESSION_DETAILS
+ * @see Intent#getIntExtra(String, int)
*/
public static final String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID";
- public static final String EXTRA_STATUS = "android.content.pm.extra.STATUS";
- public static final String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE";
-
/**
- * Package name relevant to a status.
+ * Package name that an operation is working with.
*
* @see Intent#getStringExtra(String)
*/
public static final String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
+ /**
+ * Current status of an operation. Will be one of
+ * {@link #STATUS_PENDING_USER_ACTION}, {@link #STATUS_SUCCESS},
+ * {@link #STATUS_FAILURE}, {@link #STATUS_FAILURE_ABORTED},
+ * {@link #STATUS_FAILURE_BLOCKED}, {@link #STATUS_FAILURE_CONFLICT},
+ * {@link #STATUS_FAILURE_INCOMPATIBLE}, {@link #STATUS_FAILURE_INVALID}, or
+ * {@link #STATUS_FAILURE_STORAGE}.
+ * <p>
+ * More information about a status may be available through additional
+ * extras; see the individual status documentation for details.
+ *
+ * @see Intent#getIntExtra(String, int)
+ */
+ public static final String EXTRA_STATUS = "android.content.pm.extra.STATUS";
+
+ /**
+ * Detailed string representation of the status, including raw details that
+ * are useful for debugging.
+ *
+ * @see Intent#getStringExtra(String)
+ */
+ public static final String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE";
+
+ /**
+ * Another package name relevant to a status. This is typically the package
+ * responsible for causing an operation failure.
+ *
+ * @see Intent#getStringExtra(String)
+ */
+ public static final String
+ EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME";
+
+ /**
+ * Storage path relevant to a status.
+ *
+ * @see Intent#getStringExtra(String)
+ */
+ public static final String EXTRA_STORAGE_PATH = "android.content.pm.extra.STORAGE_PATH";
+
/** {@hide} */
@Deprecated
public static final String EXTRA_PACKAGE_NAMES = "android.content.pm.extra.PACKAGE_NAMES";
@@ -153,8 +192,12 @@
* The operation failed because it was blocked. For example, a device policy
* may be blocking the operation, a package verifier may have blocked the
* operation, or the app may be required for core system operation.
+ * <p>
+ * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the
+ * specific package blocking the install.
*
* @see #EXTRA_STATUS_MESSAGE
+ * @see #EXTRA_OTHER_PACKAGE_NAME
*/
public static final int STATUS_FAILURE_BLOCKED = 2;
@@ -182,10 +225,11 @@
* 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_NAME} with the
+ * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the
* specific package identified as the cause of the conflict.
*
* @see #EXTRA_STATUS_MESSAGE
+ * @see #EXTRA_OTHER_PACKAGE_NAME
*/
public static final int STATUS_FAILURE_CONFLICT = 5;
@@ -193,8 +237,12 @@
* The operation failed because of storage issues. For example, the device
* may be running low on space, or external media may be unavailable. The
* user may be able to help free space or insert different external media.
+ * <p>
+ * The result may also contain {@link #EXTRA_STORAGE_PATH} with the path to
+ * the storage device that caused the failure.
*
* @see #EXTRA_STATUS_MESSAGE
+ * @see #EXTRA_STORAGE_PATH
*/
public static final int STATUS_FAILURE_STORAGE = 6;
@@ -281,6 +329,13 @@
* To succeed, the caller must be the current home app.
*/
public @NonNull List<SessionInfo> getAllSessions() {
+ final ApplicationInfo info = mContext.getApplicationInfo();
+ if ("com.google.android.googlequicksearchbox".equals(info.packageName)
+ && info.versionCode <= 300400070) {
+ Log.d(TAG, "Ignoring callback request from old prebuilt");
+ return Collections.EMPTY_LIST;
+ }
+
try {
return mInstaller.getAllSessions(mUserId);
} catch (RemoteException e) {
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index eb8b762..142206a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -264,7 +264,7 @@
public final boolean coreApp;
public final boolean multiArch;
- private PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
+ public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
String[] splitCodePaths) {
this.packageName = baseApk.packageName;
this.versionCode = baseApk.versionCode;
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/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/hardware/soundtrigger/KeyphraseEnrollmentInfo.java b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
index 0dbde6b..518a874 100644
--- a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
+++ b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
@@ -25,6 +25,8 @@
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.service.voice.AlwaysOnHotwordDetector;
+import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Slog;
import android.util.Xml;
@@ -35,6 +37,7 @@
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
+import java.util.Locale;
/**
* Enrollment information about the different available keyphrases.
@@ -74,6 +77,7 @@
"com.android.intent.extra.VOICE_KEYPHRASE_HINT_TEXT";
/**
* Intent extra: The voice locale to use while managing the keyphrase.
+ * This is a BCP-47 language tag.
*/
public static final String EXTRA_VOICE_KEYPHRASE_LOCALE =
"com.android.intent.extra.VOICE_KEYPHRASE_LOCALE";
@@ -151,33 +155,8 @@
TypedArray array = res.obtainAttributes(attrs,
com.android.internal.R.styleable.VoiceEnrollmentApplication);
- int searchKeyphraseId = array.getInt(
- com.android.internal.R.styleable.VoiceEnrollmentApplication_searchKeyphraseId,
- -1);
- if (searchKeyphraseId != -1) {
- String searchKeyphrase = array.getString(com.android.internal.R.styleable
- .VoiceEnrollmentApplication_searchKeyphrase);
- if (searchKeyphrase == null) {
- searchKeyphrase = "";
- }
- String searchKeyphraseSupportedLocales =
- array.getString(com.android.internal.R.styleable
- .VoiceEnrollmentApplication_searchKeyphraseSupportedLocales);
- String[] supportedLocales = new String[0];
- // Get all the supported locales from the comma-delimted string.
- if (searchKeyphraseSupportedLocales != null
- && !searchKeyphraseSupportedLocales.isEmpty()) {
- supportedLocales = searchKeyphraseSupportedLocales.split(",");
- }
- int recognitionModes = array.getInt(com.android.internal.R.styleable
- .VoiceEnrollmentApplication_searchKeyphraseRecognitionFlags, 0);
- mKeyphrases = new KeyphraseMetadata[1];
- mKeyphrases[0] = new KeyphraseMetadata(
- searchKeyphraseId, searchKeyphrase, supportedLocales, recognitionModes);
- } else {
- mParseError = "searchKeyphraseId not specified in meta-data";
- return;
- }
+ initializeKeyphrasesFromTypedArray(array);
+ array.recycle();
} catch (XmlPullParserException e) {
mParseError = "Error parsing keyphrase enrollment meta-data: " + e;
Slog.w(TAG, "error parsing keyphrase enrollment meta-data", e);
@@ -195,6 +174,65 @@
}
}
+ private void initializeKeyphrasesFromTypedArray(TypedArray array) {
+ // Get the keyphrase ID.
+ int searchKeyphraseId = array.getInt(
+ com.android.internal.R.styleable.VoiceEnrollmentApplication_searchKeyphraseId, -1);
+ if (searchKeyphraseId <= 0) {
+ mParseError = "No valid searchKeyphraseId specified in meta-data";
+ Slog.w(TAG, mParseError);
+ return;
+ }
+
+ // Get the keyphrase text.
+ String searchKeyphrase = array.getString(
+ com.android.internal.R.styleable.VoiceEnrollmentApplication_searchKeyphrase);
+ if (searchKeyphrase == null) {
+ mParseError = "No valid searchKeyphrase specified in meta-data";
+ Slog.w(TAG, mParseError);
+ return;
+ }
+
+ // Get the supported locales.
+ String searchKeyphraseSupportedLocales = array.getString(
+ com.android.internal.R.styleable
+ .VoiceEnrollmentApplication_searchKeyphraseSupportedLocales);
+ if (searchKeyphraseSupportedLocales == null) {
+ mParseError = "No valid searchKeyphraseSupportedLocales specified in meta-data";
+ Slog.w(TAG, mParseError);
+ return;
+ }
+ ArraySet<Locale> locales = new ArraySet<>();
+ // Try adding locales if the locale string is non-empty.
+ if (!TextUtils.isEmpty(searchKeyphraseSupportedLocales)) {
+ try {
+ String[] supportedLocalesDelimited = searchKeyphraseSupportedLocales.split(",");
+ for (int i = 0; i < supportedLocalesDelimited.length; i++) {
+ locales.add(Locale.forLanguageTag(supportedLocalesDelimited[i]));
+ }
+ } catch (Exception ex) {
+ // We catch a generic exception here because we don't want the system service
+ // to be affected by a malformed metadata because invalid locales were specified
+ // by the system application.
+ mParseError = "Error reading searchKeyphraseSupportedLocales from meta-data";
+ Slog.w(TAG, mParseError, ex);
+ return;
+ }
+ }
+
+ // Get the supported recognition modes.
+ int recognitionModes = array.getInt(com.android.internal.R.styleable
+ .VoiceEnrollmentApplication_searchKeyphraseRecognitionFlags, -1);
+ if (recognitionModes < 0) {
+ mParseError = "No valid searchKeyphraseRecognitionFlags specified in meta-data";
+ Slog.w(TAG, mParseError);
+ return;
+ }
+ mKeyphrases = new KeyphraseMetadata[1];
+ mKeyphrases[0] = new KeyphraseMetadata(searchKeyphraseId, searchKeyphrase, locales,
+ recognitionModes);
+ }
+
public String getParseError() {
return mParseError;
}
@@ -217,11 +255,10 @@
* or {@link AlwaysOnHotwordDetector#MANAGE_ACTION_UN_ENROLL}
* @param keyphrase The keyphrase that the user needs to be enrolled to.
* @param locale The locale for which the enrollment needs to be performed.
- * This is a Java locale, for example "en_US".
* @return An {@link Intent} to manage the keyphrase. This can be null if managing the
* given keyphrase/locale combination isn't possible.
*/
- public Intent getManageKeyphraseIntent(int action, String keyphrase, String locale) {
+ public Intent getManageKeyphraseIntent(int action, String keyphrase, Locale locale) {
if (mEnrollmentPackage == null || mEnrollmentPackage.isEmpty()) {
Slog.w(TAG, "No enrollment application exists");
return null;
@@ -231,7 +268,7 @@
Intent intent = new Intent(ACTION_MANAGE_VOICE_KEYPHRASES)
.setPackage(mEnrollmentPackage)
.putExtra(EXTRA_VOICE_KEYPHRASE_HINT_TEXT, keyphrase)
- .putExtra(EXTRA_VOICE_KEYPHRASE_LOCALE, locale)
+ .putExtra(EXTRA_VOICE_KEYPHRASE_LOCALE, locale.toLanguageTag())
.putExtra(EXTRA_VOICE_KEYPHRASE_ACTION, action);
return intent;
}
@@ -248,7 +285,7 @@
* @return The metadata, if the enrollment client supports the given keyphrase
* and locale, null otherwise.
*/
- public KeyphraseMetadata getKeyphraseMetadata(String keyphrase, String locale) {
+ public KeyphraseMetadata getKeyphraseMetadata(String keyphrase, Locale locale) {
if (mKeyphrases == null || mKeyphrases.length == 0) {
Slog.w(TAG, "Enrollment application doesn't support keyphrases");
return null;
diff --git a/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java b/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java
index 38305f9..ed8c296 100644
--- a/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java
+++ b/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java
@@ -18,6 +18,8 @@
import android.util.ArraySet;
+import java.util.Locale;
+
/**
* A Voice Keyphrase metadata read from the enrollment application.
*
@@ -26,17 +28,14 @@
public class KeyphraseMetadata {
public final int id;
public final String keyphrase;
- public final ArraySet<String> supportedLocales;
+ public final ArraySet<Locale> supportedLocales;
public final int recognitionModeFlags;
- public KeyphraseMetadata(int id, String keyphrase, String[] supportedLocales,
+ public KeyphraseMetadata(int id, String keyphrase, ArraySet<Locale> supportedLocales,
int recognitionModeFlags) {
this.id = id;
this.keyphrase = keyphrase;
- this.supportedLocales = new ArraySet<String>(supportedLocales.length);
- for (String locale : supportedLocales) {
- this.supportedLocales.add(locale);
- }
+ this.supportedLocales = supportedLocales;
this.recognitionModeFlags = recognitionModeFlags;
}
@@ -56,7 +55,7 @@
/**
* @return Indicates if we support the given locale.
*/
- public boolean supportsLocale(String locale) {
+ public boolean supportsLocale(Locale locale) {
return supportedLocales.isEmpty() || supportedLocales.contains(locale);
}
}
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/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/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/PowerManager.java b/core/java/android/os/PowerManager.java
index 75f8279..f7b0ead 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -17,6 +17,7 @@
package android.os;
import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
import android.content.Context;
import android.util.Log;
@@ -186,8 +187,6 @@
* </p><p>
* Cannot be used with {@link #ACQUIRE_CAUSES_WAKEUP}.
* </p>
- *
- * {@hide}
*/
public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 0x00000020;
@@ -197,6 +196,8 @@
* <p>
* This is used by the dream manager to implement doze mode. It currently
* has no effect unless the power manager is in the dozing state.
+ * </p><p>
+ * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
* </p>
*
* {@hide}
@@ -243,11 +244,9 @@
public static final int UNIMPORTANT_FOR_LOGGING = 0x40000000;
/**
- * Flag for {@link WakeLock#release release(int)} to defer releasing a
- * {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK} wake lock until the proximity sensor returns
- * a negative value.
- *
- * {@hide}
+ * Flag for {@link WakeLock#release WakeLock.release(int)}: Defer releasing a
+ * {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK} wake lock until the proximity sensor
+ * indicates that an object is not in close proximity.
*/
public static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1;
@@ -276,28 +275,44 @@
* User activity event type: Unspecified event type.
* @hide
*/
+ @SystemApi
public static final int USER_ACTIVITY_EVENT_OTHER = 0;
/**
* User activity event type: Button or key pressed or released.
* @hide
*/
+ @SystemApi
public static final int USER_ACTIVITY_EVENT_BUTTON = 1;
/**
* User activity event type: Touch down, move or up.
* @hide
*/
+ @SystemApi
public static final int USER_ACTIVITY_EVENT_TOUCH = 2;
/**
- * User activity flag: Do not restart the user activity timeout or brighten
- * the display in response to user activity if it is already dimmed.
+ * User activity flag: If already dimmed, extend the dim timeout
+ * but do not brighten. This flag is useful for keeping the screen on
+ * a little longer without causing a visible change such as when
+ * the power key is pressed.
* @hide
*/
+ @SystemApi
public static final int USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS = 1 << 0;
/**
+ * User activity flag: Note the user activity as usual but do not
+ * reset the user activity timeout. This flag is useful for applying
+ * user activity power hints when interacting with the device indirectly
+ * on a secondary screen while allowing the primary screen to go to sleep.
+ * @hide
+ */
+ @SystemApi
+ public static final int USER_ACTIVITY_FLAG_INDIRECT = 1 << 1;
+
+ /**
* Go to sleep reason code: Going to sleep due by application request.
* @hide
*/
@@ -335,6 +350,12 @@
public static final int GO_TO_SLEEP_REASON_HDMI = 5;
/**
+ * Go to sleep flag: Skip dozing state and directly go to full sleep.
+ * @hide
+ */
+ public static final int GO_TO_SLEEP_FLAG_NO_DOZE = 1 << 0;
+
+ /**
* The value to pass as the 'reason' argument to reboot() to
* reboot into recovery mode (for applying system updates, doing
* factory resets, etc.).
@@ -347,12 +368,6 @@
*/
public static final String REBOOT_RECOVERY = "recovery";
- /**
- * Go to sleep flag: Skip dozing state and directly go to full sleep.
- * @hide
- */
- public static final int GO_TO_SLEEP_FLAG_NO_DOZE = 1 << 0;
-
final Context mContext;
final IPowerManager mService;
final Handler mHandler;
@@ -456,6 +471,7 @@
* @see #FULL_WAKE_LOCK
* @see #SCREEN_DIM_WAKE_LOCK
* @see #SCREEN_BRIGHT_WAKE_LOCK
+ * @see #PROXIMITY_SCREEN_OFF_WAKE_LOCK
* @see #ACQUIRE_CAUSES_WAKEUP
* @see #ON_AFTER_RELEASE
*/
@@ -505,11 +521,44 @@
*
* @see #wakeUp
* @see #goToSleep
+ *
+ * @removed Requires signature or system permission.
+ * @deprecated Use {@link #userActivity(long, int, int)}.
*/
+ @Deprecated
public void userActivity(long when, boolean noChangeLights) {
+ userActivity(when, USER_ACTIVITY_EVENT_OTHER,
+ noChangeLights ? USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS : 0);
+ }
+
+ /**
+ * Notifies the power manager that user activity happened.
+ * <p>
+ * Resets the auto-off timer and brightens the screen if the device
+ * is not asleep. This is what happens normally when a key or the touch
+ * screen is pressed or when some other user activity occurs.
+ * This method does not wake up the device if it has been put to sleep.
+ * </p><p>
+ * Requires the {@link android.Manifest.permission#DEVICE_POWER} or
+ * {@link android.Manifest.permission#USER_ACTIVITY} permission.
+ * </p>
+ *
+ * @param when The time of the user activity, in the {@link SystemClock#uptimeMillis()}
+ * time base. This timestamp is used to correctly order the user activity request with
+ * other power management functions. It should be set
+ * to the timestamp of the input event that caused the user activity.
+ * @param event The user activity event.
+ * @param flags Optional user activity flags.
+ *
+ * @see #wakeUp
+ * @see #goToSleep
+ *
+ * @hide Requires signature or system permission.
+ */
+ @SystemApi
+ public void userActivity(long when, int event, int flags) {
try {
- mService.userActivity(when, USER_ACTIVITY_EVENT_OTHER,
- noChangeLights ? USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS : 0);
+ mService.userActivity(when, event, flags);
} catch (RemoteException e) {
}
}
@@ -530,13 +579,33 @@
*
* @see #userActivity
* @see #wakeUp
+ *
+ * @removed Requires signature permission.
*/
public void goToSleep(long time) {
goToSleep(time, GO_TO_SLEEP_REASON_APPLICATION, 0);
}
/**
- * @hide
+ * Forces the device to go to sleep.
+ * <p>
+ * Overrides all the wake locks that are held.
+ * This is what happens when the power key is pressed to turn off the screen.
+ * </p><p>
+ * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
+ * </p>
+ *
+ * @param time The time when the request to go to sleep was issued, in the
+ * {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
+ * order the go to sleep request with other power management functions. It should be set
+ * to the timestamp of the input event that caused the request to go to sleep.
+ * @param reason The reason the device is going to sleep.
+ * @param flags Optional flags to apply when going to sleep.
+ *
+ * @see #userActivity
+ * @see #wakeUp
+ *
+ * @hide Requires signature permission.
*/
public void goToSleep(long time, int reason, int flags) {
try {
@@ -561,6 +630,8 @@
*
* @see #userActivity
* @see #goToSleep
+ *
+ * @removed Requires signature permission.
*/
public void wakeUp(long time) {
try {
@@ -588,7 +659,7 @@
* @see #wakeUp
* @see #goToSleep
*
- * @hide
+ * @hide Requires signature permission.
*/
public void nap(long time) {
try {
@@ -605,7 +676,7 @@
*
* @param brightness The brightness value from 0 to 255.
*
- * {@hide}
+ * @hide Requires signature permission.
*/
public void setBacklightBrightness(int brightness) {
try {
@@ -619,8 +690,6 @@
*
* @param level The wake lock level to check.
* @return True if the specified wake lock level is supported.
- *
- * {@hide}
*/
public boolean isWakeLockLevelSupported(int level) {
try {
@@ -893,8 +962,6 @@
*
* @param flags Combination of flag values to modify the release behavior.
* Currently only {@link #WAIT_FOR_PROXIMITY_NEGATIVE} is supported.
- *
- * {@hide}
*/
public void release(int flags) {
synchronized (mToken) {
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index 939cda9..d1fadd6 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -321,7 +321,7 @@
* Mount a secure container with the specified key and owner UID.
* Returns an int consistent with MountServiceResultCode
*/
- public int mountSecureContainer(String id, String key, int ownerUid)
+ public int mountSecureContainer(String id, String key, int ownerUid, boolean readOnly)
throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
@@ -331,6 +331,7 @@
_data.writeString(id);
_data.writeString(key);
_data.writeInt(ownerUid);
+ _data.writeInt(readOnly ? 1 : 0);
mRemote.transact(Stub.TRANSACTION_mountSecureContainer, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
@@ -834,6 +835,27 @@
}
return _result;
}
+
+ @Override
+ public int resizeSecureContainer(String id, int sizeMb, String key)
+ throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ int _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(id);
+ _data.writeInt(sizeMb);
+ _data.writeString(key);
+ mRemote.transact(Stub.TRANSACTION_resizeSecureContainer, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
}
private static final String DESCRIPTOR = "IMountService";
@@ -918,6 +940,8 @@
static final int TRANSACTION_getField = IBinder.FIRST_CALL_TRANSACTION + 39;
+ static final int TRANSACTION_resizeSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 40;
+
/**
* Cast an IBinder object into an IMountService interface, generating a
* proxy if needed.
@@ -1082,7 +1106,9 @@
key = data.readString();
int ownerUid;
ownerUid = data.readInt();
- int resultCode = mountSecureContainer(id, key, ownerUid);
+ boolean readOnly;
+ readOnly = data.readInt() != 0;
+ int resultCode = mountSecureContainer(id, key, ownerUid, readOnly);
reply.writeNoException();
reply.writeInt(resultCode);
return true;
@@ -1308,6 +1334,19 @@
reply.writeString(contents);
return true;
}
+ case TRANSACTION_resizeSecureContainer: {
+ data.enforceInterface(DESCRIPTOR);
+ String id;
+ id = data.readString();
+ int sizeMb;
+ sizeMb = data.readInt();
+ String key;
+ key = data.readString();
+ int resultCode = resizeSecureContainer(id, sizeMb, key);
+ reply.writeNoException();
+ reply.writeInt(resultCode);
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
}
@@ -1405,7 +1444,8 @@
* Mount a secure container with the specified key and owner UID. Returns an
* int consistent with MountServiceResultCode
*/
- public int mountSecureContainer(String id, String key, int ownerUid) throws RemoteException;
+ public int mountSecureContainer(String id, String key, int ownerUid, boolean readOnly)
+ throws RemoteException;
/**
* Mount external storage at given mount point. Returns an int consistent
@@ -1571,4 +1611,6 @@
* @return contents of field
*/
public String getField(String field) throws RemoteException;
+
+ public int resizeSecureContainer(String id, int sizeMb, String key) throws RemoteException;
}
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/service/trust/ITrustAgentService.aidl b/core/java/android/service/trust/ITrustAgentService.aidl
index 637d080..bd80a3f 100644
--- a/core/java/android/service/trust/ITrustAgentService.aidl
+++ b/core/java/android/service/trust/ITrustAgentService.aidl
@@ -24,6 +24,7 @@
*/
interface ITrustAgentService {
oneway void onUnlockAttempt(boolean successful);
+ oneway void onTrustTimeout();
oneway void setCallback(ITrustAgentServiceCallback callback);
oneway void setTrustAgentFeaturesEnabled(in Bundle options, IBinder token);
}
diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java
index 5fe9194..337ae60 100644
--- a/core/java/android/service/trust/TrustAgentService.java
+++ b/core/java/android/service/trust/TrustAgentService.java
@@ -30,6 +30,7 @@
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.util.Log;
import android.util.Slog;
@@ -37,7 +38,10 @@
* A service that notifies the system about whether it believes the environment of the device
* to be trusted.
*
- * <p>Trust agents may only be provided by the platform.</p>
+ * <p>Trust agents may only be provided by the platform. It is expected that there is only
+ * one trust agent installed on the platform. In the event there is more than one,
+ * either trust agent can enable trust.
+ * </p>
*
* <p>To extend this class, you must declare the service in your manifest file with
* the {@link android.Manifest.permission#BIND_TRUST_AGENT} permission
@@ -90,6 +94,7 @@
private static final int MSG_UNLOCK_ATTEMPT = 1;
private static final int MSG_SET_TRUST_AGENT_FEATURES_ENABLED = 2;
+ private static final int MSG_TRUST_TIMEOUT = 3;
private ITrustAgentServiceCallback mCallback;
@@ -118,6 +123,9 @@
onError("calling onSetTrustAgentFeaturesEnabledCompleted()");
}
break;
+ case MSG_TRUST_TIMEOUT:
+ onTrustTimeout();
+ break;
}
}
};
@@ -139,21 +147,32 @@
}
/**
- * Called when the user attempted to authenticate on the device.
+ * Called after the user attempts to authenticate in keyguard with their device credentials,
+ * such as pin, pattern or password.
*
- * @param successful true if the attempt succeeded
+ * @param successful true if the user successfully completed the challenge.
*/
public void onUnlockAttempt(boolean successful) {
}
+ /**
+ * Called when the timeout provided by the agent expires. Note that this may be called earlier
+ * than requested by the agent if the trust timeout is adjusted by the system or
+ * {@link DevicePolicyManager}. The agent is expected to re-evaluate the trust state and only
+ * call {@link #grantTrust(CharSequence, long, boolean)} if the trust state should be
+ * continued.
+ */
+ public void onTrustTimeout() {
+ }
+
private void onError(String msg) {
Slog.v(TAG, "Remote exception while " + msg);
}
/**
- * Called when device policy wants to restrict features in the TrustAgent in response to
+ * Called when device policy wants to restrict features in the agent in response to
* {@link DevicePolicyManager#setTrustAgentFeaturesEnabled(ComponentName, ComponentName, java.util.List) }.
- * TrustAgents that support this feature should overload this method and return 'true'.
+ * Agents that support this feature should overload this method and return 'true'.
*
* The list of options can be obtained by calling
* options.getStringArrayList({@link #KEY_FEATURES}). Presence of a feature string in the list
@@ -174,10 +193,19 @@
* Call to grant trust on the device.
*
* @param message describes why the device is trusted, e.g. "Trusted by location".
- * @param durationMs amount of time in milliseconds to keep the device in a trusted state. Trust
- * for this agent will automatically be revoked when the timeout expires.
- * @param initiatedByUser indicates that the user has explicitly initiated an action that proves
- * the user is about to use the device.
+ * @param durationMs amount of time in milliseconds to keep the device in a trusted state.
+ * Trust for this agent will automatically be revoked when the timeout expires unless
+ * extended by a subsequent call to this function. The timeout is measured from the
+ * invocation of this function as dictated by {@link SystemClock#elapsedRealtime())}.
+ * For security reasons, the value should be no larger than necessary.
+ * The value may be adjusted by the system as necessary to comply with a policy controlled
+ * by the system or {@link DevicePolicyManager} restrictions. See {@link #onTrustTimeout()}
+ * for determining when trust expires.
+ * @param initiatedByUser this is a hint to the system that trust is being granted as the
+ * direct result of user action - such as solving a security challenge. The hint is used
+ * by the system to optimize the experience. Behavior may vary by device and release, so
+ * one should only set this parameter if it meets the above criteria rather than relying on
+ * the behavior of any particular device or release.
* @throws IllegalStateException if the agent is not currently managing trust.
*/
public final void grantTrust(
@@ -254,13 +282,17 @@
}
private final class TrustAgentServiceWrapper extends ITrustAgentService.Stub {
- @Override
+ @Override /* Binder API */
public void onUnlockAttempt(boolean successful) {
- mHandler.obtainMessage(MSG_UNLOCK_ATTEMPT, successful ? 1 : 0, 0)
- .sendToTarget();
+ mHandler.obtainMessage(MSG_UNLOCK_ATTEMPT, successful ? 1 : 0, 0).sendToTarget();
}
- @Override
+ @Override /* Binder API */
+ public void onTrustTimeout() {
+ mHandler.sendEmptyMessage(MSG_TRUST_TIMEOUT);
+ }
+
+ @Override /* Binder API */
public void setCallback(ITrustAgentServiceCallback callback) {
synchronized (mLock) {
mCallback = callback;
@@ -280,7 +312,7 @@
}
}
- @Override
+ @Override /* Binder API */
public void setTrustAgentFeaturesEnabled(Bundle features, IBinder token) {
Message msg = mHandler.obtainMessage(MSG_SET_TRUST_AGENT_FEATURES_ENABLED, token);
msg.setData(features);
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 15e66a0..2095773 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -39,10 +39,10 @@
import com.android.internal.app.IVoiceInteractionManagerService;
-import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Locale;
/**
* A class that lets a VoiceInteractionService implementation interact with
@@ -167,7 +167,7 @@
private static final int MSG_DETECTION_RESUME = 5;
private final String mText;
- private final String mLocale;
+ private final Locale mLocale;
/**
* The metadata of the Keyphrase, derived from the enrollment application.
* This may be null if this keyphrase isn't supported by the enrollment application.
@@ -317,7 +317,7 @@
*
* @hide
*/
- public AlwaysOnHotwordDetector(String text, String locale, Callback callback,
+ public AlwaysOnHotwordDetector(String text, Locale locale, Callback callback,
KeyphraseEnrollmentInfo keyphraseEnrollmentInfo,
IVoiceInteractionService voiceInteractionService,
IVoiceInteractionManagerService modelManagementService) {
@@ -491,8 +491,6 @@
*/
void onSoundModelsChanged() {
synchronized (mLock) {
- // FIXME: This should stop the recognition if it was using an enrolled sound model
- // that's no longer available.
if (mAvailability == STATE_INVALID
|| mAvailability == STATE_HARDWARE_UNAVAILABLE
|| mAvailability == STATE_KEYPHRASE_UNSUPPORTED) {
@@ -500,6 +498,13 @@
return;
}
+ // Stop the recognition before proceeding.
+ // This is done because we want to stop the recognition on an older model if it changed
+ // or was deleted.
+ // The availability change callback should ensure that the client starts recognition
+ // again if needed.
+ stopRecognitionLocked();
+
// Execute a refresh availability task - which should then notify of a change.
new RefreshAvailabiltyTask().execute();
}
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index b2003568..884fa9f 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -35,6 +35,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.Locale;
/**
@@ -163,7 +164,7 @@
* Called during service initialization to tell you when the system is ready
* to receive interaction from it. You should generally do initialization here
* rather than in {@link #onCreate()}. Methods such as {@link #startSession(Bundle)} and
- * {@link #createAlwaysOnHotwordDetector(String, String, android.service.voice.AlwaysOnHotwordDetector.Callback)}
+ * {@link #createAlwaysOnHotwordDetector(String, Locale, android.service.voice.AlwaysOnHotwordDetector.Callback)}
* will not be operational until this point.
*/
public void onReady() {
@@ -200,6 +201,17 @@
}
/**
+ * FIXME: Remove once the prebuilts are updated.
+ *
+ * @hide
+ */
+ @Deprecated
+ public final AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(
+ String keyphrase, String locale, AlwaysOnHotwordDetector.Callback callback) {
+ return createAlwaysOnHotwordDetector(keyphrase, new Locale(locale), callback);
+ }
+
+ /**
* Creates an {@link AlwaysOnHotwordDetector} for the given keyphrase and locale.
* This instance must be retained and used by the client.
* Calling this a second time invalidates the previously created hotword detector
@@ -207,12 +219,11 @@
*
* @param keyphrase The keyphrase that's being used, for example "Hello Android".
* @param locale The locale for which the enrollment needs to be performed.
- * This is a Java locale, for example "en_US".
* @param callback The callback to notify of detection events.
* @return An always-on hotword detector for the given keyphrase and locale.
*/
public final AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(
- String keyphrase, String locale, AlwaysOnHotwordDetector.Callback callback) {
+ String keyphrase, Locale locale, AlwaysOnHotwordDetector.Callback callback) {
if (mSystemService == null) {
throw new IllegalStateException("Not available until onReady() is called");
}
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/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 a56d448..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;
@@ -202,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);
@@ -220,7 +221,7 @@
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);
@@ -329,13 +330,22 @@
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();
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 243d7d7..6f58582 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10793,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.
*
@@ -13090,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();
diff --git a/core/java/android/view/ViewAnimationUtils.java b/core/java/android/view/ViewAnimationUtils.java
index eeff90a..7ced088 100644
--- a/core/java/android/view/ViewAnimationUtils.java
+++ b/core/java/android/view/ViewAnimationUtils.java
@@ -26,7 +26,7 @@
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.
*
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/TextView.java b/core/java/android/widget/TextView.java
index a82fa65..9b3a1e0 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
@@ -5712,8 +5719,6 @@
}
if (mEditor != null && mEditor.mKeyListener != null) {
- resetErrorChangedFlag();
-
boolean doDown = true;
if (otherEvent != null) {
try {
@@ -7630,6 +7635,7 @@
list.get(i).afterTextChanged(text);
}
}
+ hideErrorIfUnchanged();
}
void updateAfterEdit() {
@@ -7669,7 +7675,7 @@
}
ims.mChangedDelta += after-before;
}
-
+ resetErrorChangedFlag();
sendOnTextChanged(buffer, start, before, after);
onTextChanged(buffer, start, before, after);
}
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 376e5b4..ae44047 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -37,6 +37,8 @@
import java.util.Calendar;
import java.util.Locale;
+import libcore.icu.LocaleData;
+
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES;
@@ -73,16 +75,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);
@@ -153,11 +145,8 @@
mMinuteSpinnerInput = (EditText) mMinuteSpinner.findViewById(R.id.numberpicker_input);
mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
- /* Get the localized am/pm strings and use them in the spinner */
- final Resources res = context.getResources();
- final String amText = res.getString(R.string.time_picker_am_label);
- final String pmText = res.getString(R.string.time_picker_pm_label);
- mAmPmStrings = new String[] {amText, pmText};
+ // Get the localized am/pm strings and use them in the spinner.
+ mAmPmStrings = getAmPmStrings(context);
// am/pm
View amPmView = mDelegator.findViewById(R.id.amPm);
@@ -216,8 +205,6 @@
updateMinuteControl();
updateAmPmControl();
- setOnTimeChangedListener(NO_OP_CHANGE_LISTENER);
-
// set to current time
setCurrentHour(mTempCalendar.get(Calendar.HOUR_OF_DAY));
setCurrentMinute(mTempCalendar.get(Calendar.MINUTE));
@@ -613,5 +600,12 @@
}
};
}
-}
+ public static String[] getAmPmStrings(Context context) {
+ String[] result = new String[2];
+ LocaleData d = LocaleData.get(context.getResources().getConfiguration().locale);
+ result[0] = d.amPm[0].length() > 2 ? d.narrowAm : d.amPm[0];
+ result[1] = d.amPm[1].length() > 2 ? d.narrowPm : d.amPm[1];
+ return result;
+ }
+}
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index 9a50250..dd1bf4f 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -127,8 +127,10 @@
mSelectHours = res.getString(R.string.select_hours);
mMinutePickerDescription = res.getString(R.string.minute_picker_description);
mSelectMinutes = res.getString(R.string.select_minutes);
- mAmText = res.getString(R.string.time_picker_am_label);
- mPmText = res.getString(R.string.time_picker_pm_label);
+
+ String[] amPmStrings = TimePickerClockDelegate.getAmPmStrings(context);
+ mAmText = amPmStrings[0];
+ mPmText = amPmStrings[1];
final int layoutResourceId = a.getResourceId(R.styleable.TimePicker_internalLayout,
R.layout.time_picker_holo);
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/LocalePicker.java b/core/java/com/android/internal/app/LocalePicker.java
index 229df8f..1f0bb76 100644
--- a/core/java/com/android/internal/app/LocalePicker.java
+++ b/core/java/com/android/internal/app/LocalePicker.java
@@ -27,6 +27,7 @@
import android.content.res.Resources;
import android.os.Bundle;
import android.os.RemoteException;
+import android.provider.Settings;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -50,10 +51,6 @@
public void onLocaleSelected(Locale locale);
}
- protected boolean isInDeveloperMode() {
- return false;
- }
-
LocaleSelectionListener mListener; // default to null
public static class LocaleInfo implements Comparable<LocaleInfo> {
@@ -86,40 +83,17 @@
}
}
- /**
- * Constructs an Adapter object containing Locale information. Content is sorted by
- * {@link LocaleInfo#label}.
- */
- public static ArrayAdapter<LocaleInfo> constructAdapter(Context context) {
- return constructAdapter(context, false /* disable pesudolocales */);
- }
-
- public static ArrayAdapter<LocaleInfo> constructAdapter(Context context,
- final boolean isInDeveloperMode) {
- return constructAdapter(context, R.layout.locale_picker_item, R.id.locale,
- isInDeveloperMode);
- }
-
- public static ArrayAdapter<LocaleInfo> constructAdapter(Context context,
- final int layoutId, final int fieldId) {
- return constructAdapter(context, layoutId, fieldId, false /* disable pseudolocales */);
- }
-
public static List<LocaleInfo> getAllAssetLocales(Context context, boolean isInDeveloperMode) {
final Resources resources = context.getResources();
final String[] locales = Resources.getSystem().getAssets().getLocales();
List<String> localeList = new ArrayList<String>(locales.length);
Collections.addAll(localeList, locales);
- if (isInDeveloperMode) {
- if (!localeList.contains("zz_ZZ")) {
- localeList.add("zz_ZZ");
- }
- /** - TODO: Enable when zz_ZY Pseudolocale is complete
- * if (!localeList.contains("zz_ZY")) {
- * localeList.add("zz_ZY");
- * }
- */
+
+ // Don't show the pseudolocales unless we're in developer mode. http://b/17190407.
+ if (!isInDeveloperMode) {
+ localeList.remove("ar-XB");
+ localeList.remove("en-XA");
}
Collections.sort(localeList);
@@ -160,14 +134,7 @@
localeInfos.add(new LocaleInfo(toTitleCase(
getDisplayName(l, specialLocaleCodes, specialLocaleNames)), l));
} else {
- String displayName;
- if (locale.equals("zz_ZZ")) {
- displayName = "[Developer] Accented English";
- } else if (locale.equals("zz_ZY")) {
- displayName = "[Developer] Fake Bi-Directional";
- } else {
- displayName = toTitleCase(l.getDisplayLanguage(l));
- }
+ String displayName = toTitleCase(l.getDisplayLanguage(l));
if (DEBUG) {
Log.v(TAG, "adding "+displayName);
}
@@ -180,8 +147,18 @@
return localeInfos;
}
+ /**
+ * Constructs an Adapter object containing Locale information. Content is sorted by
+ * {@link LocaleInfo#label}.
+ */
+ public static ArrayAdapter<LocaleInfo> constructAdapter(Context context) {
+ return constructAdapter(context, R.layout.locale_picker_item, R.id.locale);
+ }
+
public static ArrayAdapter<LocaleInfo> constructAdapter(Context context,
- final int layoutId, final int fieldId, final boolean isInDeveloperMode) {
+ final int layoutId, final int fieldId) {
+ boolean isInDeveloperMode = Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
final List<LocaleInfo> localeInfos = getAllAssetLocales(context, isInDeveloperMode);
final LayoutInflater inflater =
@@ -232,8 +209,7 @@
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- final ArrayAdapter<LocaleInfo> adapter = constructAdapter(getActivity(),
- isInDeveloperMode());
+ final ArrayAdapter<LocaleInfo> adapter = constructAdapter(getActivity());
setListAdapter(adapter);
}
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index 179d5e8..02f675c 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -25,6 +25,7 @@
import static android.system.OsConstants.S_IXGRP;
import static android.system.OsConstants.S_IXOTH;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.Package;
@@ -51,9 +52,11 @@
*/
public class NativeLibraryHelper {
private static final String TAG = "NativeHelper";
-
private static final boolean DEBUG_NATIVE = false;
+ public static final String LIB_DIR_NAME = "lib";
+ public static final String LIB64_DIR_NAME = "lib64";
+
// Special value for {@code PackageParser.Package#cpuAbiOverride} to indicate
// that the cpuAbiOverride must be clear.
public static final String CLEAR_ABI_OVERRIDE = "-";
@@ -70,6 +73,7 @@
private volatile boolean mClosed;
final long[] apkHandles;
+ final boolean multiArch;
public static Handle create(File packageFile) throws IOException {
try {
@@ -81,14 +85,15 @@
}
public static Handle create(Package pkg) throws IOException {
- return create(pkg.getAllCodePaths());
+ return create(pkg.getAllCodePaths(),
+ (pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) != 0);
}
public static Handle create(PackageLite lite) throws IOException {
- return create(lite.getAllCodePaths());
+ return create(lite.getAllCodePaths(), lite.multiArch);
}
- private static Handle create(List<String> codePaths) throws IOException {
+ private static Handle create(List<String> codePaths, boolean multiArch) throws IOException {
final int size = codePaths.size();
final long[] apkHandles = new long[size];
for (int i = 0; i < size; i++) {
@@ -103,11 +108,12 @@
}
}
- return new Handle(apkHandles);
+ return new Handle(apkHandles, multiArch);
}
- Handle(long[] apkHandles) {
+ Handle(long[] apkHandles, boolean multiArch) {
this.apkHandles = apkHandles;
+ this.multiArch = multiArch;
mGuard.open("close");
}
@@ -159,8 +165,7 @@
* @return {@link PackageManager#INSTALL_SUCCEEDED} if successful or another
* error code from that class if not
*/
- public static int copyNativeBinariesIfNeededLI(Handle handle, File sharedLibraryDir,
- String abi) {
+ public static int copyNativeBinaries(Handle handle, File sharedLibraryDir, String abi) {
for (long apkHandle : handle.apkHandles) {
int res = nativeCopyNativeBinaries(apkHandle, sharedLibraryDir.getPath(), abi);
if (res != INSTALL_SUCCEEDED) {
@@ -267,7 +272,7 @@
}
}
- private static long sumNativeBinaries(Handle handle, String[] abiList) {
+ private static long sumNativeBinariesForSupportedAbi(Handle handle, String[] abiList) {
int abi = findSupportedAbi(handle, abiList);
if (abi >= 0) {
return sumNativeBinaries(handle, abiList[abi]);
@@ -276,7 +281,7 @@
}
}
- public static int copyNativeBinariesIfNeededLI(Handle handle, File libraryRoot,
+ public static int copyNativeBinariesForSupportedAbi(Handle handle, File libraryRoot,
String[] abiList, boolean useIsaSubdir) throws IOException {
createNativeLibrarySubdir(libraryRoot);
@@ -300,7 +305,7 @@
subDir = libraryRoot;
}
- int copyRet = copyNativeBinariesIfNeededLI(handle, subDir, abiList[abi]);
+ int copyRet = copyNativeBinaries(handle, subDir, abiList[abi]);
if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
return copyRet;
}
@@ -309,10 +314,10 @@
return abi;
}
- public static int copyNativeBinariesIfNeededLI(Handle handle, File libraryRoot,
- String abiOverride, boolean multiArch) {
+ public static int copyNativeBinariesWithOverride(Handle handle, File libraryRoot,
+ String abiOverride) {
try {
- if (multiArch) {
+ if (handle.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.
@@ -322,7 +327,7 @@
int copyRet = PackageManager.NO_NATIVE_LIBRARIES;
if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
- copyRet = copyNativeBinariesIfNeededLI(handle, libraryRoot,
+ copyRet = copyNativeBinariesForSupportedAbi(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) {
@@ -332,7 +337,7 @@
}
if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
- copyRet = copyNativeBinariesIfNeededLI(handle, libraryRoot,
+ copyRet = copyNativeBinariesForSupportedAbi(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) {
@@ -355,7 +360,7 @@
abiList = Build.SUPPORTED_32_BIT_ABIS;
}
- int copyRet = copyNativeBinariesIfNeededLI(handle, libraryRoot, abiList,
+ int copyRet = copyNativeBinariesForSupportedAbi(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 + "]");
@@ -370,10 +375,10 @@
}
}
- public static long sumNativeBinaries(Handle handle, String abiOverride, boolean multiArch)
+ public static long sumNativeBinariesWithOverride(Handle handle, String abiOverride)
throws IOException {
long sum = 0;
- if (multiArch) {
+ if (handle.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.
@@ -382,11 +387,11 @@
}
if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
- sum += sumNativeBinaries(handle, Build.SUPPORTED_32_BIT_ABIS);
+ sum += sumNativeBinariesForSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
}
if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
- sum += sumNativeBinaries(handle, Build.SUPPORTED_64_BIT_ABIS);
+ sum += sumNativeBinariesForSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
}
} else {
String cpuAbiOverride = null;
@@ -403,7 +408,7 @@
abiList = Build.SUPPORTED_32_BIT_ABIS;
}
- sum += sumNativeBinaries(handle, abiList);
+ sum += sumNativeBinariesForSupportedAbi(handle, abiList);
}
return sum;
}
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index a529cc3..c17f4ee 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -16,11 +16,14 @@
package com.android.internal.content;
+import static android.net.TrafficStats.MB_IN_BYTES;
+
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.content.pm.PackageParser.PackageLite;
import android.os.Environment;
import android.os.Environment.UserEnvironment;
import android.os.FileUtils;
@@ -77,9 +80,10 @@
}
}
- public static String createSdDir(int sizeMb, String cid, String sdEncKey, int uid,
+ public static String createSdDir(long sizeBytes, String cid, String sdEncKey, int uid,
boolean isExternal) {
- // Create mount point via MountService
+ // Round up to nearest MB, plus another MB for filesystem overhead
+ final int sizeMb = (int) ((sizeBytes + MB_IN_BYTES) / MB_IN_BYTES) + 1;
try {
IMountService mountService = getMountService();
@@ -102,19 +106,39 @@
return null;
}
- public static String mountSdDir(String cid, String key, int ownerUid) {
- try {
- int rc = getMountService().mountSecureContainer(cid, key, ownerUid);
- if (rc != StorageResultCode.OperationSucceeded) {
- Log.i(TAG, "Failed to mount container " + cid + " rc : " + rc);
- return null;
+ public static boolean resizeSdDir(long sizeBytes, String cid, String sdEncKey) {
+ // Round up to nearest MB, plus another MB for filesystem overhead
+ final int sizeMb = (int) ((sizeBytes + MB_IN_BYTES) / MB_IN_BYTES) + 1;
+ try {
+ IMountService mountService = getMountService();
+ int rc = mountService.resizeSecureContainer(cid, sizeMb, sdEncKey);
+ if (rc == StorageResultCode.OperationSucceeded) {
+ return true;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "MountService running?");
}
- return getMountService().getSecureContainerPath(cid);
- } catch (RemoteException e) {
- Log.e(TAG, "MountService running?");
+ Log.e(TAG, "Failed to create secure container " + cid);
+ return false;
}
- return null;
- }
+
+ public static String mountSdDir(String cid, String key, int ownerUid) {
+ return mountSdDir(cid, key, ownerUid, true);
+ }
+
+ public static String mountSdDir(String cid, String key, int ownerUid, boolean readOnly) {
+ try {
+ int rc = getMountService().mountSecureContainer(cid, key, ownerUid, readOnly);
+ if (rc != StorageResultCode.OperationSucceeded) {
+ Log.i(TAG, "Failed to mount container " + cid + " rc : " + rc);
+ return null;
+ }
+ return getMountService().getSecureContainerPath(cid);
+ } catch (RemoteException e) {
+ Log.e(TAG, "MountService running?");
+ }
+ return null;
+ }
public static boolean unMountSdDir(String cid) {
try {
@@ -400,6 +424,37 @@
}
}
+ public static long calculateInstalledSize(PackageLite pkg, boolean isForwardLocked,
+ String abiOverride) throws IOException {
+ NativeLibraryHelper.Handle handle = null;
+ try {
+ handle = NativeLibraryHelper.Handle.create(pkg);
+ return calculateInstalledSize(pkg, handle, isForwardLocked, abiOverride);
+ } finally {
+ IoUtils.closeQuietly(handle);
+ }
+ }
+
+ public static long calculateInstalledSize(PackageLite pkg, NativeLibraryHelper.Handle handle,
+ boolean isForwardLocked, String abiOverride) throws IOException {
+ long sizeBytes = 0;
+
+ // Include raw APKs, and possibly unpacked resources
+ for (String codePath : pkg.getAllCodePaths()) {
+ final File codeFile = new File(codePath);
+ sizeBytes += codeFile.length();
+
+ if (isForwardLocked) {
+ sizeBytes += PackageHelper.extractPublicFiles(codeFile, null);
+ }
+ }
+
+ // Include all relevant native code
+ sizeBytes += NativeLibraryHelper.sumNativeBinariesWithOverride(handle, abiOverride);
+
+ return sizeBytes;
+ }
+
public static String replaceEnd(String str, String before, String after) {
if (!str.endsWith(before)) {
throw new IllegalArgumentException(
diff --git a/core/java/com/android/internal/net/LegacyVpnInfo.java b/core/java/com/android/internal/net/LegacyVpnInfo.java
index f812ad6..d6f6d0b 100644
--- a/core/java/com/android/internal/net/LegacyVpnInfo.java
+++ b/core/java/com/android/internal/net/LegacyVpnInfo.java
@@ -40,6 +40,7 @@
public String key;
public int state = -1;
+ public PendingIntent intent;
@Override
public int describeContents() {
@@ -50,6 +51,7 @@
public void writeToParcel(Parcel out, int flags) {
out.writeString(key);
out.writeInt(state);
+ out.writeParcelable(intent, flags);
}
public static final Parcelable.Creator<LegacyVpnInfo> CREATOR =
@@ -59,6 +61,7 @@
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 aa66d7d..9c3f419 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -28,6 +28,7 @@
import android.net.RouteInfo;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.UserHandle;
import java.net.Inet4Address;
import java.net.InetAddress;
@@ -57,6 +58,15 @@
return intent;
}
+ /** NOTE: This should only be used for legacy VPN. */
+ 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();
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 a2b8ff2..8111e63 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -272,9 +272,12 @@
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;
+ nonTabMaxHeight = Math.max(nonTabMaxHeight, isCollapsed(child) ? 0 :
+ child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
}
if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
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/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_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 3fb084a..8f30f5d 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -180,7 +180,8 @@
// takes ownership of ScreenshotClient
SkMallocPixelRef* pixels = SkMallocPixelRef::NewWithProc(screenshotInfo,
(size_t) rowBytes, NULL, (void*) screenshot->getPixels(), &DeleteScreenshot,
- (void*) (screenshot.detach()));
+ (void*) (screenshot.get()));
+ screenshot.detach();
pixels->setImmutable();
bitmap->setPixelRef(pixels)->unref();
bitmap->lockPixels();
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7809c71..672ad84 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2408,6 +2408,13 @@
android:description="@string/permdesc_devicePower"
android:protectionLevel="signature" />
+ <!-- Allows access to the PowerManager.userActivity function.
+ <p>Not for use by third-party applications. @hide @SystemApi -->
+ <permission android:name="android.permission.USER_ACTIVITY"
+ android:label="@string/permlab_userActivity"
+ android:description="@string/permdesc_userActivity"
+ android:protectionLevel="signature|system" />
+
<!-- @hide Allows low-level access to tun tap driver -->
<permission android:name="android.permission.NET_TUNNELING"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
@@ -2869,7 +2876,7 @@
android:label="@string/managed_profile_label">
</activity-alias>
<activity android:name="com.android.internal.app.HeavyWeightSwitcherActivity"
- android:theme="@style/Theme.Holo.Dialog"
+ android:theme="@style/Theme.Material.Dialog"
android:label="@string/heavy_weight_switcher_title"
android:finishOnCloseSystemDialogs="true"
android:excludeFromRecents="true"
diff --git a/core/res/res/color/switch_thumb_material_dark.xml b/core/res/res/color/switch_thumb_material_dark.xml
new file mode 100644
index 0000000..8fede70
--- /dev/null
+++ b/core/res/res/color/switch_thumb_material_dark.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<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/core/res/res/color/switch_thumb_material_light.xml b/core/res/res/color/switch_thumb_material_light.xml
new file mode 100644
index 0000000..1a34b74
--- /dev/null
+++ b/core/res/res/color/switch_thumb_material_light.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<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-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-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-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/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/core/res/res/layout/notification_template_material_big_base.xml b/core/res/res/layout/notification_template_material_big_base.xml
index 3d8a527..f264b7b 100644
--- a/core/res/res/layout/notification_template_material_big_base.xml
+++ b/core/res/res/layout/notification_template_material_big_base.xml
@@ -37,14 +37,30 @@
>
<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:layout_marginEnd="8dp"
- android:singleLine="false"
- android:visibility="gone"
- />
+ 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"
diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml
index 36f8701..d9120f6 100644
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -37,14 +37,31 @@
>
<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:layout_marginEnd="8dp"
android:layout_marginBottom="10dp"
- android:visibility="gone"
- />
+ 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"
diff --git a/core/res/res/layout/notification_template_material_inbox.xml b/core/res/res/layout/notification_template_material_inbox.xml
index ef6cbd0..38b3ae2 100644
--- a/core/res/res/layout/notification_template_material_inbox.xml
+++ b/core/res/res/layout/notification_template_material_inbox.xml
@@ -37,79 +37,102 @@
>
<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"
diff --git a/core/res/res/layout/notification_template_part_line2.xml b/core/res/res/layout/notification_template_part_line2.xml
index d3f202f..1f95150 100644
--- a/core/res/res/layout/notification_template_part_line2.xml
+++ b/core/res/res/layout/notification_template_part_line2.xml
@@ -16,20 +16,37 @@
-->
<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_marginEnd="8dp"
- android:layout_marginTop="-1dp"
- android:layout_marginBottom="-1dp"
- android:singleLine="true"
- android:fadingEdge="horizontal"
- android:ellipsize="marquee"
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"
diff --git a/core/res/res/layout/notification_template_part_line3.xml b/core/res/res/layout/notification_template_part_line3.xml
index dd2779d..06de2a5 100644
--- a/core/res/res/layout/notification_template_part_line3.xml
+++ b/core/res/res/layout/notification_template_part_line3.xml
@@ -43,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/styles.xml b/core/res/res/values-television/styles.xml
new file mode 100644
index 0000000..4c0562f
--- /dev/null
+++ b/core/res/res/values-television/styles.xml
@@ -0,0 +1,22 @@
+<!-- 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.
+-->
+
+<resources>
+ <style name="Lighting">
+ <item name="lightY">-300dp</item>
+ <item name="ambientShadowAlpha">0.4</item>
+ <item name="spotShadowAlpha">0.4</item>
+ </style>
+</resources>
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 ed9e83f..cc8d7cf 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
@@ -3799,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" />
@@ -3946,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
@@ -5589,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}. -->
@@ -6898,8 +6930,8 @@
<attr name="searchKeyphraseId" format="integer" />
<!-- The actual keyphrase/hint text, or empty if not keyphrase dependent. @hide @SystemApi -->
<attr name="searchKeyphrase" format="string" />
- <!-- A comma separated list of java locales that are supported for this keyphrase,
- or empty if not locale dependent. @hide @SystemApi -->
+ <!-- A comma separated list of BCP-47 language tag for locales that are supported
+ for this keyphrase, or empty if not locale dependent. @hide @SystemApi -->
<attr name="searchKeyphraseSupportedLocales" format="string" />
<!-- Flags for supported recognition modes. @hide @SystemApi -->
<attr name="searchKeyphraseRecognitionFlags">
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 cf9a415..4f0757c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -673,6 +673,37 @@
-->
<integer name="config_doubleTapOnHomeBehavior">0</integer>
+ <!-- Minimum screen brightness setting allowed by the power manager.
+ The user is forbidden from setting the brightness below this level. -->
+ <integer name="config_screenBrightnessSettingMinimum">10</integer>
+
+ <!-- Maximum screen brightness allowed by the power manager.
+ The user is forbidden from setting the brightness above this level. -->
+ <integer name="config_screenBrightnessSettingMaximum">255</integer>
+
+ <!-- Default screen brightness setting.
+ Must be in the range specified by minimum and maximum. -->
+ <integer name="config_screenBrightnessSettingDefault">102</integer>
+
+ <!-- Screen brightness used to dim the screen while dozing in a very low power state.
+ May be less than the minimum allowed brightness setting
+ that can be set by the user. -->
+ <integer name="config_screenBrightnessDoze">1</integer>
+
+ <!-- Screen brightness used to dim the screen when the user activity
+ timeout expires. May be less than the minimum allowed brightness setting
+ that can be set by the user. -->
+ <integer name="config_screenBrightnessDim">10</integer>
+
+ <!-- Minimum allowable screen brightness to use in a very dark room.
+ This value sets the floor for the darkest possible auto-brightness
+ adjustment. It is expected to be somewhat less than the first entry in
+ config_autoBrightnessLcdBacklightValues so as to allow the user to have
+ some range of adjustment to dim the screen further than usual in very
+ dark rooms. The contents of the screen must still be clearly visible
+ in darkness (although they may not be visible in a bright room). -->
+ <integer name="config_screenBrightnessDark">1</integer>
+
<!-- Array of light sensor LUX values to define our levels for auto backlight brightness support.
The N entries of this array define N + 1 control points as follows:
(1-based arrays)
@@ -696,28 +727,6 @@
<integer-array name="config_autoBrightnessLevels">
</integer-array>
- <!-- Minimum screen brightness setting allowed by the power manager.
- The user is forbidden from setting the brightness below this level. -->
- <integer name="config_screenBrightnessSettingMinimum">10</integer>
-
- <!-- Maximum screen brightness allowed by the power manager.
- The user is forbidden from setting the brightness above this level. -->
- <integer name="config_screenBrightnessSettingMaximum">255</integer>
-
- <!-- Default screen brightness setting.
- Must be in the range specified by minimum and maximum. -->
- <integer name="config_screenBrightnessSettingDefault">102</integer>
-
- <!-- Screen brightness used to dim the screen while dozing in a very low power state.
- May be less than the minimum allowed brightness setting
- that can be set by the user. -->
- <integer name="config_screenBrightnessDoze">1</integer>
-
- <!-- Screen brightness used to dim the screen when the user activity
- timeout expires. May be less than the minimum allowed brightness setting
- that can be set by the user. -->
- <integer name="config_screenBrightnessDim">10</integer>
-
<!-- Array of output values for LCD backlight corresponding to the LUX values
in the config_autoBrightnessLevels array. This array should have size one greater
than the size of the config_autoBrightnessLevels array.
@@ -1378,6 +1387,14 @@
<string-array name="config_mobile_tcp_buffers">
</string-array>
+ <!-- Configure ethernet tcp buffersizes in the form:
+ rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max -->
+ <string name="config_ethernet_tcp_buffers" translatable="false">524288,1048576,3145728,524288,1048576,2097152</string>
+
+ <!-- Configure wifi tcp buffersizes in the form:
+ rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max -->
+ <string name="config_wifi_tcp_buffers" translatable="false">524288,1048576,2097152,262144,524288,1048576</string>
+
<!-- Whether WiFi display is supported by this device.
There are many prerequisites for this feature to work correctly.
Here are a few of them:
@@ -1675,4 +1692,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 6022bdc..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>
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 4f0c5eb..f2466f7 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2275,6 +2275,9 @@
<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 b198329..d2cf689 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1815,6 +1815,11 @@
<string name="permdesc_devicePower" product="default">Allows the app to turn the phone on or off.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_userActivity">reset display timeout</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_userActivity">Allows the app to reset the display timeout.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_factoryTest">run in factory test mode</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_factoryTest" product="tablet">Run as a low-level manufacturer test,
@@ -3958,7 +3963,7 @@
<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 profile</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 profile</string>
@@ -4142,10 +4147,6 @@
<string name="time_picker_increment_set_pm_button">Set PM</string>
<!-- Description of the button to decrease the TimePicker's set AM value. [CHAR LIMIT=NONE] -->
<string name="time_picker_decrement_set_am_button">Set AM</string>
- <!-- Label for the TimePicker's PM button. [CHAR LIMIT=2] -->
- <string name="time_picker_pm_label">PM</string>
- <!-- Label for the TimePicker's AM button. [CHAR LIMIT=2] -->
- <string name="time_picker_am_label">AM</string>
<!-- DatePicker - accessibility support -->
<!-- Description of the button to increase the DatePicker's month value. [CHAR LIMIT=NONE] -->
@@ -4325,7 +4326,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] -->
@@ -4543,6 +4544,8 @@
<string name="enable_accessibility_canceled">Accessibility canceled.</string>
<!-- Text spoken when the current user is switched if accessibility is enabled. [CHAR LIMIT=none] -->
<string name="user_switched">Current user <xliff:g id="name" example="Bob">%1$s</xliff:g>.</string>
+ <!-- Message shown when switching to a user [CHAR LIMIT=none] -->
+ <string name="user_switching_message">Switching to user <xliff:g id="name" example="Bob">%1$s</xliff:g></string>
<!-- Default name of the owner user [CHAR LIMIT=20] -->
<string name="owner_name" msgid="3879126011135546571">Owner</string>
<!-- Error message title [CHAR LIMIT=35] -->
@@ -4821,7 +4824,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]
-->
@@ -4867,7 +4870,7 @@
<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>
+ <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>
<!-- [CHAR_LIMIT=NONE] Zen mode: Condition summary for built-in downtime condition, if active -->
<string name="downtime_condition_summary">Until your downtime ends at <xliff:g id="formattedTime" example="10.00 PM">%1$s</xliff:g></string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index af73c02..3f373aa 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" />
@@ -834,6 +836,7 @@
<java-symbol type="string" name="time_picker_increment_set_pm_button" />
<java-symbol type="string" name="upload_file" />
<java-symbol type="string" name="user_switched" />
+ <java-symbol type="string" name="user_switching_message" />
<java-symbol type="string" name="volume_alarm" />
<java-symbol type="string" name="volume_icon_description_bluetooth" />
<java-symbol type="string" name="volume_icon_description_incall" />
@@ -987,6 +990,8 @@
<java-symbol type="string" name="ssl_ca_cert_warning" />
<java-symbol type="string" name="lockscreen_transport_play_description" />
<java-symbol type="string" name="lockscreen_transport_pause_description" />
+ <java-symbol type="string" name="config_ethernet_tcp_buffers" />
+ <java-symbol type="string" name="config_wifi_tcp_buffers" />
<java-symbol type="plurals" name="abbrev_in_num_days" />
<java-symbol type="plurals" name="abbrev_in_num_hours" />
@@ -1560,6 +1565,7 @@
<java-symbol type="integer" name="config_screenBrightnessSettingMinimum" />
<java-symbol type="integer" name="config_screenBrightnessSettingMaximum" />
<java-symbol type="integer" name="config_screenBrightnessSettingDefault" />
+ <java-symbol type="integer" name="config_screenBrightnessDark" />
<java-symbol type="integer" name="config_screenBrightnessDim" />
<java-symbol type="integer" name="config_screenBrightnessDoze" />
<java-symbol type="integer" name="config_shutdownBatteryTemperature" />
@@ -1980,8 +1986,6 @@
<java-symbol type="attr" name="headerSelectedTextColor" />
<java-symbol type="attr" name="amPmSelectedBackgroundColor" />
<java-symbol type="bool" name="config_sms_decode_gsm_8bit_data" />
- <java-symbol type="string" name="time_picker_am_label" />
- <java-symbol type="string" name="time_picker_pm_label" />
<java-symbol type="dimen" name="text_size_small_material" />
<java-symbol type="attr" name="checkMarkGravity" />
<java-symbol type="layout" name="select_dialog_singlechoice_material" />
@@ -1990,4 +1994,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/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
index b4b0e53..01995c7 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
@@ -127,10 +127,11 @@
assertTrue("failed to connect to " + mTestAccessPoint,
connectToWifi(mTestAccessPoint));
// assert that WifiManager reports correct state
- assertTrue(waitForWifiState(WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
+ assertTrue("wifi not enabled", waitForWifiState(
+ WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
// assert that ConnectivityManager reports correct state for Wifi
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
- WIFI_CONNECTION_TIMEOUT));
+ assertTrue("wifi not connected", waitForNetworkState(
+ ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
// below check disbabled since we have bug in what ConnectivityManager returns
// if (!mWifiOnlyFlag) {
// // assert that ConnectivityManager reports correct state for mobile
@@ -267,8 +268,8 @@
// connect to Wifi
assertTrue("failed to connect to " + mTestAccessPoint,
connectToWifi(mTestAccessPoint));
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
- WIFI_CONNECTION_TIMEOUT));
+ assertTrue("wifi not connected", waitForNetworkState(
+ ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
// verify that connection actually works
assertTrue("no network connectivity after wifi enable", checkNetworkConnectivity());
@@ -289,8 +290,8 @@
// connect to Wifi
assertTrue("failed to connect to " + mTestAccessPoint,
connectToWifi(mTestAccessPoint));
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
- WIFI_CONNECTION_TIMEOUT));
+ assertTrue("wifi not connected", waitForNetworkState(
+ ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
// enable airplane mode without clearing Wifi
mCm.setAirplaneMode(true);
@@ -322,8 +323,8 @@
// connect to Wifi
assertTrue("failed to connect to " + mTestAccessPoint,
connectToWifi(mTestAccessPoint));
- assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
- WIFI_CONNECTION_TIMEOUT));
+ assertTrue("wifi not connected", waitForNetworkState(
+ ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
assertNotNull("not associated with any AP", mWifiManager.getConnectionInfo().getBSSID());
// disconnect from the current AP
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 859c30c..6ef4f06 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -198,6 +198,9 @@
// Stress Wifi reconnection to secure net after sleep
@LargeTest
public void testWifiReconnectionAfterSleep() {
+ // set always scan to false
+ Settings.Global.putInt(mRunner.getContext().getContentResolver(),
+ Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0);
// set wifi sleep policy to never on while in sleep
Settings.Global.putInt(mRunner.getContext().getContentResolver(),
Settings.Global.WIFI_SLEEP_POLICY, Settings.Global.WIFI_SLEEP_POLICY_NEVER);
diff --git a/core/tests/coretests/src/android/content/pm/PackageHelperTests.java b/core/tests/coretests/src/android/content/pm/PackageHelperTests.java
index 7ad35d0..06c495e 100644
--- a/core/tests/coretests/src/android/content/pm/PackageHelperTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageHelperTests.java
@@ -16,7 +16,7 @@
package android.content.pm;
-import com.android.internal.content.PackageHelper;
+import static android.net.TrafficStats.MB_IN_BYTES;
import android.os.IBinder;
import android.os.RemoteException;
@@ -25,6 +25,8 @@
import android.test.AndroidTestCase;
import android.util.Log;
+import com.android.internal.content.PackageHelper;
+
public class PackageHelperTests extends AndroidTestCase {
private static final boolean localLOGV = true;
public static final String TAG = "PackageHelperTests";
@@ -81,8 +83,8 @@
public void testMountAndPullSdCard() {
try {
fullId = PREFIX;
- fullId2 = PackageHelper.createSdDir(1024, fullId, "none", android.os.Process.myUid(),
- true);
+ fullId2 = PackageHelper.createSdDir(1024 * MB_IN_BYTES, fullId, "none",
+ android.os.Process.myUid(), true);
Log.d(TAG,PackageHelper.getSdDir(fullId));
PackageHelper.unMountSdDir(fullId);
diff --git a/core/tests/coretests/src/android/os/storage/AsecTests.java b/core/tests/coretests/src/android/os/storage/AsecTests.java
index abb8eae..4f724fe 100644
--- a/core/tests/coretests/src/android/os/storage/AsecTests.java
+++ b/core/tests/coretests/src/android/os/storage/AsecTests.java
@@ -90,7 +90,7 @@
String fullId = SECURE_CONTAINER_PREFIX + localId;
IMountService ms = getMs();
- return ms.mountSecureContainer(fullId, key, android.os.Process.myUid());
+ return ms.mountSecureContainer(fullId, key, android.os.Process.myUid(), true);
}
private int renameContainer(String localId1, String localId2) throws Exception {
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 4dcbc40..ba22550 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -155,7 +155,7 @@
@Override
public void draw(Canvas canvas) {
mAnimatedVectorState.mVectorDrawable.draw(canvas);
- if (isRunning()) {
+ if (isStarted()) {
invalidateSelf();
}
}
@@ -361,13 +361,25 @@
return false;
}
+ private boolean isStarted() {
+ final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
+ final int size = animators.size();
+ for (int i = 0; i < size; i++) {
+ final Animator animator = animators.get(i);
+ if (animator.isStarted()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public void start() {
final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
final int size = animators.size();
for (int i = 0; i < size; i++) {
final Animator animator = animators.get(i);
- if (!animator.isRunning()) {
+ if (!animator.isStarted()) {
animator.start();
}
}
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/Interpolator.cpp b/libs/hwui/Interpolator.cpp
index fc0e8a0..ff8ff73 100644
--- a/libs/hwui/Interpolator.cpp
+++ b/libs/hwui/Interpolator.cpp
@@ -110,7 +110,7 @@
weight = modff(lutpos, &ipart);
int i1 = (int) ipart;
- int i2 = MathUtils::min(i1 + 1, mSize - 1);
+ int i2 = MathUtils::min(i1 + 1, (int) mSize - 1);
LOG_ALWAYS_FATAL_IF(i1 < 0 || i2 < 0, "negatives in interpolation!"
" i1=%d, i2=%d, input=%f, lutpos=%f, size=%zu, values=%p, ipart=%f, weight=%f",
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/ShadowTessellator.cpp b/libs/hwui/ShadowTessellator.cpp
index e71439d..6cff815 100644
--- a/libs/hwui/ShadowTessellator.cpp
+++ b/libs/hwui/ShadowTessellator.cpp
@@ -29,11 +29,6 @@
namespace android {
namespace uirenderer {
-template<typename T>
-static inline T max(T a, T b) {
- return a > b ? a : b;
-}
-
void ShadowTessellator::tessellateAmbientShadow(bool isCasterOpaque,
const Vector3* casterPolygon, int casterVertexCount,
const Vector3& centroid3d, const Rect& casterBounds,
@@ -66,7 +61,7 @@
}
void ShadowTessellator::tessellateSpotShadow(bool isCasterOpaque,
- const Vector3* casterPolygon, int casterVertexCount,
+ const Vector3* casterPolygon, int casterVertexCount, const Vector3& casterCentroid,
const mat4& receiverTransform, const Vector3& lightCenter, int lightRadius,
const Rect& casterBounds, const Rect& localClip, VertexBuffer& shadowVertexBuffer) {
ATRACE_CALL();
@@ -109,9 +104,9 @@
return;
}
- SpotShadow::createSpotShadow(isCasterOpaque,
- casterPolygon, casterVertexCount, adjustedLightCenter, lightRadius,
- lightVertexCount, shadowVertexBuffer);
+ SpotShadow::createSpotShadow(isCasterOpaque, adjustedLightCenter, lightRadius,
+ casterPolygon, casterVertexCount, casterCentroid, shadowVertexBuffer);
+
#if DEBUG_SHADOW
if(shadowVertexBuffer.getVertexCount() <= 0) {
ALOGD("Spot shadow generation failed %d", shadowVertexBuffer.getVertexCount());
@@ -180,6 +175,18 @@
return centroid;
}
+// Make sure p1 -> p2 is going CW around the poly.
+Vector2 ShadowTessellator::calculateNormal(const Vector2& p1, const Vector2& p2) {
+ Vector2 result = p2 - p1;
+ if (result.x != 0 || result.y != 0) {
+ result.normalize();
+ // Calculate the normal , which is CCW 90 rotate to the delta.
+ float tempy = result.y;
+ result.y = result.x;
+ result.x = -tempy;
+ }
+ return result;
+}
/**
* Test whether the polygon is order in clockwise.
*
diff --git a/libs/hwui/ShadowTessellator.h b/libs/hwui/ShadowTessellator.h
index cb65df5..141dff6 100644
--- a/libs/hwui/ShadowTessellator.h
+++ b/libs/hwui/ShadowTessellator.h
@@ -72,7 +72,7 @@
const Rect& localClip, float maxZ, VertexBuffer& shadowVertexBuffer);
static void tessellateSpotShadow(bool isCasterOpaque,
- const Vector3* casterPolygon, int casterVertexCount,
+ const Vector3* casterPolygon, int casterVertexCount, const Vector3& casterCentroid,
const mat4& receiverTransform, const Vector3& lightCenter, int lightRadius,
const Rect& casterBounds, const Rect& localClip, VertexBuffer& shadowVertexBuffer);
@@ -82,6 +82,7 @@
static bool isClockwise(const Vector2* polygon, int len);
+ static Vector2 calculateNormal(const Vector2& p1, const Vector2& p2);
/**
* Determine whether the path is clockwise, using the control points.
*
diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp
index d726538..cb20a0b 100644
--- a/libs/hwui/SpotShadow.cpp
+++ b/libs/hwui/SpotShadow.cpp
@@ -17,6 +17,9 @@
#define LOG_TAG "OpenGLRenderer"
#define SHADOW_SHRINK_SCALE 0.1f
+#define CASTER_Z_CAP_RATIO 0.95f
+#define FAKE_UMBRA_SIZE_RATIO 0.01f
+#define OCLLUDED_UMBRA_SHRINK_FACTOR 0.95f
#include <math.h>
#include <stdlib.h>
@@ -25,13 +28,29 @@
#include "ShadowTessellator.h"
#include "SpotShadow.h"
#include "Vertex.h"
+#include "utils/MathUtils.h"
+// TODO: After we settle down the new algorithm, we can remove the old one and
+// its utility functions.
+// Right now, we still need to keep it for comparison purpose and future expansion.
namespace android {
namespace uirenderer {
static const double EPSILON = 1e-7;
/**
+ * For each polygon's vertex, the light center will project it to the receiver
+ * as one of the outline vertex.
+ * For each outline vertex, we need to store the position and normal.
+ * Normal here is defined against the edge by the current vertex and the next vertex.
+ */
+struct OutlineData {
+ Vector2 position;
+ Vector2 normal;
+ float radius;
+};
+
+/**
* Calculate the angle between and x and a y coordinate.
* The atan2 range from -PI to PI.
*/
@@ -500,12 +519,13 @@
* empty strip if error.
*
*/
-void SpotShadow::createSpotShadow(bool isCasterOpaque, const Vector3* poly,
+
+void SpotShadow::createSpotShadow_old(bool isCasterOpaque, const Vector3* poly,
int polyLength, const Vector3& lightCenter, float lightSize,
int lightVertexCount, VertexBuffer& retStrips) {
Vector3 light[lightVertexCount * 3];
computeLightPolygon(lightVertexCount, lightCenter, lightSize, light);
- computeSpotShadow(isCasterOpaque, light, lightVertexCount, lightCenter, poly,
+ computeSpotShadow_old(isCasterOpaque, light, lightVertexCount, lightCenter, poly,
polyLength, retStrips);
}
@@ -519,9 +539,9 @@
* @param shadowTriangleStrip return an (x,y,alpha) triangle strip representing the shadow. Return
* empty strip if error.
*/
-void SpotShadow::computeSpotShadow(bool isCasterOpaque, const Vector3* lightPoly,
- int lightPolyLength, const Vector3& lightCenter, const Vector3* poly,
- int polyLength, VertexBuffer& shadowTriangleStrip) {
+void SpotShadow::computeSpotShadow_old(bool isCasterOpaque, const Vector3* lightPoly,
+ int lightPolyLength, const Vector3& lightCenter, const Vector3* poly, int polyLength,
+ VertexBuffer& shadowTriangleStrip) {
// Point clouds for all the shadowed vertices
Vector2 shadowRegion[lightPolyLength * polyLength];
// Shadow polygon from one point light.
@@ -616,10 +636,198 @@
umbraLength = polyLength;
}
- generateTriangleStrip(isCasterOpaque, penumbra, penumbraLength, umbra,
+ generateTriangleStrip(isCasterOpaque, 1.0, penumbra, penumbraLength, umbra,
umbraLength, poly, polyLength, shadowTriangleStrip);
}
+float SpotShadow::projectCasterToOutline(Vector2& outline,
+ const Vector3& lightCenter, const Vector3& polyVertex) {
+ float lightToPolyZ = lightCenter.z - polyVertex.z;
+ float ratioZ = CASTER_Z_CAP_RATIO;
+ if (lightToPolyZ != 0) {
+ // If any caster's vertex is almost above the light, we just keep it as 95%
+ // of the height of the light.
+ ratioZ = MathUtils::min(polyVertex.z / lightToPolyZ, CASTER_Z_CAP_RATIO);
+ }
+
+ outline.x = polyVertex.x - ratioZ * (lightCenter.x - polyVertex.x);
+ outline.y = polyVertex.y - ratioZ * (lightCenter.y - polyVertex.y);
+ return ratioZ;
+}
+
+/**
+ * Generate the shadow spot light of shape lightPoly and a object poly
+ *
+ * @param isCasterOpaque whether the caster is opaque
+ * @param lightCenter the center of the light
+ * @param lightSize the radius of the light
+ * @param poly x,y,z vertexes of a convex polygon that occludes the light source
+ * @param polyLength number of vertexes of the occluding polygon
+ * @param shadowTriangleStrip return an (x,y,alpha) triangle strip representing the shadow. Return
+ * empty strip if error.
+ */
+void SpotShadow::createSpotShadow(bool isCasterOpaque, const Vector3& lightCenter,
+ float lightSize, const Vector3* poly, int polyLength, const Vector3& polyCentroid,
+ VertexBuffer& shadowTriangleStrip) {
+ OutlineData outlineData[polyLength];
+ Vector2 outlineCentroid;
+ // Calculate the projected outline for each polygon's vertices from the light center.
+ //
+ // O Light
+ // /
+ // /
+ // . Polygon vertex
+ // /
+ // /
+ // O Outline vertices
+ //
+ // Ratio = (Poly - Outline) / (Light - Poly)
+ // Outline.x = Poly.x - Ratio * (Light.x - Poly.x)
+ // Outline's radius / Light's radius = Ratio
+
+ // Compute the last outline vertex to make sure we can get the normal and outline
+ // in one single loop.
+ projectCasterToOutline(outlineData[polyLength - 1].position, lightCenter,
+ poly[polyLength - 1]);
+
+ // Take the outline's polygon, calculate the normal for each outline edge.
+ int currentNormalIndex = polyLength - 1;
+ int nextNormalIndex = 0;
+
+ for (int i = 0; i < polyLength; i++) {
+ float ratioZ = projectCasterToOutline(outlineData[i].position,
+ lightCenter, poly[i]);
+ outlineData[i].radius = ratioZ * lightSize;
+
+ outlineData[currentNormalIndex].normal = ShadowTessellator::calculateNormal(
+ outlineData[currentNormalIndex].position,
+ outlineData[nextNormalIndex].position);
+ currentNormalIndex = (currentNormalIndex + 1) % polyLength;
+ nextNormalIndex++;
+ }
+
+ projectCasterToOutline(outlineCentroid, lightCenter, polyCentroid);
+
+ int penumbraIndex = 0;
+ int penumbraLength = polyLength * 3;
+ Vector2 penumbra[penumbraLength];
+
+ Vector2 umbra[polyLength];
+ float distOutline = 0;
+ float ratioVI = 0;
+
+ bool hasValidUmbra = true;
+ // We need the maxRatioVI to decrease the spot shadow strength accordingly.
+ float maxRaitoVI = 1.0;
+
+ for (int i = 0; i < polyLength; i++) {
+ // Generate all the penumbra's vertices only using the (outline vertex + normal * radius)
+ // There is no guarantee that the penumbra is still convex, but for
+ // each outline vertex, it will connect to all its corresponding penumbra vertices as
+ // triangle fans. And for neighber penumbra vertex, it will be a trapezoid.
+ //
+ // Penumbra Vertices marked as Pi
+ // Outline Vertices marked as Vi
+ // (P3)
+ // (P2) | ' (P4)
+ // (P1)' | | '
+ // ' | | '
+ // (P0) ------------------------------------------------(P5)
+ // | (V0) |(V1)
+ // | |
+ // | |
+ // | |
+ // | |
+ // | |
+ // | |
+ // | |
+ // | |
+ // (V3)-----------------------------------(V2)
+ int preNormalIndex = (i + polyLength - 1) % polyLength;
+ penumbra[penumbraIndex++] = outlineData[i].position +
+ outlineData[preNormalIndex].normal * outlineData[i].radius;
+
+ int currentNormalIndex = i;
+ // (TODO) Depending on how roundness we want for each corner, we can subdivide
+ // further here and/or introduce some heuristic to decide how much the
+ // subdivision should be.
+ Vector2 avgNormal =
+ (outlineData[preNormalIndex].normal + outlineData[currentNormalIndex].normal) / 2;
+
+ penumbra[penumbraIndex++] = outlineData[i].position +
+ avgNormal * outlineData[i].radius;
+
+ penumbra[penumbraIndex++] = outlineData[i].position +
+ outlineData[currentNormalIndex].normal * outlineData[i].radius;
+
+ // Compute the umbra by the intersection from the outline's centroid!
+ //
+ // (V) ------------------------------------
+ // | ' |
+ // | ' |
+ // | ' (I) |
+ // | ' |
+ // | ' (C) |
+ // | |
+ // | |
+ // | |
+ // | |
+ // ------------------------------------
+ //
+ // Connect a line b/t the outline vertex (V) and the centroid (C), it will
+ // intersect with the outline vertex's circle at point (I).
+ // Now, ratioVI = VI / VC, ratioIC = IC / VC
+ // Then the intersetion point can be computed as Ixy = Vxy * ratioIC + Cxy * ratioVI;
+ //
+ // When one of the outline circle cover the the outline centroid, (like I is
+ // on the other side of C), there is no real umbra any more, so we just fake
+ // a small area around the centroid as the umbra, and tune down the spot
+ // shadow's umbra strength to simulate the effect the whole shadow will
+ // become lighter in this case.
+ // The ratio can be simulated by using the inverse of maximum of ratioVI for
+ // all (V).
+ distOutline = (outlineData[i].position - outlineCentroid).length();
+ if (distOutline == 0) {
+ // If the outline has 0 area, then there is no spot shadow anyway.
+ ALOGW("Outline has 0 area, no spot shadow!");
+ return;
+ }
+ ratioVI = outlineData[i].radius / distOutline;
+ if (ratioVI >= 1.0) {
+ maxRaitoVI = ratioVI;
+ hasValidUmbra = false;
+ }
+ // When we know we don't have valid umbra, don't bother to compute the
+ // values below. But we can't skip the loop yet since we want to know the
+ // maximum ratio.
+ if (hasValidUmbra) {
+ float ratioIC = (distOutline - outlineData[i].radius) / distOutline;
+ umbra[i] = outlineData[i].position * ratioIC + outlineCentroid * ratioVI;
+ }
+ }
+
+ float shadowStrengthScale = 1.0;
+ if (!hasValidUmbra) {
+ ALOGW("The object is too close to the light or too small, no real umbra!");
+ for (int i = 0; i < polyLength; i++) {
+ umbra[i] = outlineData[i].position * FAKE_UMBRA_SIZE_RATIO +
+ outlineCentroid * (1 - FAKE_UMBRA_SIZE_RATIO);
+ }
+ shadowStrengthScale = 1.0 / maxRaitoVI;
+ }
+
+#if DEBUG_SHADOW
+ dumpPolygon(poly, polyLength, "input poly");
+ dumpPolygon(outline, polyLength, "outline");
+ dumpPolygon(penumbra, penumbraLength, "penumbra");
+ dumpPolygon(umbra, polyLength, "umbra");
+ ALOGD("hasValidUmbra is %d and shadowStrengthScale is %f", hasValidUmbra, shadowStrengthScale);
+#endif
+
+ generateTriangleStrip(isCasterOpaque, shadowStrengthScale, penumbra,
+ penumbraLength, umbra, polyLength, poly, polyLength, shadowTriangleStrip);
+}
+
/**
* Converts a polygon specified with CW vertices into an array of distance-from-centroid values.
*
@@ -697,7 +905,6 @@
occludedUmbra, polyLength);
}
-#define OCLLUDED_UMBRA_SHRINK_FACTOR 0.95f
/**
* Generate a triangle strip given two convex polygons
*
@@ -708,8 +915,8 @@
* @param shadowTriangleStrip return an (x,y,alpha) triangle strip representing the shadow. Return
* empty strip if error.
**/
-void SpotShadow::generateTriangleStrip(bool isCasterOpaque, const Vector2* penumbra,
- int penumbraLength, const Vector2* umbra, int umbraLength,
+void SpotShadow::generateTriangleStrip(bool isCasterOpaque, float shadowStrengthScale,
+ const Vector2* penumbra, int penumbraLength, const Vector2* umbra, int umbraLength,
const Vector3* poly, int polyLength, VertexBuffer& shadowTriangleStrip) {
const int rays = SHADOW_RAY_COUNT;
const int size = 2 * rays;
@@ -750,13 +957,12 @@
}
}
}
-
AlphaVertex* shadowVertices =
shadowTriangleStrip.alloc<AlphaVertex>(SHADOW_VERTEX_COUNT);
// NOTE: Shadow alpha values are transformed when stored in alphavertices,
// so that they can be consumed directly by gFS_Main_ApplyVertexAlphaShadowInterp
- float transformedMaxAlpha = M_PI;
+ float transformedMaxAlpha = M_PI * shadowStrengthScale;
// Calculate the vertices (x, y, alpha) in the shadow area.
AlphaVertex centroidXYA;
@@ -789,7 +995,6 @@
shadowVertices[2 * rays + rayIndex] = centroidXYA;
}
}
-
shadowTriangleStrip.setMode(VertexBuffer::kTwoPolyRingShadow);
shadowTriangleStrip.computeBounds<AlphaVertex>();
}
@@ -844,7 +1049,16 @@
/**
* For debug purpose, when things go wrong, dump the whole polygon data.
*/
-static void dumpPolygon(const Vector2* poly, int polyLength, const char* polyName) {
+void SpotShadow::dumpPolygon(const Vector2* poly, int polyLength, const char* polyName) {
+ for (int i = 0; i < polyLength; i++) {
+ ALOGD("polygon %s i %d x %f y %f", polyName, i, poly[i].x, poly[i].y);
+ }
+}
+
+/**
+ * For debug purpose, when things go wrong, dump the whole polygon data.
+ */
+void SpotShadow::dumpPolygon(const Vector3* poly, int polyLength, const char* polyName) {
for (int i = 0; i < polyLength; i++) {
ALOGD("polygon %s i %d x %f y %f", polyName, i, poly[i].x, poly[i].y);
}
@@ -885,8 +1099,8 @@
const Vector2* poly2, int poly2Length,
const Vector2* intersection, int intersectionLength) {
// Find the min and max of x and y.
- Vector2 lowerBound(FLT_MAX, FLT_MAX);
- Vector2 upperBound(-FLT_MAX, -FLT_MAX);
+ Vector2 lowerBound = {FLT_MAX, FLT_MAX};
+ Vector2 upperBound = {-FLT_MAX, -FLT_MAX};
for (int i = 0; i < poly1Length; i++) {
updateBound(poly1[i], lowerBound, upperBound);
}
diff --git a/libs/hwui/SpotShadow.h b/libs/hwui/SpotShadow.h
index d65ea89..355be8d 100644
--- a/libs/hwui/SpotShadow.h
+++ b/libs/hwui/SpotShadow.h
@@ -26,16 +26,22 @@
class SpotShadow {
public:
- static void createSpotShadow(bool isCasterOpaque, const Vector3* poly,
+ static void createSpotShadow_old(bool isCasterOpaque, const Vector3* poly,
int polyLength, const Vector3& lightCenter, float lightSize,
int lightVertexCount, VertexBuffer& retStrips);
+ static void createSpotShadow(bool isCasterOpaque, const Vector3& lightCenter,
+ float lightSize, const Vector3* poly, int polyLength,
+ const Vector3& polyCentroid, VertexBuffer& retstrips);
private:
+ static float projectCasterToOutline(Vector2& outline,
+ const Vector3& lightCenter, const Vector3& polyVertex);
static int calculateOccludedUmbra(const Vector2* umbra, int umbraLength,
const Vector3* poly, int polyLength, Vector2* occludedUmbra);
- static void computeSpotShadow(bool isCasterOpaque, const Vector3* lightPoly,
+
+ static void computeSpotShadow_old(bool isCasterOpaque, const Vector3* lightPoly,
int lightPolyLength, const Vector3& lightCenter, const Vector3* poly,
- int polyLength, VertexBuffer& retstrips);
+ int polyLength, VertexBuffer& shadowTriangleStrip);
static void computeLightPolygon(int points, const Vector3& lightCenter,
float size, Vector3* ret);
@@ -60,8 +66,8 @@
static inline bool lineIntersection(double x1, double y1, double x2, double y2,
double x3, double y3, double x4, double y4, Vector2& ret);
- static void generateTriangleStrip(bool isCasterOpaque, const Vector2* penumbra,
- int penumbraLength, const Vector2* umbra, int umbraLength,
+ static void generateTriangleStrip(bool isCasterOpaque, float shadowStrengthScale,
+ const Vector2* penumbra, int penumbraLength, const Vector2* umbra, int umbraLength,
const Vector3* poly, int polyLength, VertexBuffer& retstrips);
#if DEBUG_SHADOW
@@ -72,6 +78,8 @@
const Vector2* poly2, int poly2Length,
const Vector2* intersection, int intersectionLength);
static void updateBound(const Vector2 inVector, Vector2& lowerBound, Vector2& upperBound );
+ static void dumpPolygon(const Vector2* poly, int polyLength, const char* polyName);
+ static void dumpPolygon(const Vector3* poly, int polyLength, const char* polyName);
#endif
}; // SpotShadow
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/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp
index 0a9aeb8..9e62f36 100644
--- a/libs/hwui/TessellationCache.cpp
+++ b/libs/hwui/TessellationCache.cpp
@@ -267,7 +267,7 @@
casterBounds, *localClip, maxZ, ambientBuffer);
ShadowTessellator::tessellateSpotShadow(
- isCasterOpaque, casterPolygon, casterVertexCount,
+ isCasterOpaque, casterPolygon, casterVertexCount, centroid3d,
*drawTransform, lightCenter, lightRadius, casterBounds, *localClip,
spotBuffer);
}
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 5922135..4bf5a8a 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -257,6 +257,7 @@
info.frameTimeMs = mRenderThread.timeLord().frameTimeMs();
info.damageAccumulator = &mDamageAccumulator;
info.renderer = mCanvas;
+ info.runAnimations = false;
node->prepareTree(info);
SkRect ignore;
mDamageAccumulator.finish(&ignore);
diff --git a/libs/hwui/utils/MathUtils.h b/libs/hwui/utils/MathUtils.h
index 6fb0411..00448b8 100644
--- a/libs/hwui/utils/MathUtils.h
+++ b/libs/hwui/utils/MathUtils.h
@@ -66,11 +66,13 @@
return isZero(valueA - valueB);
}
- inline static int max(int a, int b) {
+ template<typename T>
+ static inline T max(T a, T b) {
return a > b ? a : b;
}
- inline static int min(int a, int b) {
+ template<typename T>
+ static inline T min(T a, T b) {
return a < b ? a : b;
}
diff --git a/libs/storage/IMountService.cpp b/libs/storage/IMountService.cpp
index 5701678..621de18 100644
--- a/libs/storage/IMountService.cpp
+++ b/libs/storage/IMountService.cpp
@@ -295,6 +295,8 @@
data.writeString16(id);
data.writeString16(key);
data.writeInt32(ownerUid);
+ // Assume read-only
+ data.writeInt32(1);
if (remote()->transact(TRANSACTION_mountSecureContainer, data, &reply) != NO_ERROR) {
ALOGD("mountSecureContainer couldn't call remote");
return -1;
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/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/tv/TvContentRating.java b/media/java/android/media/tv/TvContentRating.java
index c4a81cc..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,19 +25,22 @@
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
* <rating-system-definitions xmlns:android="http://schemas.android.com/apk/res/android"
@@ -118,24 +120,36 @@
* </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>
@@ -316,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>
@@ -328,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>
@@ -1401,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>
@@ -1518,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) {
@@ -1541,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) {
@@ -1568,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) {
@@ -1588,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) {
@@ -1619,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() {
@@ -1644,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/TvContract.java b/media/java/android/media/tv/TvContract.java
index bdceb24..00c7ad4 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -686,6 +686,7 @@
* </p>
* @hide
*/
+ @SystemApi
public static final String COLUMN_BROWSABLE = "browsable";
/**
@@ -717,6 +718,7 @@
* </p>
* @hide
*/
+ @SystemApi
public static final String COLUMN_LOCKED = "locked";
/**
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/packages/BackupRestoreConfirmation/res/values/strings.xml b/packages/BackupRestoreConfirmation/res/values/strings.xml
index 5c90fd0..3fb3fd4 100644
--- a/packages/BackupRestoreConfirmation/res/values/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values/strings.xml
@@ -44,6 +44,8 @@
<string name="backup_enc_password_text">Please enter a password to use for encrypting the full backup data. If this is left blank, your current backup password will be used:</string>
<!-- Text for message to user that they may optionally supply an encryption password to use for a full backup operation. -->
<string name="backup_enc_password_optional">If you wish to encrypt the full backup data, enter a password below:</string>
+ <!-- Text for message to user that they must supply an encryption password to use for a full backup operation because their phone is locked. -->
+ <string name="backup_enc_password_required">Since your device is encrypted, you are required to encrypt your backup. Please enter a password below:</string>
<!-- Text for message to user when performing a full restore operation, explaining that they must enter the password originally used to encrypt the full backup data. -->
<string name="restore_enc_password_text">If the restore data is encrypted, please enter the password below:</string>
diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
index 82ac8cb..c2bb90c 100644
--- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
+++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
@@ -28,6 +28,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.storage.IMountService;
+import android.os.storage.StorageManager;
import android.util.Log;
import android.util.Slog;
import android.view.View;
@@ -182,25 +183,14 @@
// We vary the password prompt depending on whether one is predefined, and whether
// the device is encrypted.
mIsEncrypted = deviceIsEncrypted();
- if (mIsEncrypted) {
- Log.d(TAG, "Device is encrypted: requiring encryption pw");
- TextView pwPrompt = (TextView) findViewById(R.id.password_desc);
- // this password is mandatory; we hide the other options during backup
- if (layoutId == R.layout.confirm_backup) {
- pwPrompt.setText(R.string.device_encryption_backup_text);
- TextView tv = (TextView) findViewById(R.id.enc_password);
- tv.setVisibility(View.GONE);
- tv = (TextView) findViewById(R.id.enc_password_desc);
- tv.setVisibility(View.GONE);
- } else {
- pwPrompt.setText(R.string.device_encryption_restore_text);
- }
- } else if (!haveBackupPassword()) {
+ if (!haveBackupPassword()) {
curPwDesc.setVisibility(View.GONE);
mCurPassword.setVisibility(View.GONE);
if (layoutId == R.layout.confirm_backup) {
TextView encPwDesc = (TextView) findViewById(R.id.enc_password_desc);
- encPwDesc.setText(R.string.backup_enc_password_optional);
+ encPwDesc.setText(mIsEncrypted
+ ? R.string.backup_enc_password_required
+ : R.string.backup_enc_password_optional);
}
}
@@ -246,8 +236,7 @@
mDidAcknowledge = true;
try {
- CharSequence encPassword = (mIsEncrypted)
- ? mCurPassword.getText() : mEncPassword.getText();
+ CharSequence encPassword = mEncPassword.getText();
mBackupManager.acknowledgeFullBackupOrRestore(mToken,
allow,
String.valueOf(mCurPassword.getText()),
@@ -261,7 +250,10 @@
boolean deviceIsEncrypted() {
try {
- return (mMountService.getEncryptionState() != IMountService.ENCRYPTION_STATE_NONE);
+ return mMountService.getEncryptionState()
+ != IMountService.ENCRYPTION_STATE_NONE
+ && mMountService.getPasswordType()
+ != StorageManager.CRYPT_TYPE_DEFAULT;
} catch (Exception e) {
// If we can't talk to the mount service we have a serious problem; fail
// "secure" i.e. assuming that the device is encrypted.
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index fae30e5..1f28324 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -16,7 +16,7 @@
package com.android.defcontainer;
-import static android.net.TrafficStats.MB_IN_BYTES;
+import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
import android.app.IntentService;
import android.content.Context;
@@ -67,8 +67,6 @@
public class DefaultContainerService extends IntentService {
private static final String TAG = "DefContainer";
- private static final String LIB_DIR_NAME = "lib";
-
// TODO: migrate native code unpacking to always be a derivative work
private IMediaContainerService.Stub mBinder = new IMediaContainerService.Stub() {
@@ -168,7 +166,7 @@
final long sizeBytes;
try {
pkg = PackageParser.parsePackageLite(packageFile, 0);
- sizeBytes = calculateInstalledSizeInner(pkg, isForwardLocked, abiOverride);
+ sizeBytes = PackageHelper.calculateInstalledSize(pkg, isForwardLocked, abiOverride);
} catch (PackageParserException | IOException e) {
Slog.w(TAG, "Failed to parse package at " + packagePath + ": " + e);
@@ -253,7 +251,7 @@
final PackageParser.PackageLite pkg;
try {
pkg = PackageParser.parsePackageLite(packageFile, 0);
- return calculateInstalledSizeInner(pkg, isForwardLocked, abiOverride);
+ return PackageHelper.calculateInstalledSize(pkg, isForwardLocked, abiOverride);
} catch (PackageParserException | IOException e) {
Slog.w(TAG, "Failed to calculate installed size: " + e);
return Long.MAX_VALUE;
@@ -315,13 +313,12 @@
// 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;
+ final long sizeBytes = PackageHelper.calculateInstalledSize(pkg, handle,
+ isForwardLocked, abiOverride);
// Create new container
- final String newMountPath = PackageHelper.createSdDir(sizeMb, newCid, key, Process.myUid(),
- isExternal);
+ final String newMountPath = PackageHelper.createSdDir(sizeBytes, newCid, key,
+ Process.myUid(), isExternal);
if (newMountPath == null) {
throw new IOException("Failed to create container " + newCid);
}
@@ -339,8 +336,8 @@
// Extract native code
final File libraryRoot = new File(targetDir, LIB_DIR_NAME);
- final int res = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, libraryRoot,
- abiOverride, pkg.multiArch);
+ final int res = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
+ abiOverride);
if (res != PackageManager.INSTALL_SUCCEEDED) {
throw new IOException("Failed to extract native code, res=" + res);
}
@@ -415,35 +412,4 @@
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, abiOverride);
- } finally {
- IoUtils.closeQuietly(handle);
- }
- }
-
- private long calculateInstalledSizeInner(PackageLite pkg, NativeLibraryHelper.Handle handle,
- boolean isForwardLocked, String abiOverride) throws IOException {
- long sizeBytes = 0;
-
- // Include raw APKs, and possibly unpacked resources
- for (String codePath : pkg.getAllCodePaths()) {
- final File codeFile = new File(codePath);
- sizeBytes += codeFile.length();
-
- if (isForwardLocked) {
- sizeBytes += PackageHelper.extractPublicFiles(codeFile, null);
- }
- }
-
- // Include all relevant native code
- sizeBytes += NativeLibraryHelper.sumNativeBinaries(handle, abiOverride, pkg.multiArch);
-
- return sizeBytes;
- }
}
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/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
index 4ea1c77..c650a0f 100644
--- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
@@ -76,6 +76,12 @@
}
@Override
+ public void onTrustTimeout() {
+ super.onTrustTimeout();
+ Toast.makeText(this, "onTrustTimeout(): timeout expired", Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
public void onUnlockAttempt(boolean successful) {
if (getReportUnlockAttempts(this)) {
Toast.makeText(this, "onUnlockAttempt(successful=" + successful + ")",
diff --git a/packages/SystemUI/res/drawable/ic_ringer_mute.xml b/packages/SystemUI/res/drawable/ic_ringer_mute.xml
new file mode 100644
index 0000000..dee6018
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ringer_mute.xml
@@ -0,0 +1,24 @@
+<!--
+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:width="32dp"
+ android:height="32dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M23.000000,44.000000c2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000l-8.000000,0.000000C19.000000,42.200001 20.799999,44.000000 23.000000,44.000000zM36.000000,21.000000c0.000000,-6.100000 -4.300000,-11.300000 -10.000000,-12.600000L26.000000,7.000000c0.000000,-1.700000 -1.300000,-3.000000 -3.000000,-3.000000c-1.700000,0.000000 -3.000000,1.300000 -3.000000,3.000000l0.000000,1.400000c-1.000000,0.200000 -2.000000,0.600000 -2.900000,1.100000L36.000000,28.400000L36.000000,21.000000zM35.500000,38.000000l4.000000,4.000000l2.500000,-2.500000L8.500000,6.000000L6.000000,8.500000l5.800000,5.800000C10.700000,16.299999 10.000000,18.600000 10.000000,21.000000l0.000000,11.000000l-4.000000,4.000000l0.000000,2.000000L35.500000,38.000000z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml b/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml
index a291495..35414bc 100644
--- a/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml
+++ b/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml
@@ -191,7 +191,7 @@
<!-- navigation controls -->
<FrameLayout
android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
+ android:layout_height="40dp"
android:layout_weight="0" >
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
android:layout_height="@dimen/navigation_extra_key_width"
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index ca07c87..ef0c9bb 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -67,6 +67,6 @@
android:src="@drawable/ic_lock_24dp"
android:scaleType="center"
android:tint="#ffffffff"
- android:contentDescription="@string/accessibility_unlock_button" />
+ 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/volume_panel_item.xml b/packages/SystemUI/res/layout/volume_panel_item.xml
index 18b496c..85e3fb3 100644
--- a/packages/SystemUI/res/layout/volume_panel_item.xml
+++ b/packages/SystemUI/res/layout/volume_panel_item.xml
@@ -29,14 +29,30 @@
android:background="@drawable/btn_borderless_rect"
android:contentDescription="@null" />
- <SeekBar
- android:id="@+id/seekbar"
+ <FrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_weight="1"
- android:paddingBottom="0dp"
- android:paddingEnd="16dp"
- android:paddingStart="8dp"
- android:paddingTop="0dip" />
+ android:layout_weight="1" >
+ <TextView
+ android:id="@+id/suppressor"
+ android:visibility="gone"
+ android:textAppearance="@style/TextAppearance.QS.VolumeSuppressor"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <SeekBar
+ android:id="@+id/seekbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="0dp"
+ android:paddingEnd="16dp"
+ android:paddingStart="8dp"
+ android:paddingTop="0dp" />
+
+ </FrameLayout>
</LinearLayout>
\ No newline at end of file
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/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/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 8f05f7b..120af1d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -213,8 +213,6 @@
<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>
- <!-- Content description of the unlock button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_unlock_button">Unlock</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] -->
@@ -222,6 +220,17 @@
<!-- 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>
<!-- Content description of the compatibility zoom button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -858,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/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 48a031a..8c1ac9f 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -141,6 +141,11 @@
<item name="android:textColor">@color/system_accent_color</item>
</style>
+ <style name="TextAppearance.QS.VolumeSuppressor">
+ <item name="android:textSize">14sp</item>
+ <item name="android:textColor">@color/qs_tile_text</item>
+ </style>
+
<style name="TextAppearance.QS.DetailButton">
<item name="android:textSize">14sp</item>
<item name="android:textAllCaps">true</item>
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/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index c1fd509..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
@@ -317,7 +325,9 @@
mDetail.bringToFront();
mDetailContent.addView(r.detailView);
setDetailRecord(r);
+ listener = mHideGridContentWhenDone;
} else {
+ setGridContentVisibility(true);
listener = mTeardownDetailWhenDone;
fireScanStateChanged(false);
}
@@ -325,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);
@@ -448,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);
}
}
}
@@ -473,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/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/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 63c880f..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
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 b12c6c1..4fc2ee4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -87,11 +87,7 @@
@Override
protected void handleSecondaryClick() {
- if (!mState.enabled) {
- mController.setWifiEnabled(true);
- mState.enabled = true;
- }
- showDetail(true);
+ mHost.startSettingsActivity(WIFI_SETTINGS);
}
@Override
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 b0fd829..57df1d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1185,8 +1185,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(),
@@ -1205,14 +1205,14 @@
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);
}
}
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 44d8d23..cb2d40a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -377,11 +377,20 @@
boolean trustManaged = mUnlockMethodCache.isTrustManaged();
mTrustDrawable.setTrustManaged(trustManaged);
- // TODO: Update content description depending on state
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() {
return mPhoneImageView;
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 b3042b9..7158ba1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -752,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) {
@@ -2131,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;
@@ -2305,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();
@@ -3920,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();
@@ -3970,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..938d888 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);
}
@@ -542,7 +545,13 @@
target.avatarScale = mMultiUserAvatar.getScaleX();
target.avatarX = mMultiUserSwitch.getLeft() + mMultiUserAvatar.getLeft();
target.avatarY = mMultiUserSwitch.getTop() + mMultiUserAvatar.getTop();
- target.batteryX = mSystemIconsSuperContainer.getLeft() + mSystemIconsContainer.getRight();
+ if (getLayoutDirection() == LAYOUT_DIRECTION_LTR) {
+ target.batteryX = mSystemIconsSuperContainer.getLeft()
+ + mSystemIconsContainer.getRight();
+ } else {
+ target.batteryX = mSystemIconsSuperContainer.getLeft()
+ + mSystemIconsContainer.getLeft();
+ }
target.batteryY = mSystemIconsSuperContainer.getTop() + mSystemIconsContainer.getTop();
target.batteryLevelAlpha = getAlphaForVisibility(mBatteryLevel);
target.settingsAlpha = getAlphaForVisibility(mSettingsButton);
@@ -579,11 +588,20 @@
mMultiUserAvatar.setScaleY(values.avatarScale);
mMultiUserAvatar.setX(values.avatarX - mMultiUserSwitch.getLeft());
mMultiUserAvatar.setY(values.avatarY - mMultiUserSwitch.getTop());
- mSystemIconsSuperContainer.setX(values.batteryX - mSystemIconsContainer.getRight());
+ if (getLayoutDirection() == LAYOUT_DIRECTION_LTR) {
+ mSystemIconsSuperContainer.setX(values.batteryX - mSystemIconsContainer.getRight());
+ } else {
+ mSystemIconsSuperContainer.setX(values.batteryX - mSystemIconsContainer.getLeft());
+ }
mSystemIconsSuperContainer.setY(values.batteryY - mSystemIconsContainer.getTop());
if (mSignalCluster != null && mExpanded) {
- mSignalCluster.setX(mSystemIconsSuperContainer.getX()
- - mSignalCluster.getWidth());
+ if (getLayoutDirection() == LAYOUT_DIRECTION_LTR) {
+ mSignalCluster.setX(mSystemIconsSuperContainer.getX()
+ - mSignalCluster.getWidth());
+ } else {
+ mSignalCluster.setX(mSystemIconsSuperContainer.getX()
+ + mSystemIconsSuperContainer.getWidth());
+ }
mSignalCluster.setY(
mSystemIconsSuperContainer.getY() + mSystemIconsSuperContainer.getHeight()/2
- mSignalCluster.getHeight()/2);
@@ -716,6 +734,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 +760,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/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index ae0291b..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,11 +17,11 @@
import android.app.admin.DevicePolicyManager;
import android.content.Context;
-import android.content.Intent;
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;
@@ -45,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(
@@ -52,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;
@@ -69,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);
}
@@ -86,10 +88,7 @@
@Override
public boolean isVpnEnabled() {
- // TODO: Remove once using NetworkCallback for updates.
- updateState();
-
- return mIsVpnEnabled;
+ return mCurrentVpnNetworkId != NO_NETWORK;
}
@Override
@@ -138,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();
@@ -148,9 +155,6 @@
try {
mVpnConfig = mConnectivityService.getVpnConfig();
- // TODO: Remove once using NetworkCallback for updates.
- mIsVpnEnabled = mVpnConfig != null;
-
if (mVpnConfig != null && !mVpnConfig.legacy) {
mVpnName = VpnConfig.getVpnLabel(mContext, mVpnConfig.user).toString();
}
@@ -160,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..adb71e7 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);
}
}
@@ -244,7 +246,6 @@
private void switchToUserId(int id) {
try {
- WindowManagerGlobal.getWindowManagerService().lockNow(null);
ActivityManagerNative.getDefault().switchUser(id);
} catch (RemoteException e) {
Log.e(TAG, "Couldn't switch user.", e);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
index 7d102ba..600b750 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.policy;
+import android.content.ComponentName;
import android.service.notification.Condition;
public interface ZenModeController {
@@ -29,6 +30,7 @@
long getNextAlarm();
void setUserId(int userId);
boolean isZenAvailable();
+ ComponentName getEffectsSuppressor();
public static class Callback {
public void onZenChanged(int zen) {}
@@ -36,5 +38,6 @@
public void onConditionsChanged(Condition[] conditions) {}
public void onNextAlarmChanged() {}
public void onZenAvailableChanged(boolean available) {}
+ public void onEffectsSupressorChanged() {}
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index b0c8f26..415eb27 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -18,7 +18,9 @@
import android.app.AlarmManager;
import android.app.INotificationManager;
+import android.app.NotificationManager;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -161,12 +163,23 @@
mSetupObserver.register();
}
+ @Override
+ public ComponentName getEffectsSuppressor() {
+ return NotificationManager.from(mContext).getEffectsSuppressor();
+ }
+
private void fireNextAlarmChanged() {
for (Callback cb : mCallbacks) {
cb.onNextAlarmChanged();
}
}
+ private void fireEffectsSuppressorChanged() {
+ for (Callback cb : mCallbacks) {
+ cb.onEffectsSupressorChanged();
+ }
+ }
+
private void fireZenChanged(int zen) {
for (Callback cb : mCallbacks) {
cb.onZenChanged(zen);
@@ -219,6 +232,9 @@
if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(intent.getAction())) {
fireNextAlarmChanged();
}
+ if (NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED.equals(intent.getAction())) {
+ fireEffectsSuppressorChanged();
+ }
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 1469d73..ce17795 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -1913,7 +1913,9 @@
@Override
public void onReset(ExpandableView view) {
- mRequestViewResizeAnimationOnLayout = true;
+ if (mIsExpanded && mAnimationsEnabled) {
+ mRequestViewResizeAnimationOnLayout = true;
+ }
mStackScrollAlgorithm.onReset(view);
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index 8a14288..f03c5eb 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -19,11 +19,15 @@
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ServiceInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -57,6 +61,7 @@
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
import com.android.internal.R;
import com.android.systemui.statusbar.phone.SystemUIDialog;
@@ -109,6 +114,7 @@
private static final int MSG_LAYOUT_DIRECTION = 12;
private static final int MSG_ZEN_MODE_AVAILABLE_CHANGED = 13;
private static final int MSG_USER_ACTIVITY = 14;
+ private static final int MSG_NOTIFICATION_EFFECTS_SUPPRESSOR_CHANGED = 15;
// Pseudo stream type for master volume
private static final int STREAM_MASTER = -100;
@@ -234,8 +240,10 @@
ViewGroup group;
ImageView icon;
SeekBar seekbarView;
+ TextView suppressorView;
int iconRes;
int iconMuteRes;
+ int iconSuppressedRes;
}
// Synchronize when accessing this
@@ -613,8 +621,12 @@
toggle(sc);
}
});
+ sc.iconSuppressedRes = com.android.systemui.R.drawable.ic_ringer_mute;
}
sc.seekbarView = (SeekBar) sc.group.findViewById(com.android.systemui.R.id.seekbar);
+ sc.suppressorView =
+ (TextView) sc.group.findViewById(com.android.systemui.R.id.suppressor);
+ sc.suppressorView.setVisibility(View.GONE);
final int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO ||
streamType == AudioSystem.STREAM_VOICE_CALL) ? 1 : 0;
sc.seekbarView.setMax(getStreamMaxVolume(streamType) + plusOne);
@@ -678,6 +690,40 @@
sc.icon.setImageResource(muted ? sc.iconMuteRes : sc.iconRes);
}
+ private void updateSliderSupressor(StreamControl sc) {
+ final ComponentName suppressor = isNotificationOrRing(sc.streamType)
+ ? mZenController.getEffectsSuppressor() : null;
+ if (suppressor == null) {
+ sc.seekbarView.setVisibility(View.VISIBLE);
+ sc.suppressorView.setVisibility(View.GONE);
+ } else {
+ sc.seekbarView.setVisibility(View.GONE);
+ sc.suppressorView.setVisibility(View.VISIBLE);
+ sc.suppressorView.setText(mContext.getString(com.android.systemui.R.string.muted_by,
+ getSuppressorCaption(suppressor)));
+ sc.icon.setImageResource(sc.iconSuppressedRes);
+ }
+ }
+
+ private String getSuppressorCaption(ComponentName suppressor) {
+ final PackageManager pm = mContext.getPackageManager();
+ try {
+ final ServiceInfo info = pm.getServiceInfo(suppressor, 0);
+ if (info != null) {
+ final CharSequence seq = info.loadLabel(pm);
+ if (seq != null) {
+ final String str = seq.toString().trim();
+ if (str.length() > 0) {
+ return str;
+ }
+ }
+ }
+ } catch (Throwable e) {
+ Log.w(TAG, "Error loading suppressor caption", e);
+ }
+ return suppressor.getPackageName();
+ }
+
/** Update the mute and progress state of a slider */
private void updateSlider(StreamControl sc) {
updateSliderProgress(sc, -1);
@@ -686,6 +732,7 @@
sc.icon.setImageDrawable(null);
updateSliderIcon(sc, muted);
updateSliderEnabled(sc, muted, false);
+ updateSliderSupressor(sc);
}
private void updateSliderEnabled(final StreamControl sc, boolean muted, boolean fixedVolume) {
@@ -1275,7 +1322,9 @@
}
break;
}
- case MSG_RINGER_MODE_CHANGED: {
+
+ case MSG_RINGER_MODE_CHANGED:
+ case MSG_NOTIFICATION_EFFECTS_SUPPRESSOR_CHANGED: {
if (isShowing()) {
updateStates();
}
@@ -1356,9 +1405,15 @@
};
private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
+ @Override
public void onZenAvailableChanged(boolean available) {
obtainMessage(MSG_ZEN_MODE_AVAILABLE_CHANGED, available ? 1 : 0, 0).sendToTarget();
}
+ @Override
+ public void onEffectsSupressorChanged() {
+ obtainMessage(MSG_NOTIFICATION_EFFECTS_SUPPRESSOR_CHANGED,
+ mZenController.getEffectsSuppressor()).sendToTarget();
+ }
};
private final MediaController.Callback mMediaControllerCb = new MediaController.Callback() {
diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml
index 1768400..03d920a 100644
--- a/packages/VpnDialogs/AndroidManifest.xml
+++ b/packages/VpnDialogs/AndroidManifest.xml
@@ -28,5 +28,14 @@
<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/layout/manage.xml b/packages/VpnDialogs/res/layout/manage.xml
new file mode 100644
index 0000000..6b504e4
--- /dev/null
+++ b/packages/VpnDialogs/res/layout/manage.xml
@@ -0,0 +1,46 @@
+<?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 84206a1..406bcc3 100644
--- a/packages/VpnDialogs/res/values/strings.xml
+++ b/packages/VpnDialogs/res/values/strings.xml
@@ -28,4 +28,26 @@
<img src="vpn_icon" />
]]> appears at the top of your screen when VPN is active.
</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>
</resources>
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
new file mode 100644
index 0000000..cc8500a
--- /dev/null
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
@@ -0,0 +1,198 @@
+/*
+ * 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.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.mTitle = getText(R.string.legacy_title);
+ } else {
+ mAlertParams.mTitle = VpnConfig.getVpnLabel(this, mConfig.user);
+ }
+ 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/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java
index 394c196..38827d0 100644
--- a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java
+++ b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java
@@ -60,15 +60,17 @@
public static boolean hasAdjustments(Context context, int userId) {
final ContentResolver cr = context.getContentResolver();
- boolean hasColorTransform = Settings.Secure.getIntForUser(
- cr, Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) == 1;
-
- if (!hasColorTransform) {
- hasColorTransform |= Settings.Secure.getIntForUser(
- cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) == 1;
+ if (Settings.Secure.getIntForUser(cr,
+ Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) != 0) {
+ return true;
}
- return hasColorTransform;
+ if (Settings.Secure.getIntForUser(cr,
+ Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0) {
+ return true;
+ }
+
+ return false;
}
/**
@@ -76,52 +78,39 @@
*/
public static void applyAdjustments(Context context, int userId) {
final ContentResolver cr = context.getContentResolver();
- float[] colorMatrix = new float[16];
- float[] outputMatrix = new float[16];
- boolean hasColorTransform = false;
+ float[] colorMatrix = null;
- Matrix.setIdentityM(colorMatrix, 0);
-
- final boolean inversionEnabled = Settings.Secure.getIntForUser(
- cr, Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) == 1;
- if (inversionEnabled) {
- final float[] inversionMatrix = INVERSION_MATRIX_VALUE_ONLY;
- Matrix.multiplyMM(outputMatrix, 0, colorMatrix, 0, inversionMatrix, 0);
-
- colorMatrix = outputMatrix;
- outputMatrix = colorMatrix;
-
- hasColorTransform = true;
+ if (Settings.Secure.getIntForUser(cr,
+ Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) != 0) {
+ colorMatrix = multiply(colorMatrix, INVERSION_MATRIX_VALUE_ONLY);
}
- final boolean daltonizerEnabled = Settings.Secure.getIntForUser(
- cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0;
- if (daltonizerEnabled) {
+ if (Settings.Secure.getIntForUser(cr,
+ Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0) {
final int daltonizerMode = Settings.Secure.getIntForUser(cr,
Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, DEFAULT_DISPLAY_DALTONIZER,
userId);
// Monochromacy isn't supported by the native Daltonizer.
if (daltonizerMode == AccessibilityManager.DALTONIZER_SIMULATE_MONOCHROMACY) {
- Matrix.multiplyMM(outputMatrix, 0, colorMatrix, 0, GRAYSCALE_MATRIX, 0);
-
- final float[] temp = colorMatrix;
- colorMatrix = outputMatrix;
- outputMatrix = temp;
-
- hasColorTransform = true;
- nativeSetDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED);
+ colorMatrix = multiply(colorMatrix, GRAYSCALE_MATRIX);
+ setDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED);
} else {
- nativeSetDaltonizerMode(daltonizerMode);
+ setDaltonizerMode(daltonizerMode);
}
} else {
- nativeSetDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED);
+ setDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED);
}
- if (hasColorTransform) {
- nativeSetColorTransform(colorMatrix);
- } else {
- nativeSetColorTransform(null);
+ setColorTransform(colorMatrix);
+ }
+
+ private static float[] multiply(float[] matrix, float[] other) {
+ if (matrix == null) {
+ return other;
}
+ float[] result = new float[16];
+ Matrix.multiplyMM(result, 0, matrix, 0, other, 0);
+ return result;
}
/**
@@ -130,7 +119,7 @@
*
* @param mode new Daltonization mode
*/
- private static void nativeSetDaltonizerMode(int mode) {
+ private static void setDaltonizerMode(int mode) {
try {
final IBinder flinger = ServiceManager.getService("SurfaceFlinger");
if (flinger != null) {
@@ -152,7 +141,7 @@
* @param m the float array that holds the transformation matrix, or null to
* disable transformation
*/
- private static void nativeSetColorTransform(float[] m) {
+ private static void setColorTransform(float[] m) {
try {
final IBinder flinger = ServiceManager.getService("SurfaceFlinger");
if (flinger != null) {
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index c6aa30b..f1e99fd 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -1539,7 +1539,7 @@
widget.views = views;
}
- scheduleNotifyUpdateAppWidgetLocked(widget);
+ scheduleNotifyUpdateAppWidgetLocked(widget, views);
}
}
@@ -1611,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;
@@ -1620,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(
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index b576324..9674ca2 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -75,6 +75,7 @@
import android.os.WorkSource;
import android.os.Environment.UserEnvironment;
import android.os.storage.IMountService;
+import android.os.storage.StorageManager;
import android.provider.Settings;
import android.system.ErrnoException;
import android.system.Os;
@@ -1064,31 +1065,19 @@
}
if (DEBUG) Slog.v(TAG, "Starting with transport " + mCurrentTransport);
- // Find transport hosts and bind to their services
+ // Find all transport hosts and bind to their services
List<ResolveInfo> hosts = mPackageManager.queryIntentServicesAsUser(
mTransportServiceIntent, 0, UserHandle.USER_OWNER);
if (DEBUG) {
Slog.v(TAG, "Found transports: " + ((hosts == null) ? "null" : hosts.size()));
}
if (hosts != null) {
- if (MORE_DEBUG) {
- for (int i = 0; i < hosts.size(); i++) {
- ServiceInfo info = hosts.get(i).serviceInfo;
- Slog.v(TAG, " " + info.packageName + "/" + info.name);
- }
- }
for (int i = 0; i < hosts.size(); i++) {
- try {
- ServiceInfo info = hosts.get(i).serviceInfo;
- PackageInfo packInfo = mPackageManager.getPackageInfo(info.packageName, 0);
- if ((packInfo.applicationInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0) {
- bindTransport(info);
- } else {
- Slog.w(TAG, "Transport package not privileged: " + info.packageName);
- }
- } catch (Exception e) {
- Slog.e(TAG, "Problem resolving transport service: " + e.getMessage());
+ final ServiceInfo transport = hosts.get(i).serviceInfo;
+ if (MORE_DEBUG) {
+ Slog.v(TAG, " " + transport.packageName + "/" + transport.name);
}
+ tryBindTransport(transport);
}
}
@@ -1442,43 +1431,7 @@
return array;
}
- // Backup password management
boolean passwordMatchesSaved(String algorithm, String candidatePw, int rounds) {
- // First, on an encrypted device we require matching the device pw
- final boolean isEncrypted;
- try {
- isEncrypted = (mMountService.getEncryptionState() !=
- IMountService.ENCRYPTION_STATE_NONE);
- if (isEncrypted) {
- if (DEBUG) {
- Slog.i(TAG, "Device encrypted; verifying against device data pw");
- }
- // 0 means the password validated
- // -2 means device not encrypted
- // Any other result is either password failure or an error condition,
- // so we refuse the match
- final int result = mMountService.verifyEncryptionPassword(candidatePw);
- if (result == 0) {
- if (MORE_DEBUG) Slog.d(TAG, "Pw verifies");
- return true;
- } else if (result != -2) {
- if (MORE_DEBUG) Slog.d(TAG, "Pw mismatch");
- return false;
- } else {
- // ...else the device is supposedly not encrypted. HOWEVER, the
- // query about the encryption state said that the device *is*
- // encrypted, so ... we may have a problem. Log it and refuse
- // the backup.
- Slog.e(TAG, "verified encryption state mismatch against query; no match allowed");
- return false;
- }
- }
- } catch (Exception e) {
- // Something went wrong talking to the mount service. This is very bad;
- // assume that we fail password validation.
- return false;
- }
-
if (mPasswordHash == null) {
// no current password case -- require that 'currentPw' be null or empty
if (candidatePw == null || "".equals(candidatePw)) {
@@ -1583,14 +1536,7 @@
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"hasBackupPassword");
- try {
- return (mMountService.getEncryptionState() != IMountService.ENCRYPTION_STATE_NONE)
- || (mPasswordHash != null && mPasswordHash.length() > 0);
- } catch (Exception e) {
- // If we can't talk to the mount service we have a serious problem; fail
- // "secure" i.e. assuming that we require a password
- return true;
- }
+ return mPasswordHash != null && mPasswordHash.length() > 0;
}
private boolean backupPasswordMatches(String currentPw) {
@@ -1789,8 +1735,8 @@
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.
+ // Transport maintenance: rebind to known existing transports that have
+ // just been updated; and bind to any newly-installed transport services.
if (rebind) {
synchronized (mTransportConnections) {
final TransportConnection conn = mTransportConnections.get(packageName);
@@ -1799,9 +1745,12 @@
Slog.i(TAG, "Transport package changed; rebinding");
}
bindTransport(conn.mTransport);
+ } else {
+ checkForTransportAndBind(app);
}
}
}
+
} catch (NameNotFoundException e) {
// doesn't really exist; ignore it
if (DEBUG) {
@@ -1853,7 +1802,36 @@
}
};
- void bindTransport(ServiceInfo transport) {
+ // Check whether the given package hosts a transport, and bind if so
+ void checkForTransportAndBind(PackageInfo pkgInfo) {
+ Intent intent = new Intent(mTransportServiceIntent)
+ .setPackage(pkgInfo.packageName);
+ List<ResolveInfo> hosts = mPackageManager.queryIntentServicesAsUser(
+ intent, 0, UserHandle.USER_OWNER);
+ final int N = hosts.size();
+ for (int i = 0; i < N; i++) {
+ final ServiceInfo info = hosts.get(i).serviceInfo;
+ tryBindTransport(info);
+ }
+ }
+
+ // Verify that the service exists and is hosted by a privileged app, then proceed to bind
+ boolean tryBindTransport(ServiceInfo info) {
+ try {
+ PackageInfo packInfo = mPackageManager.getPackageInfo(info.packageName, 0);
+ if ((packInfo.applicationInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0) {
+ return bindTransport(info);
+ } else {
+ Slog.w(TAG, "Transport package " + info.packageName + " not privileged");
+ }
+ } catch (NameNotFoundException e) {
+ Slog.w(TAG, "Problem resolving transport package " + info.packageName);
+ }
+ return false;
+ }
+
+ // Actually bind; presumes that we have already validated the transport service
+ boolean bindTransport(ServiceInfo transport) {
ComponentName svcName = new ComponentName(transport.packageName, transport.name);
if (DEBUG) {
Slog.i(TAG, "Binding to transport host " + svcName);
@@ -1874,7 +1852,7 @@
mContext.unbindService(connection);
}
}
- mContext.bindServiceAsUser(intent,
+ return mContext.bindServiceAsUser(intent,
connection, Context.BIND_AUTO_CREATE,
UserHandle.OWNER);
}
@@ -3321,6 +3299,20 @@
}
}
+ boolean deviceIsEncrypted() {
+ try {
+ return mMountService.getEncryptionState()
+ != IMountService.ENCRYPTION_STATE_NONE
+ && mMountService.getPasswordType()
+ != StorageManager.CRYPT_TYPE_DEFAULT;
+ } catch (Exception e) {
+ // If we can't talk to the mount service we have a serious problem; fail
+ // "secure" i.e. assuming that the device is encrypted.
+ Slog.e(TAG, "Unable to communicate with mount service: " + e.getMessage());
+ return true;
+ }
+ }
+
// Full backup task variant used for adb backup
class PerformAdbBackupTask extends FullBackupTask {
FullBackupEngine mBackupEngine;
@@ -3338,7 +3330,7 @@
ArrayList<String> mPackages;
String mCurrentPassword;
String mEncryptPassword;
-
+
PerformAdbBackupTask(ParcelFileDescriptor fd, IFullBackupRestoreObserver observer,
boolean includeApks, boolean includeObbs, boolean includeShared,
boolean doWidgets, String curPassword, String encryptPassword, boolean doAllApps,
@@ -3535,6 +3527,13 @@
PackageInfo pkg = null;
try {
boolean encrypting = (mEncryptPassword != null && mEncryptPassword.length() > 0);
+
+ // Only allow encrypted backups of encrypted devices
+ if (deviceIsEncrypted() && !encrypting) {
+ Slog.e(TAG, "Unencrypted backup of encrypted device; aborting");
+ return;
+ }
+
OutputStream finalOutput = ofstream;
// Verify that the given password matches the currently-active
@@ -8315,17 +8314,7 @@
params.observer = observer;
params.curPassword = curPassword;
- boolean isEncrypted;
- try {
- isEncrypted = (mMountService.getEncryptionState() !=
- IMountService.ENCRYPTION_STATE_NONE);
- if (isEncrypted) Slog.w(TAG, "Device is encrypted; forcing enc password");
- } catch (RemoteException e) {
- // couldn't contact the mount service; fail "safe" and assume encryption
- Slog.e(TAG, "Unable to contact mount service!");
- isEncrypted = true;
- }
- params.encryptPassword = (isEncrypted) ? curPassword : encPpassword;
+ params.encryptPassword = encPpassword;
if (DEBUG) Slog.d(TAG, "Sending conf message with verb " + verb);
mWakelock.acquire();
@@ -8470,7 +8459,8 @@
// name is not one of the available transports, no action is taken and the method
// returns null.
public String selectBackupTransport(String transport) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "selectBackupTransport");
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
+ "selectBackupTransport");
synchronized (mTransports) {
String prevTransport = null;
@@ -9130,19 +9120,22 @@
pw.println(" next scheduled: " + mNextBackupPass);
pw.println("Available transports:");
- for (String t : listAllTransports()) {
- pw.println((t.equals(mCurrentTransport) ? " * " : " ") + t);
- try {
- IBackupTransport transport = getTransport(t);
- File dir = new File(mBaseStateDir, transport.transportDirName());
- pw.println(" destination: " + transport.currentDestinationString());
- pw.println(" intent: " + transport.configurationIntent());
- for (File f : dir.listFiles()) {
- pw.println(" " + f.getName() + " - " + f.length() + " state bytes");
+ final String[] transports = listAllTransports();
+ if (transports != null) {
+ for (String t : listAllTransports()) {
+ pw.println((t.equals(mCurrentTransport) ? " * " : " ") + t);
+ try {
+ IBackupTransport transport = getTransport(t);
+ File dir = new File(mBaseStateDir, transport.transportDirName());
+ pw.println(" destination: " + transport.currentDestinationString());
+ pw.println(" intent: " + transport.configurationIntent());
+ for (File f : dir.listFiles()) {
+ pw.println(" " + f.getName() + " - " + f.length() + " state bytes");
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "Error in transport", e);
+ pw.println(" Error: " + e);
}
- } catch (Exception e) {
- Slog.e(TAG, "Error in transport", e);
- pw.println(" Error: " + e);
}
}
diff --git a/services/backup/java/com/android/server/backup/FullBackupJob.java b/services/backup/java/com/android/server/backup/FullBackupJob.java
index deb2293..601f15e 100644
--- a/services/backup/java/com/android/server/backup/FullBackupJob.java
+++ b/services/backup/java/com/android/server/backup/FullBackupJob.java
@@ -20,10 +20,8 @@
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
-import android.app.job.JobInfo.NetworkType;
import android.content.ComponentName;
import android.content.Context;
-import android.util.Slog;
public class FullBackupJob extends JobService {
private static final String TAG = "FullBackupJob";
@@ -40,7 +38,7 @@
JobScheduler js = (JobScheduler) ctx.getSystemService(Context.JOB_SCHEDULER_SERVICE);
JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, sIdleService)
.setRequiresDeviceIdle(true)
- .setRequiredNetworkCapabilities(NetworkType.UNMETERED)
+ .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(true);
if (minDelay > 0) {
builder.setMinimumLatency(minDelay);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 96f8324..7655e92 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2160,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;
}
@@ -2850,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();
}
}
}
@@ -4759,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/MountService.java b/services/core/java/com/android/server/MountService.java
index 50f2ae9..ea24d7c 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -33,7 +33,6 @@
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.hardware.usb.UsbManager;
-import android.app.admin.DevicePolicyManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Environment;
@@ -1761,6 +1760,21 @@
return rc;
}
+ @Override
+ public int resizeSecureContainer(String id, int sizeMb, String key) {
+ validatePermission(android.Manifest.permission.ASEC_CREATE);
+ waitForReady();
+ warnOnNotMounted();
+
+ int rc = StorageResultCode.OperationSucceeded;
+ try {
+ mConnector.execute("asec", "resize", id, sizeMb, new SensitiveArg(key));
+ } catch (NativeDaemonConnectorException e) {
+ rc = StorageResultCode.OperationFailedInternalError;
+ }
+ return rc;
+ }
+
public int finalizeSecureContainer(String id) {
validatePermission(android.Manifest.permission.ASEC_CREATE);
warnOnNotMounted();
@@ -1835,7 +1849,7 @@
return rc;
}
- public int mountSecureContainer(String id, String key, int ownerUid) {
+ public int mountSecureContainer(String id, String key, int ownerUid, boolean readOnly) {
validatePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT);
waitForReady();
warnOnNotMounted();
@@ -1848,7 +1862,8 @@
int rc = StorageResultCode.OperationSucceeded;
try {
- mConnector.execute("asec", "mount", id, new SensitiveArg(key), ownerUid);
+ mConnector.execute("asec", "mount", id, new SensitiveArg(key), ownerUid,
+ readOnly ? "ro" : "rw");
} catch (NativeDaemonConnectorException e) {
int code = e.getCode();
if (code != VoldResponseCode.OpFailedStorageBusy) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b1d84f58..dd3d862 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;
@@ -1160,6 +1179,7 @@
static final int SYSTEM_USER_CURRENT_MSG = 43;
static final int ENTER_ANIMATION_COMPLETE_MSG = 44;
static final int ENABLE_SCREEN_AFTER_BOOT_MSG = 45;
+ static final int START_USER_SWITCH_MSG = 46;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1181,6 +1201,9 @@
/** Flag whether the device has a recents UI */
final boolean mHasRecents;
+ final int mThumbnailWidth;
+ final int mThumbnailHeight;
+
final ServiceThread mHandlerThread;
final MainHandler mHandler;
@@ -1749,6 +1772,10 @@
thread.start();
break;
}
+ case START_USER_SWITCH_MSG: {
+ showUserSwitchDialog(msg.arg1, (String) msg.obj);
+ break;
+ }
case REPORT_USER_SWITCH_MSG: {
dispatchUserSwitch((UserStartedState) msg.obj, msg.arg1, msg.arg2);
break;
@@ -1819,6 +1846,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 +2257,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 +3511,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 +3812,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 +3821,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 +3871,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 +3894,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 +7687,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 +7707,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 +7729,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 +7779,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 +15571,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,
@@ -17295,6 +17448,15 @@
}
/**
+ * Start user, if its not already running, and bring it to foreground.
+ */
+ boolean startUserInForeground(final int userId, Dialog dlg) {
+ boolean result = startUser(userId, /* foreground */ true);
+ dlg.dismiss();
+ return result;
+ }
+
+ /**
* Refreshes the list of users related to the current user when either a
* user switch happens or when a new related user is started in the
* background.
@@ -17332,7 +17494,29 @@
@Override
public boolean switchUser(final int userId) {
- return startUser(userId, /* foregound */ true);
+ String userName;
+ synchronized (this) {
+ UserInfo userInfo = getUserManagerLocked().getUserInfo(userId);
+ if (userInfo == null) {
+ Slog.w(TAG, "No user info for user #" + userId);
+ return false;
+ }
+ if (userInfo.isManagedProfile()) {
+ Slog.w(TAG, "Cannot switch to User #" + userId + ": not a full user");
+ return false;
+ }
+ userName = userInfo.name;
+ }
+ mHandler.removeMessages(START_USER_SWITCH_MSG);
+ mHandler.sendMessage(mHandler.obtainMessage(START_USER_SWITCH_MSG, userId, 0, userName));
+ return true;
+ }
+
+ private void showUserSwitchDialog(int userId, String userName) {
+ // The dialog will show and then initiate the user switch by calling startUserInForeground
+ Dialog d = new UserSwitchingDialog(this, mContext, userId, userName,
+ true /* above system */);
+ d.show();
}
private boolean startUser(final int userId, boolean foreground) {
@@ -18056,14 +18240,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 +18271,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 +18286,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/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/LockToAppRequestDialog.java b/services/core/java/com/android/server/am/LockToAppRequestDialog.java
index 5abf699..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,6 +101,8 @@
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) {
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/am/UserSwitchingDialog.java b/services/core/java/com/android/server/am/UserSwitchingDialog.java
new file mode 100644
index 0000000..59d53ec
--- /dev/null
+++ b/services/core/java/com/android/server/am/UserSwitchingDialog.java
@@ -0,0 +1,79 @@
+/*
+ * 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.am;
+
+import android.app.Service;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Slog;
+import android.view.WindowManager;
+
+/**
+ * Dialog to show when a user switch it about to happen. The intent is to snapshot the screen
+ * immediately after the dialog shows so that the user is informed that something is happening
+ * in the background rather than just freeze the screen and not know if the user-switch affordance
+ * was being handled.
+ */
+final class UserSwitchingDialog extends BaseErrorDialog {
+ private static final String TAG = "ActivityManagerUserSwitchingDialog";
+
+ private static final int MSG_START_USER = 1;
+
+ private final ActivityManagerService mService;
+ private final int mUserId;
+
+ public UserSwitchingDialog(ActivityManagerService service, Context context,
+ int userId, String userName, boolean aboveSystem) {
+ super(context);
+
+ mService = service;
+ mUserId = userId;
+ Resources res = context.getResources();
+ setCancelable(false);
+ setMessage(res.getString(com.android.internal.R.string.user_switching_message, userName));
+ if (aboveSystem) {
+ getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
+ }
+ WindowManager.LayoutParams attrs = getWindow().getAttributes();
+ attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR |
+ WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ getWindow().setAttributes(attrs);
+ }
+
+ @Override
+ public void show() {
+ super.show();
+ // TODO: Instead of just an arbitrary delay, wait for a signal that the window was fully
+ // displayed by the window manager
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_USER), 250);
+ }
+
+ private final Handler mHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_START_USER:
+ mService.startUserInForeground(mUserId, UserSwitchingDialog.this);
+ break;
+ }
+ }
+ };
+}
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index b09298c..9f4ed89 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -639,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);
@@ -769,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 69caab9..94aa421 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -22,6 +22,7 @@
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -105,6 +106,7 @@
private boolean mAllowIPv6;
private Connection mConnection;
private LegacyVpnRunner mLegacyVpnRunner;
+ private PendingIntent mStatusIntent;
private volatile boolean mEnableTeardown = true;
private final IConnectivityManager mConnService;
private final INetworkManagementService mNetd;
@@ -237,6 +239,7 @@
// Reset the interface.
if (mInterface != null) {
+ mStatusIntent = null;
agentDisconnect();
jniReset(mInterface);
mInterface = null;
@@ -567,17 +570,20 @@
// add the user
mVpnUsers.add(UidRange.createForUser(user));
+
+ prepareStatusIntent();
}
private void removeVpnUserLocked(int user) {
- if (!isRunningLocked()) {
- throw new IllegalStateException("VPN is not active");
- }
- UidRange uidRange = UidRange.createForUser(user);
- if (mNetworkAgent != null) {
- mNetworkAgent.removeUidRanges(new UidRange[] { uidRange });
- }
- mVpnUsers.remove(uidRange);
+ if (!isRunningLocked()) {
+ throw new IllegalStateException("VPN is not active");
+ }
+ UidRange uidRange = UidRange.createForUser(user);
+ if (mNetworkAgent != null) {
+ mNetworkAgent.removeUidRanges(new UidRange[] { uidRange });
+ }
+ mVpnUsers.remove(uidRange);
+ mStatusIntent = null;
}
private void onUserAdded(int userId) {
@@ -645,6 +651,7 @@
public void interfaceRemoved(String interfaze) {
synchronized (Vpn.this) {
if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) {
+ mStatusIntent = null;
mVpnUsers = null;
mInterface = null;
if (mConnection != null) {
@@ -702,6 +709,15 @@
}
}
+ private void prepareStatusIntent() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mStatusIntent = VpnConfig.getIntentForStatusPanel(mContext);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
public synchronized boolean addAddress(String address, int prefixLength) {
if (Binder.getCallingUid() != mOwnerUID || mInterface == null || mNetworkAgent == null) {
return false;
@@ -911,6 +927,9 @@
final LegacyVpnInfo info = new LegacyVpnInfo();
info.key = mConfig.user;
info.state = LegacyVpnInfo.stateFromNetworkInfo(mNetworkInfo);
+ if (mNetworkInfo.isConnected()) {
+ info.intent = mStatusIntent;
+ }
return info;
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 2a1ceaa..38077eb 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -139,6 +139,9 @@
// The dim screen brightness.
private final int mScreenBrightnessDimConfig;
+ // The minimum screen brightness to use in a very dark room.
+ private final int mScreenBrightnessDarkConfig;
+
// The minimum allowed brightness.
private final int mScreenBrightnessRangeMinimum;
@@ -247,6 +250,8 @@
mContext = context;
final Resources resources = context.getResources();
+ final int screenBrightnessSettingMinimum = clampAbsoluteBrightness(resources.getInteger(
+ com.android.internal.R.integer.config_screenBrightnessSettingMinimum));
mScreenBrightnessDozeConfig = clampAbsoluteBrightness(resources.getInteger(
com.android.internal.R.integer.config_screenBrightnessDoze));
@@ -254,9 +259,23 @@
mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger(
com.android.internal.R.integer.config_screenBrightnessDim));
- int screenBrightnessRangeMinimum = clampAbsoluteBrightness(Math.min(resources.getInteger(
- com.android.internal.R.integer.config_screenBrightnessSettingMinimum),
- mScreenBrightnessDimConfig));
+ mScreenBrightnessDarkConfig = clampAbsoluteBrightness(resources.getInteger(
+ com.android.internal.R.integer.config_screenBrightnessDark));
+ if (mScreenBrightnessDarkConfig > mScreenBrightnessDimConfig) {
+ Slog.w(TAG, "Expected config_screenBrightnessDark ("
+ + mScreenBrightnessDarkConfig + ") to be less than or equal to "
+ + "config_screenBrightnessDim (" + mScreenBrightnessDimConfig + ").");
+ }
+ if (mScreenBrightnessDarkConfig > mScreenBrightnessDimConfig) {
+ Slog.w(TAG, "Expected config_screenBrightnessDark ("
+ + mScreenBrightnessDarkConfig + ") to be less than or equal to "
+ + "config_screenBrightnessSettingMinimum ("
+ + screenBrightnessSettingMinimum + ").");
+ }
+
+ int screenBrightnessRangeMinimum = Math.min(Math.min(
+ screenBrightnessSettingMinimum, mScreenBrightnessDimConfig),
+ mScreenBrightnessDarkConfig);
mScreenBrightnessRangeMaximum = PowerManager.BRIGHTNESS_ON;
@@ -280,8 +299,15 @@
+ "Auto-brightness will be disabled.");
mUseSoftwareAutoBrightnessConfig = false;
} else {
- if (screenBrightness[0] < screenBrightnessRangeMinimum) {
- screenBrightnessRangeMinimum = clampAbsoluteBrightness(screenBrightness[0]);
+ int bottom = clampAbsoluteBrightness(screenBrightness[0]);
+ if (mScreenBrightnessDarkConfig > bottom) {
+ Slog.w(TAG, "config_screenBrightnessDark (" + mScreenBrightnessDarkConfig
+ + ") should be less than or equal to the first value of "
+ + "config_autoBrightnessLcdBacklightValues ("
+ + bottom + ").");
+ }
+ if (bottom < screenBrightnessRangeMinimum) {
+ screenBrightnessRangeMinimum = bottom;
}
mAutomaticBrightnessController = new AutomaticBrightnessController(this,
handler.getLooper(), sensorManager, screenAutoBrightnessSpline,
@@ -905,6 +931,7 @@
pw.println("Display Power Controller Configuration:");
pw.println(" mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
+ pw.println(" mScreenBrightnessDarkConfig=" + mScreenBrightnessDarkConfig);
pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
pw.println(" mUseSoftwareAutoBrightnessConfig="
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index a231945..935714c 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,11 +312,13 @@
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);
@@ -317,7 +327,9 @@
addAndStartAction(new RoutingControlAction(this, newPath, true, callback));
}
+ @ServiceThreadOnly
int getPowerStatus() {
+ assertRunOnServiceThread();
return mService.getPowerStatus();
}
@@ -418,8 +430,7 @@
@ServiceThreadOnly
protected boolean handleGetMenuLanguage(HdmiCecMessage message) {
assertRunOnServiceThread();
- // TODO: figure out how to handle failed to get language code.
- if (!broadcastMenuLanguage(Locale.getDefault().getISO3Language())) {
+ if (!broadcastMenuLanguage(mService.getLanguage())) {
Slog.w(TAG, "Failed to respond to <Get Menu Language>: " + message.toString());
}
return true;
@@ -566,8 +577,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 888ceec3..3021285 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;
@@ -125,8 +126,10 @@
}
private class HdmiControlBroadcastReceiver extends BroadcastReceiver {
+ @ServiceThreadOnly
@Override
public void onReceive(Context context, Intent intent) {
+ assertRunOnServiceThread();
switch (intent.getAction()) {
case Intent.ACTION_SCREEN_OFF:
if (isPowerOnOrTransient()) {
@@ -159,41 +162,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 +208,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 +217,9 @@
private final SettingsObserver mSettingsObserver;
+ private final HdmiControlBroadcastReceiver
+ mHdmiControlBroadcastReceiver = new HdmiControlBroadcastReceiver();
+
@Nullable
private HdmiCecController mCecController;
@@ -248,9 +241,6 @@
private HdmiCecMessageValidator mMessageValidator;
- private final HdmiControlBroadcastReceiver
- mHdmiControlBroadcastReceiver = new HdmiControlBroadcastReceiver();
-
@ServiceThreadOnly
private int mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
@@ -367,6 +357,7 @@
super(handler);
}
+ // onChange is set up to run in service thread.
@Override
public void onChange(boolean selfChange, Uri uri) {
String option = uri.getLastPathSegment();
@@ -648,7 +639,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);
}
@@ -709,7 +700,7 @@
}
if (message.getDestination() != Constants.ADDR_BROADCAST) {
- Slog.w(TAG, "Unhandled cec command:" + message);
+ mSpamSafeLogger.warning("Unhandled cec command:" + message);
}
return false;
}
@@ -788,8 +779,11 @@
}
void announceSystemAudioModeChange(boolean enabled) {
- for (IHdmiSystemAudioModeChangeListener listener : mSystemAudioModeChangeListeners) {
- invokeSystemAudioModeChange(listener, enabled);
+ synchronized (mLock) {
+ for (SystemAudioModeChangeListenerRecord record :
+ mSystemAudioModeChangeListenerRecords) {
+ invokeSystemAudioModeChangeLocked(record.mListener, enabled);
+ }
}
}
@@ -914,7 +908,6 @@
public void binderDied() {
synchronized (mLock) {
mHotplugEventListenerRecords.remove(this);
- mHotplugEventListeners.remove(mListener);
}
}
}
@@ -930,7 +923,6 @@
public void binderDied() {
synchronized (mLock) {
mDeviceEventListenerRecords.remove(this);
- mDeviceEventListeners.remove(mListener);
}
}
}
@@ -946,7 +938,6 @@
public void binderDied() {
synchronized (mLock) {
mSystemAudioModeChangeListenerRecords.remove(this);
- mSystemAudioModeChangeListeners.remove(mListener);
}
}
}
@@ -969,14 +960,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);
}
@@ -1120,34 +1130,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
@@ -1288,12 +1283,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
@@ -1382,6 +1372,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
@@ -1418,7 +1440,6 @@
}
synchronized (mLock) {
mHotplugEventListenerRecords.add(record);
- mHotplugEventListeners.add(listener);
}
}
@@ -1431,7 +1452,6 @@
break;
}
}
- mHotplugEventListeners.remove(listener);
}
}
@@ -1444,16 +1464,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);
}
@@ -1471,7 +1490,6 @@
return;
}
synchronized (mLock) {
- mSystemAudioModeChangeListeners.add(listener);
mSystemAudioModeChangeListenerRecords.add(record);
}
}
@@ -1486,37 +1504,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);
}
@@ -1526,21 +1548,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);
}
@@ -1551,9 +1572,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);
}
@@ -1563,9 +1584,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);
}
@@ -1575,9 +1596,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);
}
@@ -1593,7 +1614,7 @@
}
}
- private void invokeSystemAudioModeChange(IHdmiSystemAudioModeChangeListener listener,
+ private void invokeSystemAudioModeChangeLocked(IHdmiSystemAudioModeChangeListener listener,
boolean enabled) {
try {
listener.onStatusChanged(enabled);
@@ -1605,8 +1626,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);
}
}
}
@@ -1643,21 +1664,29 @@
}
}
+ @ServiceThreadOnly
int getPowerStatus() {
+ assertRunOnServiceThread();
return mPowerStatus;
}
+ @ServiceThreadOnly
boolean isPowerOnOrTransient() {
+ assertRunOnServiceThread();
return mPowerStatus == HdmiControlManager.POWER_STATUS_ON
|| mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON;
}
+ @ServiceThreadOnly
boolean isPowerStandbyOrTransient() {
+ assertRunOnServiceThread();
return mPowerStatus == HdmiControlManager.POWER_STATUS_STANDBY
|| mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY;
}
+ @ServiceThreadOnly
boolean isPowerStandby() {
+ assertRunOnServiceThread();
return mPowerStatus == HdmiControlManager.POWER_STATUS_STANDBY;
}
@@ -1681,11 +1710,6 @@
// the intent, the sequence will continue at onStandby().
}
- void nap() {
- PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
- pm.nap(SystemClock.uptimeMillis());
- }
-
@ServiceThreadOnly
private void onWakeUp() {
assertRunOnServiceThread();
@@ -1735,6 +1759,12 @@
}
}
+ @ServiceThreadOnly
+ String getLanguage() {
+ assertRunOnServiceThread();
+ return mLanguage;
+ }
+
private void disableDevices(PendingActionClearedCallback callback) {
if (mCecController != null) {
for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
@@ -1805,6 +1835,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;
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..379ec94 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -117,6 +117,8 @@
*/
final ArrayList<JobStatus> mPendingJobs = new ArrayList<JobStatus>();
+ final ArrayList<Integer> mStartedUsers = new ArrayList();
+
final JobHandler mHandler;
final JobSchedulerStub mJobSchedulerStub;
@@ -151,6 +153,18 @@
}
};
+ @Override
+ public void onStartUser(int userHandle) {
+ mStartedUsers.add(userHandle);
+ // Let's kick any outstanding jobs for this user.
+ mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+ }
+
+ @Override
+ public void onStopUser(int userHandle) {
+ mStartedUsers.remove(Integer.valueOf(userHandle));
+ }
+
/**
* Entry point from client to schedule the provided job.
* This cancels the job if it's already been scheduled, and replaces it with the one provided.
@@ -162,6 +176,7 @@
JobStatus jobStatus = new JobStatus(job, uId);
cancelJob(uId, job.getId());
startTrackingJob(jobStatus);
+ mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
return JobScheduler.RESULT_SUCCESS;
}
@@ -392,26 +407,26 @@
final JobInfo job = failureToReschedule.getJob();
final long initialBackoffMillis = job.getInitialBackoffMillis();
- final int backoffAttempt = failureToReschedule.getNumFailures() + 1;
- long newEarliestRuntimeElapsed = elapsedNowMillis;
+ final int backoffAttempts = failureToReschedule.getNumFailures() + 1;
+ long delayMillis;
switch (job.getBackoffPolicy()) {
- case JobInfo.BackoffPolicy.LINEAR:
- newEarliestRuntimeElapsed += initialBackoffMillis * backoffAttempt;
+ case JobInfo.BACKOFF_POLICY_LINEAR:
+ delayMillis = initialBackoffMillis * backoffAttempts;
break;
default:
if (DEBUG) {
Slog.v(TAG, "Unrecognised back-off policy, defaulting to exponential.");
}
- case JobInfo.BackoffPolicy.EXPONENTIAL:
- newEarliestRuntimeElapsed +=
- Math.pow(initialBackoffMillis * 0.001, backoffAttempt) * 1000;
+ case JobInfo.BACKOFF_POLICY_EXPONENTIAL:
+ delayMillis =
+ (long) Math.scalb(initialBackoffMillis, backoffAttempts - 1);
break;
}
- newEarliestRuntimeElapsed =
- Math.min(newEarliestRuntimeElapsed, JobInfo.MAX_BACKOFF_DELAY_MILLIS);
- return new JobStatus(failureToReschedule, newEarliestRuntimeElapsed,
- JobStatus.NO_LATEST_RUNTIME, backoffAttempt);
+ delayMillis =
+ Math.min(delayMillis, JobInfo.MAX_BACKOFF_DELAY_MILLIS);
+ return new JobStatus(failureToReschedule, elapsedNowMillis + delayMillis,
+ JobStatus.NO_LATEST_RUNTIME, backoffAttempts);
}
/**
@@ -507,7 +522,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);
}
}
@@ -607,9 +624,20 @@
* - It's ready.
* - It's not pending.
* - It's not already running on a JSC.
+ * - The user that requested the job is running.
*/
private boolean isReadyToBeExecutedLocked(JobStatus job) {
- return job.isReady() && !mPendingJobs.contains(job) && !isCurrentlyActiveLocked(job);
+ final boolean jobReady = job.isReady();
+ final boolean jobPending = mPendingJobs.contains(job);
+ final boolean jobActive = isCurrentlyActiveLocked(job);
+ final boolean userRunning = mStartedUsers.contains(job.getUserId());
+
+ if (DEBUG) {
+ Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString()
+ + " ready=" + jobReady + " pending=" + jobPending
+ + " active=" + jobActive + " userRunning=" + userRunning);
+ }
+ return userRunning && jobReady && !jobPending && !jobActive;
}
/**
@@ -792,6 +820,11 @@
void dumpInternal(PrintWriter pw) {
synchronized (mJobs) {
+ pw.print("Started users: ");
+ for (int i=0; i<mStartedUsers.size(); i++) {
+ pw.print("u" + mStartedUsers.get(i) + " ");
+ }
+ pw.println();
pw.println("Registered jobs:");
if (mJobs.size() > 0) {
ArraySet<JobStatus> jobs = mJobs.getJobs();
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 46f557f..df12e1a 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -515,7 +515,7 @@
// Read out job identifier attributes.
try {
jobBuilder = buildBuilderFromXml(parser);
- jobBuilder.setIsPersisted(true);
+ jobBuilder.setPersisted(true);
uid = Integer.valueOf(parser.getAttributeValue(null, "uid"));
} catch (NumberFormatException e) {
Slog.e(TAG, "Error parsing job's required fields, skipping");
@@ -622,11 +622,11 @@
private void buildConstraintsFromXml(JobInfo.Builder jobBuilder, XmlPullParser parser) {
String val = parser.getAttributeValue(null, "unmetered");
if (val != null) {
- jobBuilder.setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED);
+ jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
}
val = parser.getAttributeValue(null, "connectivity");
if (val != null) {
- jobBuilder.setRequiredNetworkCapabilities(JobInfo.NetworkType.ANY);
+ jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
}
val = parser.getAttributeValue(null, "idle");
if (val != null) {
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/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 652d8f8..6f5d3c2 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -21,6 +21,7 @@
import android.os.PersistableBundle;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.text.format.DateUtils;
import java.io.PrintWriter;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -41,6 +42,7 @@
public static final long NO_EARLIEST_RUNTIME = 0L;
final JobInfo job;
+ /** Uid of the package requesting this job. */
final int uId;
final String name;
final String tag;
@@ -157,11 +159,11 @@
}
public boolean hasConnectivityConstraint() {
- return job.getNetworkCapabilities() == JobInfo.NetworkType.ANY;
+ return job.getNetworkType() == JobInfo.NETWORK_TYPE_ANY;
}
public boolean hasUnmeteredConstraint() {
- return job.getNetworkCapabilities() == JobInfo.NetworkType.UNMETERED;
+ return job.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED;
}
public boolean hasChargingConstraint() {
@@ -214,12 +216,39 @@
return String.valueOf(hashCode()).substring(0, 3) + ".."
+ ":[" + job.getService()
+ ",jId=" + job.getId()
- + ",R=(" + earliestRunTimeElapsedMillis + "," + latestRunTimeElapsedMillis + ")"
- + ",N=" + job.getNetworkCapabilities() + ",C=" + job.isRequireCharging()
+ + ",u" + getUserId()
+ + ",R=(" + formatRunTime(earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME)
+ + "," + formatRunTime(latestRunTimeElapsedMillis, NO_LATEST_RUNTIME) + ")"
+ + ",N=" + job.getNetworkType() + ",C=" + job.isRequireCharging()
+ ",I=" + job.isRequireDeviceIdle() + ",F=" + numFailures
+ + ",P=" + job.isPersisted()
+ (isReady() ? "(READY)" : "")
+ "]";
}
+
+ private String formatRunTime(long runtime, long defaultValue) {
+ if (runtime == defaultValue) {
+ return "none";
+ } else {
+ long elapsedNow = SystemClock.elapsedRealtime();
+ long nextRuntime = runtime - elapsedNow;
+ if (nextRuntime > 0) {
+ return DateUtils.formatElapsedTime(nextRuntime / 1000);
+ } else {
+ return "-" + DateUtils.formatElapsedTime(nextRuntime / -1000);
+ }
+ }
+ }
+
+ /**
+ * Convenience function to identify a job uniquely without pulling all the data that
+ * {@link #toString()} returns.
+ */
+ public String toShortString() {
+ return job.getService().flattenToShortString() + " jId=" + job.getId() +
+ ", u" + getUserId();
+ }
+
// Dumpsys infrastructure
public void dump(PrintWriter pw, String prefix) {
pw.println(this.toString());
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 45bd812..c390f9b 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -29,6 +29,7 @@
import android.app.INotificationManager;
import android.app.ITransientNotification;
import android.app.Notification;
+import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
@@ -56,6 +57,7 @@
import android.os.IInterface;
import android.os.Looper;
import android.os.Message;
+import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -109,6 +111,7 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.NoSuchElementException;
+import java.util.Objects;
/** {@hide} */
public class NotificationManagerService extends SystemService {
@@ -173,6 +176,7 @@
NotificationRecord mVibrateNotification;
private final ArraySet<ManagedServiceInfo> mListenersDisablingEffects = new ArraySet<>();
+ private ComponentName mEffectsSuppressor;
private int mListenerHints; // right now, all hints are global
// for enabling and disabling notification pulse behavior
@@ -941,6 +945,15 @@
scheduleListenerHintsChanged(hints);
}
+ private void updateEffectsSuppressorLocked() {
+ final ComponentName suppressor = !mListenersDisablingEffects.isEmpty()
+ ? mListenersDisablingEffects.valueAt(0).component : null;
+ if (Objects.equals(suppressor, mEffectsSuppressor)) return;
+ mEffectsSuppressor = suppressor;
+ getContext().sendBroadcast(new Intent(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED)
+ .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
+ }
+
private final IBinder mService = new INotificationManager.Stub() {
// Toasts
// ============================================================================
@@ -1299,6 +1312,7 @@
}
mZenModeHelper.requestFromListener(hints);
updateListenerHintsLocked();
+ updateEffectsSuppressorLocked();
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -1384,6 +1398,12 @@
dumpImpl(pw, DumpFilter.parseFromArguments(args));
}
+
+ @Override
+ public ComponentName getEffectsSuppressor() {
+ enforceSystemOrSystemUI("INotificationManager.getEffectsSuppressor");
+ return mEffectsSuppressor;
+ }
};
private String[] getActiveNotificationKeys(INotificationListener token) {
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 03cb2e9..6f60d24 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -19,7 +19,6 @@
import static android.content.pm.PackageManager.INSTALL_ALL_USERS;
import static android.content.pm.PackageManager.INSTALL_FROM_ADB;
import static android.content.pm.PackageManager.INSTALL_REPLACE_EXISTING;
-import static android.net.TrafficStats.MB_IN_BYTES;
import static com.android.internal.util.XmlUtils.readBitmapAttribute;
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
import static com.android.internal.util.XmlUtils.readIntAttribute;
@@ -48,8 +47,11 @@
import android.content.pm.IPackageInstallerCallback;
import android.content.pm.IPackageInstallerSession;
import android.content.pm.PackageInstaller;
+import android.content.pm.PackageParser;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageInstaller.SessionParams;
+import android.content.pm.PackageParser.PackageLite;
+import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
@@ -208,7 +210,7 @@
// Ignore stages claimed by active sessions
for (int i = 0; i < mSessions.size(); i++) {
final PackageInstallerSession session = mSessions.valueAt(i);
- unclaimed.remove(session.internalStageDir);
+ unclaimed.remove(session.stageDir);
}
// Clean up orphaned staging directories
@@ -234,7 +236,7 @@
// Ignore stages claimed by active sessions
for (int i = 0; i < mSessions.size(); i++) {
final PackageInstallerSession session = mSessions.valueAt(i);
- final String cid = session.externalStageCid;
+ final String cid = session.stageCid;
if (unclaimed.remove(cid)) {
// Claimed by active session, mount it
@@ -304,10 +306,10 @@
Slog.w(TAG, "Abandoning old session first created at "
+ session.createdMillis);
valid = false;
- } else if (session.internalStageDir != null
- && !session.internalStageDir.exists()) {
+ } else if (session.stageDir != null
+ && !session.stageDir.exists()) {
Slog.w(TAG, "Abandoning internal session with missing stage "
- + session.internalStageDir);
+ + session.stageDir);
valid = false;
} else {
valid = true;
@@ -401,12 +403,12 @@
writeStringAttribute(out, ATTR_INSTALLER_PACKAGE_NAME,
session.installerPackageName);
writeLongAttribute(out, ATTR_CREATED_MILLIS, session.createdMillis);
- if (session.internalStageDir != null) {
+ if (session.stageDir != null) {
writeStringAttribute(out, ATTR_SESSION_STAGE_DIR,
- session.internalStageDir.getAbsolutePath());
+ session.stageDir.getAbsolutePath());
}
- if (session.externalStageCid != null) {
- writeStringAttribute(out, ATTR_SESSION_STAGE_CID, session.externalStageCid);
+ if (session.stageCid != null) {
+ writeStringAttribute(out, ATTR_SESSION_STAGE_CID, session.stageCid);
}
writeBooleanAttribute(out, ATTR_SEALED, session.isSealed());
@@ -479,40 +481,61 @@
}
}
+ // TODO: treat INHERIT_EXISTING as install for user
+
// Figure out where we're going to be staging session data
final boolean stageInternal;
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.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);
- }
+ 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
- // everything looks legit.
- stageInternal = true;
- checkInternalStorage(params.sizeBytes);
-
- // If we have a good hunch we'll end up on external storage, verify
- // free space there too.
- final ApplicationInfo info = mPm.getApplicationInfo(params.appPackageName, 0,
+ // Inheriting existing install, so stay on the same storage medium.
+ final ApplicationInfo existingApp = mPm.getApplicationInfo(params.appPackageName, 0,
userId);
- if (info != null && (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
- checkExternalStorage(params.sizeBytes);
-
- throw new UnsupportedOperationException("TODO: finish fleshing out ASEC support");
+ if (existingApp == null) {
+ throw new IllegalStateException(
+ "Missing existing app " + params.appPackageName);
}
+ final long existingSize;
+ try {
+ final PackageLite existingPkg = PackageParser.parsePackageLite(
+ new File(existingApp.getCodePath()), 0);
+ existingSize = PackageHelper.calculateInstalledSize(existingPkg, false,
+ params.abiOverride);
+ } catch (PackageParserException e) {
+ throw new IllegalStateException(
+ "Failed to calculate size of " + params.appPackageName);
+ }
+
+ if ((existingApp.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0) {
+ // Internal we can link existing install into place, so we only
+ // need enough space for the new data.
+ checkInternalStorage(params.sizeBytes);
+ stageInternal = true;
+ } else {
+ // External we're going to copy existing install into our
+ // container, so we need footprint of both.
+ checkExternalStorage(params.sizeBytes + existingSize);
+ stageInternal = false;
+ }
} else {
throw new IllegalArgumentException("Invalid install mode: " + params.mode);
}
@@ -636,11 +659,7 @@
}
final String cid = "smdl" + sessionId + ".tmp";
-
- // Round up to nearest MB, plus another MB for filesystem overhead
- final int sizeMb = (int) ((sizeBytes + MB_IN_BYTES) / MB_IN_BYTES) + 1;
-
- if (PackageHelper.createSdDir(sizeMb, cid, PackageManagerService.getEncryptKey(),
+ if (PackageHelper.createSdDir(sizeBytes, cid, PackageManagerService.getEncryptKey(),
Process.SYSTEM_UID, true) == null) {
throw new IOException("Failed to create ASEC");
}
@@ -852,7 +871,7 @@
final String existing = extras.getString(
PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
if (!TextUtils.isEmpty(existing)) {
- fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, existing);
+ fillIn.putExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME, existing);
}
}
try {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 38a2016..5264fc4 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -19,6 +19,7 @@
import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
import static android.content.pm.PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
+import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
import static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
@@ -38,6 +39,7 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.ApkLite;
+import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.Signature;
import android.os.Bundle;
@@ -47,6 +49,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
+import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.system.ErrnoException;
@@ -59,18 +62,21 @@
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.server.pm.PackageInstallerService.PackageInstallObserverAdapter;
+import libcore.io.IoUtils;
import libcore.io.Libcore;
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@@ -95,18 +101,9 @@
final SessionParams params;
final long createdMillis;
- /** Internal location where staged data is written. */
- final File internalStageDir;
- /** External container where staged data is written. */
- final String externalStageCid;
-
- /**
- * When a {@link SessionParams#MODE_INHERIT_EXISTING} session is installed
- * into an ASEC, this is the container where the stage is combined with the
- * existing install.
- */
- // TODO: persist this cid once we start splicing
- String combinedCid;
+ /** Staging location where client data is written. */
+ final File stageDir;
+ final String stageCid;
/** Note that UID is not persisted; it's always derived at runtime. */
final int installerUid;
@@ -133,20 +130,6 @@
private String mFinalMessage;
@GuardedBy("mLock")
- private File mResolvedStageDir;
-
- /**
- * Path to the resolved base APK for this session, which may point at an APK
- * inside the session (when the session defines the base), or it may point
- * at the existing base APK (when adding splits to an existing app).
- * <p>
- * This is used when confirming permissions, since we can't fully stage the
- * session inside an ASEC before confirming with user.
- */
- @GuardedBy("mLock")
- private String mResolvedBaseCodePath;
-
- @GuardedBy("mLock")
private ArrayList<FileBridge> mBridges = new ArrayList<>();
@GuardedBy("mLock")
@@ -157,6 +140,25 @@
private int mVersionCode;
private Signature[] mSignatures;
+ /**
+ * Path to the validated base APK for this session, which may point at an
+ * APK inside the session (when the session defines the base), or it may
+ * point at the existing base APK (when adding splits to an existing app).
+ * <p>
+ * This is used when confirming permissions, since we can't fully stage the
+ * session inside an ASEC before confirming with user.
+ */
+ @GuardedBy("mLock")
+ private File mResolvedBaseFile;
+
+ @GuardedBy("mLock")
+ private File mResolvedStageDir;
+
+ @GuardedBy("mLock")
+ private final List<File> mResolvedStagedFiles = new ArrayList<>();
+ @GuardedBy("mLock")
+ private final List<File> mResolvedInheritedFiles = new ArrayList<>();
+
private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
@@ -168,9 +170,10 @@
try {
commitLocked();
} catch (PackageManagerException e) {
- Slog.e(TAG, "Install failed: " + e);
+ final String completeMsg = ExceptionUtils.getCompleteMessage(e);
+ Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
destroyInternal();
- dispatchSessionFinished(e.error, e.getMessage(), null);
+ dispatchSessionFinished(e.error, completeMsg, null);
}
return true;
@@ -181,7 +184,7 @@
public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
Context context, PackageManagerService pm, Looper looper, int sessionId, int userId,
String installerPackageName, SessionParams params, long createdMillis,
- File internalStageDir, String externalStageCid, boolean sealed) {
+ File stageDir, String stageCid, boolean sealed) {
mCallback = callback;
mContext = context;
mPm = pm;
@@ -192,12 +195,12 @@
this.installerPackageName = installerPackageName;
this.params = params;
this.createdMillis = createdMillis;
- this.internalStageDir = internalStageDir;
- this.externalStageCid = externalStageCid;
+ this.stageDir = stageDir;
+ this.stageCid = stageCid;
- if ((internalStageDir == null) == (externalStageCid == null)) {
+ if ((stageDir == null) == (stageCid == null)) {
throw new IllegalArgumentException(
- "Exactly one of internal or external stage must be set");
+ "Exactly one of stageDir or stageCid stage must be set");
}
mSealed = sealed;
@@ -220,7 +223,8 @@
synchronized (mLock) {
info.sessionId = sessionId;
info.installerPackageName = installerPackageName;
- info.resolvedBaseCodePath = mResolvedBaseCodePath;
+ info.resolvedBaseCodePath = (mResolvedBaseFile != null) ?
+ mResolvedBaseFile.getAbsolutePath() : null;
info.progress = mProgress;
info.sealed = mSealed;
info.open = mOpenCount.get() > 0;
@@ -253,18 +257,17 @@
* might point at an ASEC mount point, which is why we delay path resolution
* until someone actively works with the session.
*/
- private File getStageDir() throws IOException {
+ private File resolveStageDir() throws IOException {
synchronized (mLock) {
if (mResolvedStageDir == null) {
- if (internalStageDir != null) {
- mResolvedStageDir = internalStageDir;
+ if (stageDir != null) {
+ mResolvedStageDir = stageDir;
} else {
- final String path = PackageHelper.getSdDir(externalStageCid);
+ final String path = PackageHelper.getSdDir(stageCid);
if (path != null) {
mResolvedStageDir = new File(path);
} else {
- throw new IOException(
- "Failed to resolve container path for " + externalStageCid);
+ throw new IOException("Failed to resolve path to container " + stageCid);
}
}
}
@@ -306,7 +309,7 @@
public String[] getNames() {
assertNotSealed("getNames");
try {
- return getStageDir().list();
+ return resolveStageDir().list();
} catch (IOException e) {
throw ExceptionUtils.wrap(e);
}
@@ -339,8 +342,10 @@
if (!FileUtils.isValidExtFilename(name)) {
throw new IllegalArgumentException("Invalid name: " + name);
}
- final File target = new File(getStageDir(), name);
+ final File target = new File(resolveStageDir(), name);
+ // TODO: this should delegate to DCS so the system process avoids
+ // holding open FDs into containers.
final FileDescriptor targetFd = Libcore.os.open(target.getAbsolutePath(),
O_CREAT | O_WRONLY, 0644);
Os.chmod(target.getAbsolutePath(), 0644);
@@ -350,7 +355,8 @@
if (lengthBytes > 0) {
final StructStat stat = Libcore.os.fstat(targetFd);
final long deltaBytes = lengthBytes - stat.st_size;
- if (deltaBytes > 0) {
+ // Only need to free up space when writing to internal stage
+ if (stageDir != null && deltaBytes > 0) {
mPm.freeStorage(deltaBytes);
}
Libcore.os.posix_fallocate(targetFd, 0, lengthBytes);
@@ -385,7 +391,7 @@
if (!FileUtils.isValidExtFilename(name)) {
throw new IllegalArgumentException("Invalid name: " + name);
}
- final File target = new File(getStageDir(), name);
+ final File target = new File(resolveStageDir(), name);
final FileDescriptor targetFd = Libcore.os.open(target.getAbsolutePath(), O_RDONLY, 0);
return new ParcelFileDescriptor(targetFd);
@@ -424,22 +430,21 @@
mCallback.onSessionSealed(this);
}
- final File stageDir;
try {
- stageDir = getStageDir();
+ resolveStageDir();
} catch (IOException e) {
throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
- "Failed to resolve stage dir", e);
+ "Failed to resolve stage location", e);
}
// Verify that stage looks sane with respect to existing application.
// This currently only ensures packageName, versionCode, and certificate
// consistency.
- validateInstallLocked(stageDir);
+ validateInstallLocked();
Preconditions.checkNotNull(mPackageName);
Preconditions.checkNotNull(mSignatures);
- Preconditions.checkNotNull(mResolvedBaseCodePath);
+ Preconditions.checkNotNull(mResolvedBaseFile);
if (!mPermissionsAccepted) {
// User needs to accept permissions; give installer an intent they
@@ -454,17 +459,41 @@
return;
}
+ if (stageCid != null) {
+ // Figure out the final installed size and resize the container once
+ // and for all. Internally the parser handles straddling between two
+ // locations when inheriting.
+ final long finalSize = calculateInstalledSize();
+ resizeContainer(stageCid, finalSize);
+ }
+
// Inherit any packages and native libraries from existing install that
// haven't been overridden.
if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
- // TODO: implement splicing into existing ASEC
- spliceExistingFilesIntoStage(stageDir);
+ try {
+ if (stageCid != null) {
+ // TODO: this should delegate to DCS so the system process
+ // avoids holding open FDs into containers.
+ copyFiles(mResolvedInheritedFiles, resolveStageDir());
+ } else {
+ linkFiles(mResolvedInheritedFiles, resolveStageDir());
+ }
+ } catch (IOException e) {
+ throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
+ "Failed to inherit existing install", e);
+ }
}
// TODO: surface more granular state from dexopt
mCallback.onSessionProgressChanged(this, 0.9f);
- // TODO: for ASEC based applications, grow and stream in packages
+ // Unpack native libraries
+ extractNativeLibraries(mResolvedStageDir, params.abiOverride);
+
+ // Container is ready to go, let's seal it up!
+ if (stageCid != null) {
+ finalizeAndFixContainer(stageCid);
+ }
// We've reached point of no return; call into PMS to install the stage.
// Regardless of success or failure we always destroy session.
@@ -482,7 +511,7 @@
}
};
- mPm.installStage(mPackageName, this.internalStageDir, this.externalStageCid, localObserver,
+ mPm.installStage(mPackageName, stageDir, stageCid, localObserver,
params, installerPackageName, installerUid, new UserHandle(userId));
}
@@ -490,81 +519,88 @@
* Validate install by confirming that all application packages are have
* consistent package name, version code, and signing certificates.
* <p>
+ * Clears and populates {@link #mResolvedBaseFile},
+ * {@link #mResolvedStagedFiles}, and {@link #mResolvedInheritedFiles}.
+ * <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 {
+ private void validateInstallLocked() throws PackageManagerException {
mPackageName = null;
mVersionCode = -1;
mSignatures = null;
- mResolvedBaseCodePath = null;
- final File[] files = stageDir.listFiles();
+ mResolvedBaseFile = null;
+ mResolvedStagedFiles.clear();
+ mResolvedInheritedFiles.clear();
+
+ final File[] files = mResolvedStageDir.listFiles();
if (ArrayUtils.isEmpty(files)) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
}
// Verify that all staged packages are internally consistent
- final ArraySet<String> seenSplits = new ArraySet<>();
+ final ArraySet<String> stagedSplits = 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;
+ final ApkLite apk;
try {
- info = PackageParser.parseApkLite(file, PackageParser.PARSE_COLLECT_CERTIFICATES);
+ apk = PackageParser.parseApkLite(file, PackageParser.PARSE_COLLECT_CERTIFICATES);
} catch (PackageParserException e) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
"Failed to parse " + file + ": " + e);
}
- if (!seenSplits.add(info.splitName)) {
+ if (!stagedSplits.add(apk.splitName)) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
- "Split " + info.splitName + " was defined multiple times");
+ "Split " + apk.splitName + " was defined multiple times");
}
// Use first package to define unknown values
if (mPackageName == null) {
- mPackageName = info.packageName;
- mVersionCode = info.versionCode;
+ mPackageName = apk.packageName;
+ mVersionCode = apk.versionCode;
}
if (mSignatures == null) {
- mSignatures = info.signatures;
+ mSignatures = apk.signatures;
}
- assertPackageConsistent(String.valueOf(file), info.packageName, info.versionCode,
- info.signatures);
+ assertApkConsistent(String.valueOf(file), apk);
// Take this opportunity to enforce uniform naming
final String targetName;
- if (info.splitName == null) {
+ if (apk.splitName == null) {
targetName = "base.apk";
} else {
- targetName = "split_" + info.splitName + ".apk";
+ targetName = "split_" + apk.splitName + ".apk";
}
if (!FileUtils.isValidExtFilename(targetName)) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
"Invalid filename: " + targetName);
}
- final File targetFile = new File(stageDir, targetName);
+ final File targetFile = new File(mResolvedStageDir, targetName);
if (!file.equals(targetFile)) {
file.renameTo(targetFile);
}
// Base is coming from session
- if (info.splitName == null) {
- mResolvedBaseCodePath = targetFile.getAbsolutePath();
+ if (apk.splitName == null) {
+ mResolvedBaseFile = targetFile;
}
+
+ mResolvedStagedFiles.add(targetFile);
}
if (params.mode == SessionParams.MODE_FULL_INSTALL) {
// Full installs must include a base package
- if (!seenSplits.contains(null)) {
+ if (!stagedSplits.contains(null)) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
"Full install must include a base package");
}
@@ -577,67 +613,204 @@
"Missing existing base package for " + mPackageName);
}
- // Base might be inherited from existing install
- if (mResolvedBaseCodePath == null) {
- mResolvedBaseCodePath = app.getBaseCodePath();
- }
-
- final ApkLite info;
+ final PackageLite existing;
+ final ApkLite existingBase;
try {
- info = PackageParser.parseApkLite(new File(app.getBaseCodePath()),
+ existing = PackageParser.parsePackageLite(new File(app.getCodePath()), 0);
+ existingBase = PackageParser.parseApkLite(new File(app.getBaseCodePath()),
PackageParser.PARSE_COLLECT_CERTIFICATES);
} catch (PackageParserException e) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
- "Failed to parse existing base " + app.getBaseCodePath() + ": " + e);
+ "Failed to parse existing package " + app.getCodePath() + ": " + e);
}
- assertPackageConsistent("Existing base", info.packageName, info.versionCode,
- info.signatures);
+ assertApkConsistent("Existing base", existingBase);
+
+ // Inherit base if not overridden
+ if (mResolvedBaseFile == null) {
+ mResolvedBaseFile = new File(app.getBaseCodePath());
+ mResolvedInheritedFiles.add(mResolvedBaseFile);
+ }
+
+ // Inherit splits if not overridden
+ if (!ArrayUtils.isEmpty(existing.splitNames)) {
+ for (int i = 0; i < existing.splitNames.length; i++) {
+ final String splitName = existing.splitNames[i];
+ final File splitFile = new File(existing.splitCodePaths[i]);
+
+ if (!stagedSplits.contains(splitName)) {
+ mResolvedInheritedFiles.add(splitFile);
+ }
+ }
+ }
}
}
- private void assertPackageConsistent(String tag, String packageName, int versionCode,
- Signature[] signatures) throws PackageManagerException {
- if (!mPackageName.equals(packageName)) {
+ private void assertApkConsistent(String tag, ApkLite apk) throws PackageManagerException {
+ if (!mPackageName.equals(apk.packageName)) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag + " package "
- + packageName + " inconsistent with " + mPackageName);
+ + apk.packageName + " inconsistent with " + mPackageName);
}
- if (mVersionCode != versionCode) {
+ if (mVersionCode != apk.versionCode) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag
- + " version code " + versionCode + " inconsistent with "
+ + " version code " + apk.versionCode + " inconsistent with "
+ mVersionCode);
}
- if (!Signature.areExactMatch(mSignatures, signatures)) {
+ if (!Signature.areExactMatch(mSignatures, apk.signatures)) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
tag + " signatures are inconsistent");
}
}
/**
- * Application is already installed; splice existing files that haven't been
- * overridden into our stage.
+ * Calculate the final install footprint size, combining both staged and
+ * existing APKs together and including unpacked native code from both.
*/
- private void spliceExistingFilesIntoStage(File stageDir) throws PackageManagerException {
- final ApplicationInfo app = mPm.getApplicationInfo(mPackageName, 0, userId);
+ private long calculateInstalledSize() throws PackageManagerException {
+ Preconditions.checkNotNull(mResolvedBaseFile);
- int n = 0;
- final File[] oldFiles = new File(app.getCodePath()).listFiles();
- if (!ArrayUtils.isEmpty(oldFiles)) {
- for (File oldFile : oldFiles) {
- if (!PackageParser.isApkFile(oldFile)) continue;
+ final ApkLite baseApk;
+ try {
+ baseApk = PackageParser.parseApkLite(mResolvedBaseFile, 0);
+ } catch (PackageParserException e) {
+ throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
+ "Failed to parse base package " + mResolvedBaseFile + ": " + e);
+ }
- final File newFile = new File(stageDir, oldFile.getName());
- try {
- Os.link(oldFile.getAbsolutePath(), newFile.getAbsolutePath());
- n++;
- } catch (ErrnoException e) {
- throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
- "Failed to splice into stage", e);
- }
+ final List<String> splitPaths = new ArrayList<>();
+ for (File file : mResolvedStagedFiles) {
+ if (mResolvedBaseFile.equals(file)) continue;
+ splitPaths.add(file.getAbsolutePath());
+ }
+ for (File file : mResolvedInheritedFiles) {
+ if (mResolvedBaseFile.equals(file)) continue;
+ splitPaths.add(file.getAbsolutePath());
+ }
+
+ // This is kind of hacky; we're creating a half-parsed package that is
+ // straddled between the inherited and staged APKs.
+ final PackageLite pkg = new PackageLite(null, baseApk, null,
+ splitPaths.toArray(new String[splitPaths.size()]));
+ final boolean isForwardLocked =
+ (params.installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
+
+ try {
+ return PackageHelper.calculateInstalledSize(pkg, isForwardLocked, params.abiOverride);
+ } catch (IOException e) {
+ throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
+ "Failed to calculate install size", e);
+ }
+ }
+
+ private static void linkFiles(List<File> fromFiles, File toDir) throws IOException {
+ for (File fromFile : fromFiles) {
+ final File toFile = new File(toDir, fromFile.getName());
+ try {
+ if (LOGD) Slog.d(TAG, "Linking " + fromFile + " to " + toFile);
+ Os.link(fromFile.getAbsolutePath(), toFile.getAbsolutePath());
+ } catch (ErrnoException e) {
+ throw new IOException("Failed to link " + fromFile + " to " + toFile, e);
+ }
+ }
+ Slog.d(TAG, "Linked " + fromFiles.size() + " files into " + toDir);
+ }
+
+ private static void copyFiles(List<File> fromFiles, File toDir) throws IOException {
+ // Remove any partial files from previous attempt
+ for (File file : toDir.listFiles()) {
+ if (file.getName().endsWith(".tmp")) {
+ file.delete();
}
}
- if (LOGD) Slog.d(TAG, "Spliced " + n + " existing APKs into stage");
+ for (File fromFile : fromFiles) {
+ final File tmpFile = File.createTempFile("inherit", ".tmp", toDir);
+ if (LOGD) Slog.d(TAG, "Copying " + fromFile + " to " + tmpFile);
+ if (!FileUtils.copyFile(fromFile, tmpFile)) {
+ throw new IOException("Failed to copy " + fromFile + " to " + tmpFile);
+ }
+
+ final File toFile = new File(toDir, fromFile.getName());
+ if (LOGD) Slog.d(TAG, "Renaming " + tmpFile + " to " + toFile);
+ if (!tmpFile.renameTo(toFile)) {
+ throw new IOException("Failed to rename " + tmpFile + " to " + toFile);
+ }
+ }
+ Slog.d(TAG, "Copied " + fromFiles.size() + " files into " + toDir);
+ }
+
+ private static void extractNativeLibraries(File packageDir, String abiOverride)
+ throws PackageManagerException {
+ if (LOGD) Slog.v(TAG, "extractNativeLibraries()");
+
+ // Always start from a clean slate
+ final File libDir = new File(packageDir, NativeLibraryHelper.LIB_DIR_NAME);
+ NativeLibraryHelper.removeNativeBinariesFromDirLI(libDir, true);
+
+ NativeLibraryHelper.Handle handle = null;
+ try {
+ handle = NativeLibraryHelper.Handle.create(packageDir);
+ final int res = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libDir,
+ abiOverride);
+ if (res != PackageManager.INSTALL_SUCCEEDED) {
+ throw new PackageManagerException(res,
+ "Failed to extract native libraries, res=" + res);
+ }
+ } catch (IOException e) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Failed to extract native libraries", e);
+ } finally {
+ IoUtils.closeQuietly(handle);
+ }
+ }
+
+ private static void resizeContainer(String cid, long targetSize)
+ throws PackageManagerException {
+ String path = PackageHelper.getSdDir(cid);
+ if (path == null) {
+ throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
+ "Failed to find mounted " + cid);
+ }
+
+ final long currentSize = new File(path).getTotalSpace();
+ if (currentSize > targetSize) {
+ Slog.w(TAG, "Current size " + currentSize + " is larger than target size "
+ + targetSize + "; skipping resize");
+ return;
+ }
+
+ if (!PackageHelper.unMountSdDir(cid)) {
+ throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
+ "Failed to unmount " + cid + " before resize");
+ }
+
+ if (!PackageHelper.resizeSdDir(targetSize, cid,
+ PackageManagerService.getEncryptKey())) {
+ throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
+ "Failed to resize " + cid + " to " + targetSize + " bytes");
+ }
+
+ path = PackageHelper.mountSdDir(cid, PackageManagerService.getEncryptKey(),
+ Process.SYSTEM_UID, false);
+ if (path == null) {
+ throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
+ "Failed to mount " + cid + " after resize");
+ }
+ }
+
+ private void finalizeAndFixContainer(String cid) throws PackageManagerException {
+ if (!PackageHelper.finalizeSdDir(cid)) {
+ throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
+ "Failed to finalize container " + cid);
+ }
+
+ final int uid = mPm.getPackageUid(PackageManagerService.DEFAULT_CONTAINER_PACKAGE,
+ UserHandle.USER_OWNER);
+ final int gid = UserHandle.getSharedAppGid(uid);
+ if (!PackageHelper.fixSdPermissions(cid, gid, null)) {
+ throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
+ "Failed to fix permissions on container " + cid);
+ }
}
void setPermissionsResult(boolean accepted) {
@@ -694,12 +867,12 @@
mSealed = true;
mDestroyed = true;
}
- if (internalStageDir != null) {
- FileUtils.deleteContents(internalStageDir);
- internalStageDir.delete();
+ if (stageDir != null) {
+ FileUtils.deleteContents(stageDir);
+ stageDir.delete();
}
- if (externalStageCid != null) {
- PackageHelper.destroySdDir(externalStageCid);
+ if (stageCid != null) {
+ PackageHelper.destroySdDir(stageCid);
}
}
@@ -717,8 +890,8 @@
pw.printPair("installerPackageName", installerPackageName);
pw.printPair("installerUid", installerUid);
pw.printPair("createdMillis", createdMillis);
- pw.printPair("internalStageDir", internalStageDir);
- pw.printPair("externalStageCid", externalStageCid);
+ pw.printPair("stageDir", stageDir);
+ pw.printPair("stageCid", stageCid);
pw.println();
params.dump(pw);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index aa49b27..f06992a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -50,6 +50,8 @@
import static android.system.OsConstants.O_RDWR;
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.content.NativeLibraryHelper.LIB64_DIR_NAME;
+import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
import static com.android.internal.util.ArrayUtils.appendInt;
import static com.android.internal.util.ArrayUtils.removeInt;
@@ -298,9 +300,6 @@
private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
- private static final String LIB_DIR_NAME = "lib";
- private static final String LIB64_DIR_NAME = "lib64";
-
private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay";
private static String sPreferredInstructionSet;
@@ -1121,7 +1120,7 @@
if ((state != null) && !state.timeoutExtended()) {
final InstallArgs args = state.getInstallArgs();
- final Uri originUri = Uri.fromFile(args.originFile);
+ final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
Slog.i(TAG, "Verification timed out for " + originUri);
mPendingVerification.remove(verificationId);
@@ -1168,7 +1167,7 @@
mPendingVerification.remove(verificationId);
final InstallArgs args = state.getInstallArgs();
- final Uri originUri = Uri.fromFile(args.originFile);
+ final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
int ret;
if (state.isInstallAllowed()) {
@@ -4271,7 +4270,7 @@
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
- getAppDexInstructionSets(ps), isMultiArch(ps));
+ getAppDexInstructionSets(ps));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
@@ -4334,7 +4333,7 @@
+ " better than installed " + ps.versionCode);
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
- getAppDexInstructionSets(ps), isMultiArch(ps));
+ getAppDexInstructionSets(ps));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
@@ -5527,8 +5526,9 @@
if (isAsec) {
abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
} else {
- abi32 = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
- nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS, useIsaSpecificSubdirs);
+ abi32 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
+ nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS,
+ useIsaSpecificSubdirs);
}
}
@@ -5539,8 +5539,9 @@
if (isAsec) {
abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
} else {
- abi64 = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
- nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS, useIsaSpecificSubdirs);
+ abi64 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
+ nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS,
+ useIsaSpecificSubdirs);
}
}
@@ -5578,7 +5579,7 @@
if (isAsec) {
copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList);
} else {
- copyRet = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
+ copyRet = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
nativeLibraryRoot, abiList, useIsaSpecificSubdirs);
}
@@ -7782,7 +7783,8 @@
verificationParams.setInstallerUid(uid);
final Message msg = mHandler.obtainMessage(INIT_COPY);
- msg.obj = new InstallParams(originFile, null, false, observer, filteredFlags,
+ final OriginInfo origin = new OriginInfo(originFile, null, false);
+ msg.obj = new InstallParams(origin, observer, filteredFlags,
installerPackageName, verificationParams, user, packageAbiOverride);
mHandler.sendMessage(msg);
}
@@ -7794,7 +7796,8 @@
params.referrerUri, installerUid, null);
final Message msg = mHandler.obtainMessage(INIT_COPY);
- msg.obj = new InstallParams(stagedDir, stagedCid, true, observer, params.installFlags,
+ final OriginInfo origin = new OriginInfo(stagedDir, stagedCid, true);
+ msg.obj = new InstallParams(origin, observer, params.installFlags,
installerPackageName, verifParams, user, params.abiOverride);
mHandler.sendMessage(msg);
}
@@ -8487,22 +8490,45 @@
}
}
- class InstallParams extends HandlerParams {
+ static class OriginInfo {
/**
* Location where install is coming from, before it has been
* copied/renamed into place. This could be a single monolithic APK
* file, or a cluster directory. This location may be untrusted.
*/
- final File originFile;
- final String originCid;
+ final File file;
+ final String cid;
/**
- * Flag indicating that {@link #originFile} or {@link #originCid} has
- * already been staged, meaning downstream users don't need to
- * defensively copy the contents.
+ * Flag indicating that {@link #file} or {@link #cid} has already been
+ * staged, meaning downstream users don't need to defensively copy the
+ * contents.
*/
- boolean originStaged;
+ final boolean staged;
+ final String resolvedPath;
+ final File resolvedFile;
+
+ public OriginInfo(File file, String cid, boolean staged) {
+ this.file = file;
+ this.cid = cid;
+ this.staged = staged;
+
+ if (cid != null) {
+ resolvedPath = PackageHelper.getSdDir(cid);
+ resolvedFile = new File(resolvedPath);
+ } else if (file != null) {
+ resolvedPath = file.getAbsolutePath();
+ resolvedFile = file;
+ } else {
+ resolvedPath = null;
+ resolvedFile = null;
+ }
+ }
+ }
+
+ class InstallParams extends HandlerParams {
+ final OriginInfo origin;
final IPackageInstallObserver2 observer;
int flags;
final String installerPackageName;
@@ -8510,15 +8536,12 @@
private InstallArgs mArgs;
private int mRet;
final String packageAbiOverride;
- boolean multiArch;
- InstallParams(File originFile, String originCid, boolean originStaged,
- IPackageInstallObserver2 observer, int flags, String installerPackageName,
- VerificationParams verificationParams, UserHandle user, String packageAbiOverride) {
+ InstallParams(OriginInfo origin, IPackageInstallObserver2 observer, int flags,
+ String installerPackageName, VerificationParams verificationParams, UserHandle user,
+ String packageAbiOverride) {
super(user);
- this.originFile = originFile;
- this.originCid = originCid;
- this.originStaged = originStaged;
+ this.origin = origin;
this.observer = observer;
this.flags = flags;
this.installerPackageName = installerPackageName;
@@ -8529,7 +8552,7 @@
@Override
public String toString() {
return "InstallParams{" + Integer.toHexString(System.identityHashCode(this))
- + " file=" + originFile + " cid=" + originCid + "}";
+ + " file=" + origin.file + " cid=" + origin.cid + "}";
}
public ManifestDigest getManifestDigest() {
@@ -8608,11 +8631,11 @@
int ret = PackageManager.INSTALL_SUCCEEDED;
// If we're already staged, we've firmly committed to an install location
- if (originStaged) {
- if (originFile != null) {
+ if (origin.staged) {
+ if (origin.file != null) {
flags |= PackageManager.INSTALL_INTERNAL;
flags &= ~PackageManager.INSTALL_EXTERNAL;
- } else if (originCid != null) {
+ } else if (origin.cid != null) {
flags |= PackageManager.INSTALL_EXTERNAL;
flags &= ~PackageManager.INSTALL_INTERNAL;
} else {
@@ -8622,6 +8645,7 @@
final boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
final boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
+
PackageInfoLite pkgLite = null;
if (onInt && onSd) {
@@ -8629,21 +8653,14 @@
Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} else {
- // Remote call to find out default install location
- final String originPath = originFile.getAbsolutePath();
- pkgLite = mContainerService.getMinimalPackageInfo(originPath, flags,
+ pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, flags,
packageAbiOverride);
- // Keep track of whether this package is a multiArch package until
- // we perform a full scan of it. We need to do this because we might
- // end up extracting the package shared libraries before we perform
- // a full scan.
- multiArch = pkgLite.multiArch;
/*
* If we have too little free space, try to free cache
* before giving up.
*/
- if (!originStaged && pkgLite.recommendedInstallLocation
+ if (!origin.staged && pkgLite.recommendedInstallLocation
== PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
// TODO: focus freeing disk space on the target device
final StorageManager storage = StorageManager.from(mContext);
@@ -8651,11 +8668,11 @@
Environment.getDataDirectory());
final long sizeBytes = mContainerService.calculateInstalledSize(
- originPath, isForwardLocked(), packageAbiOverride);
+ origin.resolvedPath, isForwardLocked(), packageAbiOverride);
if (mInstaller.freeCache(sizeBytes + lowThreshold) >= 0) {
- pkgLite = mContainerService.getMinimalPackageInfo(originPath, flags,
- packageAbiOverride);
+ pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath,
+ flags, packageAbiOverride);
}
/*
@@ -8729,10 +8746,10 @@
final int requiredUid = mRequiredVerifierPackage == null ? -1
: getPackageUid(mRequiredVerifierPackage, userIdentifier);
if (requiredUid != -1 && isVerificationEnabled(userIdentifier, flags)) {
- // TODO: send verifier the install session instead of uri
final Intent verification = new Intent(
Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
- verification.setDataAndType(Uri.fromFile(originFile), PACKAGE_MIME_TYPE);
+ verification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
+ PACKAGE_MIME_TYPE);
verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
final List<ResolveInfo> receivers = queryIntentReceivers(verification,
@@ -8890,8 +8907,7 @@
int mRet;
MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags,
- String packageName, String[] instructionSets, int uid, UserHandle user,
- boolean isMultiArch) {
+ String packageName, String[] instructionSets, int uid, UserHandle user) {
super(user);
this.srcArgs = srcArgs;
this.observer = observer;
@@ -8901,7 +8917,7 @@
if (srcArgs != null) {
final String codePath = srcArgs.getCodePath();
targetArgs = createInstallArgsForMoveTarget(codePath, flags, packageName,
- instructionSets, isMultiArch);
+ instructionSets);
} else {
targetArgs = null;
}
@@ -9002,8 +9018,6 @@
}
private InstallArgs createInstallArgs(InstallParams params) {
- // TODO: extend to support incoming zero-copy locations
-
if (installOnSd(params.flags) || params.isForwardLocked()) {
return new AsecInstallArgs(params);
} else {
@@ -9016,8 +9030,7 @@
* when cleaning up old installs, or used as a move source.
*/
private InstallArgs createInstallArgsForExisting(int flags, String codePath,
- String resourcePath, String nativeLibraryRoot, String[] instructionSets,
- boolean isMultiArch) {
+ String resourcePath, String nativeLibraryRoot, String[] instructionSets) {
final boolean isInAsec;
if (installOnSd(flags)) {
/* Apps on SD card are always in ASEC containers. */
@@ -9035,33 +9048,29 @@
if (isInAsec) {
return new AsecInstallArgs(codePath, instructionSets,
- installOnSd(flags), installForwardLocked(flags), isMultiArch);
+ installOnSd(flags), installForwardLocked(flags));
} else {
return new FileInstallArgs(codePath, resourcePath, nativeLibraryRoot,
- instructionSets, isMultiArch);
+ instructionSets);
}
}
private InstallArgs createInstallArgsForMoveTarget(String codePath, int flags, String pkgName,
- String[] instructionSets, boolean isMultiArch) {
+ String[] instructionSets) {
final File codeFile = new File(codePath);
if (installOnSd(flags) || installForwardLocked(flags)) {
String cid = getNextCodePath(codePath, pkgName, "/"
+ AsecInstallArgs.RES_FILE_NAME);
return new AsecInstallArgs(codeFile, cid, instructionSets, installOnSd(flags),
- installForwardLocked(flags), isMultiArch);
+ installForwardLocked(flags));
} else {
- return new FileInstallArgs(codeFile, instructionSets, isMultiArch);
+ return new FileInstallArgs(codeFile, instructionSets);
}
}
static abstract class InstallArgs {
- /** @see InstallParams#originFile */
- final File originFile;
- /** @see InstallParams#originStaged */
- final boolean originStaged;
-
- // TODO: define inherit location
+ /** @see InstallParams#origin */
+ final OriginInfo origin;
final IPackageInstallObserver2 observer;
// Always refers to PackageManager flags only
@@ -9070,19 +9079,16 @@
final ManifestDigest manifestDigest;
final UserHandle user;
final String abiOverride;
- final boolean multiArch;
// The list of instruction sets supported by this app. This is currently
// only used during the rmdex() phase to clean up resources. We can get rid of this
// if we move dex files under the common app path.
/* nullable */ String[] instructionSets;
- InstallArgs(File originFile, boolean originStaged, IPackageInstallObserver2 observer,
- int flags, String installerPackageName, ManifestDigest manifestDigest,
- UserHandle user, String[] instructionSets,
- String abiOverride, boolean multiArch) {
- this.originFile = originFile;
- this.originStaged = originStaged;
+ InstallArgs(OriginInfo origin, IPackageInstallObserver2 observer, int flags,
+ String installerPackageName, ManifestDigest manifestDigest, UserHandle user,
+ String[] instructionSets, String abiOverride) {
+ this.origin = origin;
this.flags = flags;
this.observer = observer;
this.installerPackageName = installerPackageName;
@@ -9090,7 +9096,6 @@
this.user = user;
this.instructionSets = instructionSets;
this.abiOverride = abiOverride;
- this.multiArch = multiArch;
}
abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
@@ -9161,10 +9166,9 @@
/** New install */
FileInstallArgs(InstallParams params) {
- super(params.originFile, params.originStaged, params.observer, params.flags,
+ super(params.origin, params.observer, params.flags,
params.installerPackageName, params.getManifestDigest(), params.getUser(),
- null /* instruction sets */, params.packageAbiOverride,
- params.multiArch);
+ null /* instruction sets */, params.packageAbiOverride);
if (isFwdLocked()) {
throw new IllegalArgumentException("Forward locking only supported in ASEC");
}
@@ -9172,8 +9176,8 @@
/** Existing install */
FileInstallArgs(String codePath, String resourcePath, String legacyNativeLibraryPath,
- String[] instructionSets, boolean isMultiArch) {
- super(null, false, null, 0, null, null, null, instructionSets, null, isMultiArch);
+ String[] instructionSets) {
+ super(new OriginInfo(null, null, false), null, 0, null, null, null, instructionSets, null);
this.codeFile = (codePath != null) ? new File(codePath) : null;
this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
this.legacyNativeLibraryPath = (legacyNativeLibraryPath != null) ?
@@ -9181,13 +9185,12 @@
}
/** New install from existing */
- FileInstallArgs(File originFile, String[] instructionSets, boolean isMultiArch) {
- super(originFile, false, null, 0, null, null, null, instructionSets, null,
- isMultiArch);
+ FileInstallArgs(File originFile, String[] instructionSets) {
+ super(new OriginInfo(originFile, null, false), null, 0, null, null, null, instructionSets, null);
}
boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
- final long sizeBytes = imcs.calculateInstalledSize(originFile.getAbsolutePath(),
+ final long sizeBytes = imcs.calculateInstalledSize(origin.file.getAbsolutePath(),
isFwdLocked(), abiOverride);
final StorageManager storage = StorageManager.from(mContext);
@@ -9195,53 +9198,53 @@
}
int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
- int ret = PackageManager.INSTALL_SUCCEEDED;
+ if (origin.staged) {
+ Slog.d(TAG, origin.file + " already staged; skipping copy");
+ codeFile = origin.file;
+ resourceFile = origin.file;
+ return PackageManager.INSTALL_SUCCEEDED;
+ }
- if (originStaged) {
- Slog.d(TAG, originFile + " already staged; skipping copy");
- codeFile = originFile;
- resourceFile = originFile;
- } else {
- try {
- final File tempDir = mInstallerService.allocateInternalStageDirLegacy();
- codeFile = tempDir;
- resourceFile = tempDir;
- } catch (IOException e) {
- Slog.w(TAG, "Failed to create copy file: " + e);
- return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- }
+ try {
+ final File tempDir = mInstallerService.allocateInternalStageDirLegacy();
+ codeFile = tempDir;
+ resourceFile = tempDir;
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to create copy file: " + e);
+ return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ }
- final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() {
- @Override
- public ParcelFileDescriptor open(String name, int mode) throws RemoteException {
- if (!FileUtils.isValidExtFilename(name)) {
- throw new IllegalArgumentException("Invalid filename: " + name);
- }
- try {
- final File file = new File(codeFile, name);
- final FileDescriptor fd = Os.open(file.getAbsolutePath(),
- O_RDWR | O_CREAT, 0644);
- Os.chmod(file.getAbsolutePath(), 0644);
- return new ParcelFileDescriptor(fd);
- } catch (ErrnoException e) {
- throw new RemoteException("Failed to open: " + e.getMessage());
- }
+ final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() {
+ @Override
+ public ParcelFileDescriptor open(String name, int mode) throws RemoteException {
+ if (!FileUtils.isValidExtFilename(name)) {
+ throw new IllegalArgumentException("Invalid filename: " + name);
}
- };
-
- ret = imcs.copyPackage(originFile.getAbsolutePath(), target);
- if (ret != PackageManager.INSTALL_SUCCEEDED) {
- Slog.e(TAG, "Failed to copy package");
- return ret;
+ try {
+ final File file = new File(codeFile, name);
+ final FileDescriptor fd = Os.open(file.getAbsolutePath(),
+ O_RDWR | O_CREAT, 0644);
+ Os.chmod(file.getAbsolutePath(), 0644);
+ return new ParcelFileDescriptor(fd);
+ } catch (ErrnoException e) {
+ throw new RemoteException("Failed to open: " + e.getMessage());
+ }
}
+ };
+
+ int ret = PackageManager.INSTALL_SUCCEEDED;
+ ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);
+ if (ret != PackageManager.INSTALL_SUCCEEDED) {
+ Slog.e(TAG, "Failed to copy package");
+ return ret;
}
final File libraryRoot = new File(codeFile, LIB_DIR_NAME);
NativeLibraryHelper.Handle handle = null;
try {
handle = NativeLibraryHelper.Handle.create(codeFile);
- ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, libraryRoot,
- abiOverride, multiArch);
+ ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
+ abiOverride);
} catch (IOException e) {
Slog.e(TAG, "Copying native libraries failed", e);
ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
@@ -9429,18 +9432,18 @@
/** New install */
AsecInstallArgs(InstallParams params) {
- super(params.originFile, params.originStaged, params.observer, params.flags,
+ super(params.origin, params.observer, params.flags,
params.installerPackageName, params.getManifestDigest(),
params.getUser(), null /* instruction sets */,
- params.packageAbiOverride, params.multiArch);
+ params.packageAbiOverride);
}
/** Existing install */
AsecInstallArgs(String fullCodePath, String[] instructionSets,
- boolean isExternal, boolean isForwardLocked, boolean isMultiArch) {
- super(null, false, null, (isExternal ? INSTALL_EXTERNAL : 0)
+ boolean isExternal, boolean isForwardLocked) {
+ super(new OriginInfo(null, null, false), null, (isExternal ? INSTALL_EXTERNAL : 0)
| (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
- instructionSets, null, isMultiArch);
+ instructionSets, null);
// 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();
@@ -9454,21 +9457,20 @@
setMountPath(subStr1);
}
- AsecInstallArgs(String cid, String[] instructionSets, boolean isForwardLocked,
- boolean isMultiArch) {
- super(null, false, null, (isAsecExternal(cid) ? INSTALL_EXTERNAL : 0)
+ AsecInstallArgs(String cid, String[] instructionSets, boolean isForwardLocked) {
+ super(new OriginInfo(null, null, false), null, (isAsecExternal(cid) ? INSTALL_EXTERNAL : 0)
| (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
- instructionSets, null, isMultiArch);
+ instructionSets, null);
this.cid = cid;
setMountPath(PackageHelper.getSdDir(cid));
}
/** New install from existing */
AsecInstallArgs(File originPackageFile, String cid, String[] instructionSets,
- boolean isExternal, boolean isForwardLocked, boolean isMultiArch) {
- super(originPackageFile, false, null, (isExternal ? INSTALL_EXTERNAL : 0)
+ boolean isExternal, boolean isForwardLocked) {
+ super(new OriginInfo(originPackageFile, null, false), null, (isExternal ? INSTALL_EXTERNAL : 0)
| (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
- instructionSets, null, isMultiArch);
+ instructionSets, null);
this.cid = cid;
}
@@ -9496,7 +9498,13 @@
}
int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
- // TODO: if already staged, we only need to extract native code
+ if (origin.staged) {
+ Slog.d(TAG, origin.cid + " already staged; skipping copy");
+ cid = origin.cid;
+ setMountPath(PackageHelper.getSdDir(cid));
+ return PackageManager.INSTALL_SUCCEEDED;
+ }
+
if (temp) {
createCopyFile();
} else {
@@ -9508,7 +9516,7 @@
}
final String newMountPath = imcs.copyPackageToContainer(
- originFile.getAbsolutePath(), cid, getEncryptKey(), isExternal(),
+ origin.file.getAbsolutePath(), cid, getEncryptKey(), isExternal(),
isFwdLocked(), deriveAbiOverride(abiOverride, null /* settings */));
if (newMountPath != null) {
@@ -10133,8 +10141,7 @@
deletedPackage.applicationInfo.getCodePath(),
deletedPackage.applicationInfo.getResourcePath(),
deletedPackage.applicationInfo.nativeLibraryRootDir,
- getAppDexInstructionSets(deletedPackage.applicationInfo),
- isMultiArch(deletedPackage.applicationInfo));
+ getAppDexInstructionSets(deletedPackage.applicationInfo));
} else {
res.removedInfo.args = null;
}
@@ -10920,7 +10927,7 @@
if (deleteCodeAndResources && (outInfo != null)) {
outInfo.args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
- getAppDexInstructionSets(ps), isMultiArch(ps));
+ getAppDexInstructionSets(ps));
if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.args);
}
return true;
@@ -12725,7 +12732,7 @@
}
final AsecInstallArgs args = new AsecInstallArgs(cid,
- getAppDexInstructionSets(ps), isForwardLocked(ps), isMultiArch(ps));
+ getAppDexInstructionSets(ps), isForwardLocked(ps));
// The package status is changed only if the code path
// matches between settings and the container id.
if (ps.codePathString != null
@@ -13019,7 +13026,7 @@
* anyway.
*/
if (returnCode != PackageManager.MOVE_SUCCEEDED) {
- processPendingMove(new MoveParams(null, observer, 0, packageName, null, -1, user, false),
+ processPendingMove(new MoveParams(null, observer, 0, packageName, null, -1, user),
returnCode);
} else {
Message msg = mHandler.obtainMessage(INIT_COPY);
@@ -13027,9 +13034,9 @@
final boolean multiArch = isMultiArch(pkg.applicationInfo);
InstallArgs srcArgs = createInstallArgsForExisting(currFlags,
pkg.applicationInfo.getCodePath(), pkg.applicationInfo.getResourcePath(),
- pkg.applicationInfo.nativeLibraryRootDir, instructionSets, multiArch);
+ pkg.applicationInfo.nativeLibraryRootDir, instructionSets);
MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
- instructionSets, pkg.applicationInfo.uid, user, multiArch);
+ instructionSets, pkg.applicationInfo.uid, user);
msg.obj = mp;
mHandler.sendMessage(msg);
}
@@ -13107,8 +13114,8 @@
final int abi = NativeLibraryHelper.findSupportedAbi(
handle, Build.SUPPORTED_ABIS);
if (abi >= 0) {
- NativeLibraryHelper.copyNativeBinariesIfNeededLI(
- handle, newNativeDir, Build.SUPPORTED_ABIS[abi]);
+ NativeLibraryHelper.copyNativeBinaries(handle,
+ newNativeDir, Build.SUPPORTED_ABIS[abi]);
}
} catch (IOException ioe) {
Slog.w(TAG, "Unable to extract native libs for package :"
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 9734bd4..f47a07c 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -160,9 +160,9 @@
// Poll interval in milliseconds for watching boot animation finished.
private static final int BOOT_ANIMATION_POLL_INTERVAL = 200;
- // Used to send the hint to the PowerHAL indicating transitions
- // from and to the low power mode.
- private static final int POWER_HINT_LOW_POWER_MODE = 5;
+ // Power hints defined in hardware/libhardware/include/hardware/power.h.
+ private static final int POWER_HINT_INTERACTION = 2;
+ private static final int POWER_HINT_LOW_POWER = 5;
private final Context mContext;
private final ServiceThread mHandlerThread;
@@ -223,6 +223,9 @@
private long mLastUserActivityTime;
private long mLastUserActivityTimeNoChangeLights;
+ // Timestamp of last interactive power hint.
+ private long mLastInteractivePowerHintTime;
+
// A bitfield that summarizes the effect of the user activity timer.
// A zero value indicates that the user activity timer has expired.
private int mUserActivitySummary;
@@ -707,7 +710,7 @@
final boolean lowPowerModeEnabled = mLowPowerModeSetting;
if (mLowPowerModeEnabled != lowPowerModeEnabled) {
mLowPowerModeEnabled = lowPowerModeEnabled;
- powerHintInternal(POWER_HINT_LOW_POWER_MODE, lowPowerModeEnabled ? 1 : 0);
+ powerHintInternal(POWER_HINT_LOW_POWER, lowPowerModeEnabled ? 1 : 0);
mLowPowerModeEnabled = lowPowerModeEnabled;
BackgroundThread.getHandler().post(new Runnable() {
@Override
@@ -969,15 +972,25 @@
}
if (eventTime < mLastSleepTime || eventTime < mLastWakeTime
- || mWakefulness == WAKEFULNESS_ASLEEP || mWakefulness == WAKEFULNESS_DOZING
|| !mBootCompleted || !mSystemReady) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "userActivity");
try {
+ if (eventTime > mLastInteractivePowerHintTime) {
+ powerHintInternal(POWER_HINT_INTERACTION, 0);
+ mLastInteractivePowerHintTime = eventTime;
+ }
+
mNotifier.onUserActivity(event, uid);
+ if (mWakefulness == WAKEFULNESS_ASLEEP
+ || mWakefulness == WAKEFULNESS_DOZING
+ || (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) {
+ return false;
+ }
+
if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {
if (eventTime > mLastUserActivityTimeNoChangeLights
&& eventTime > mLastUserActivityTime) {
@@ -2319,6 +2332,8 @@
pw.println(" mLastUserActivityTime=" + TimeUtils.formatUptime(mLastUserActivityTime));
pw.println(" mLastUserActivityTimeNoChangeLights="
+ TimeUtils.formatUptime(mLastUserActivityTimeNoChangeLights));
+ pw.println(" mLastInteractivePowerHintTime="
+ + TimeUtils.formatUptime(mLastInteractivePowerHintTime));
pw.println(" mDisplayReady=" + mDisplayReady);
pw.println(" mHoldingWakeLockSuspendBlocker=" + mHoldingWakeLockSuspendBlocker);
pw.println(" mHoldingDisplaySuspendBlocker=" + mHoldingDisplaySuspendBlocker);
@@ -2774,6 +2789,10 @@
PowerManager.validateWakeLockParameters(flags, tag);
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+ if ((flags & PowerManager.DOZE_WAKE_LOCK) != 0) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, null);
+ }
if (ws != null && ws.size() != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.UPDATE_DEVICE_STATS, null);
@@ -2859,7 +2878,10 @@
public void userActivity(long eventTime, int event, int flags) {
final long now = SystemClock.uptimeMillis();
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
- != PackageManager.PERMISSION_GRANTED) {
+ != PackageManager.PERMISSION_GRANTED
+ && mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.USER_ACTIVITY)
+ != PackageManager.PERMISSION_GRANTED) {
// Once upon a time applications could call userActivity().
// Now we require the DEVICE_POWER permission. Log a warning and ignore the
// request instead of throwing a SecurityException so we don't break old apps.
@@ -2867,8 +2889,8 @@
if (now >= mLastWarningAboutUserActivityPermission + (5 * 60 * 1000)) {
mLastWarningAboutUserActivityPermission = now;
Slog.w(TAG, "Ignoring call to PowerManager.userActivity() because the "
- + "caller does not have DEVICE_POWER permission. "
- + "Please fix your app! "
+ + "caller does not have DEVICE_POWER or USER_ACTIVITY "
+ + "permission. Please fix your app! "
+ " pid=" + Binder.getCallingPid()
+ " uid=" + Binder.getCallingUid());
}
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index 0523af7..4c080cb 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -16,16 +16,22 @@
package com.android.server.trust;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.ServiceConnection;
+import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.os.PatternMatcher;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -43,6 +49,9 @@
* TrustManager and the actual TrustAgent.
*/
public class TrustAgentWrapper {
+ private static final String EXTRA_COMPONENT_NAME = "componentName";
+ private static final String TRUST_EXPIRED_ACTION = "android.server.trust.TRUST_EXPIRED_ACTION";
+ private static final String PERMISSION = "android.permission.PROVIDE_TRUST_AGENT";
private static final boolean DEBUG = false;
private static final String TAG = "TrustAgentWrapper";
@@ -79,6 +88,20 @@
private boolean mTrustDisabledByDpm;
private boolean mManagingTrust;
private IBinder mSetTrustAgentFeaturesToken;
+ private AlarmManager mAlarmManager;
+ private final Intent mAlarmIntent;
+
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ ComponentName component = intent.getParcelableExtra(EXTRA_COMPONENT_NAME);
+ if (TRUST_EXPIRED_ACTION.equals(intent.getAction())
+ && mName.equals(component)) {
+ mHandler.removeMessages(MSG_TRUST_TIMEOUT);
+ mHandler.sendEmptyMessage(MSG_TRUST_TIMEOUT);
+ }
+ }
+ };
private final Handler mHandler = new Handler() {
@Override
@@ -95,8 +118,10 @@
boolean initiatedByUser = msg.arg1 != 0;
long durationMs = msg.getData().getLong(DATA_DURATION);
if (durationMs > 0) {
- mHandler.removeMessages(MSG_TRUST_TIMEOUT);
- mHandler.sendEmptyMessageDelayed(MSG_TRUST_TIMEOUT, durationMs);
+ long expiration = SystemClock.elapsedRealtime() + durationMs;
+ PendingIntent op = PendingIntent.getBroadcast(mContext, 0, mAlarmIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, expiration, op);
}
mTrustManagerService.mArchive.logGrantTrust(mUserId, mName,
(mMessage != null ? mMessage.toString() : null),
@@ -106,6 +131,7 @@
case MSG_TRUST_TIMEOUT:
if (DEBUG) Slog.v(TAG, "Trust timed out : " + mName.flattenToShortString());
mTrustManagerService.mArchive.logTrustTimeout(mUserId, mName);
+ onTrustTimeout();
// Fall through.
case MSG_REVOKE_TRUST:
mTrusted = false;
@@ -212,8 +238,19 @@
Intent intent, UserHandle user) {
mContext = context;
mTrustManagerService = trustManagerService;
+ mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
mUserId = user.getIdentifier();
mName = intent.getComponent();
+
+ mAlarmIntent = new Intent(TRUST_EXPIRED_ACTION).putExtra(EXTRA_COMPONENT_NAME, mName);
+ mAlarmIntent.setData(Uri.parse(mAlarmIntent.toUri(Intent.URI_INTENT_SCHEME)));
+
+ final IntentFilter alarmFilter = new IntentFilter(TRUST_EXPIRED_ACTION);
+ alarmFilter.addDataScheme(mAlarmIntent.getScheme());
+ final String pathUri = mAlarmIntent.toUri(Intent.URI_INTENT_SCHEME);
+ alarmFilter.addDataPath(pathUri, PatternMatcher.PATTERN_LITERAL);
+ mContext.registerReceiver(mBroadcastReceiver, alarmFilter);
+
// Schedules a restart for when connecting times out. If the connection succeeds,
// the restart is canceled in mCallback's onConnected.
scheduleRestart();
@@ -227,6 +264,13 @@
Slog.w(TAG , "Remote Exception", e);
}
+ private void onTrustTimeout() {
+ try {
+ if (mTrustAgentService != null) mTrustAgentService.onTrustTimeout();
+ } catch (RemoteException e) {
+ onError(e);
+ }
+ }
/**
* @see android.service.trust.TrustAgentService#onUnlockAttempt(boolean)
*/
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/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index d05d0c7..61ad7aa 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -412,8 +412,9 @@
private final WindowManager mWindowManager;
- private final int mBorderWidth;
+ private final float mBorderWidth;
private final int mHalfBorderWidth;
+ private final int mDrawBorderInset;
private final ViewportWindow mWindow;
@@ -421,10 +422,11 @@
public MagnifiedViewport() {
mWindowManager = (WindowManager) mContext.getSystemService(Service.WINDOW_SERVICE);
- mBorderWidth = (int) TypedValue.applyDimension(
+ mBorderWidth = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, DEFAUTLT_BORDER_WIDTH_DIP,
mContext.getResources().getDisplayMetrics());
- mHalfBorderWidth = (int) (mBorderWidth + 0.5) / 2;
+ mHalfBorderWidth = (int) Math.ceil(mBorderWidth / 2);
+ mDrawBorderInset = (int) mBorderWidth / 2;
mWindow = new ViewportWindow(mContext);
recomputeBoundsLocked();
}
@@ -437,7 +439,8 @@
}
// If this message is pending we are in a rotation animation and do not want
// to show the border. We will do so when the pending message is handled.
- if (!mHandler.hasMessages(MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED)) {
+ if (!mHandler.hasMessages(
+ MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED)) {
setMagnifiedRegionBorderShownLocked(isMagnifyingLocked(), true);
}
}
@@ -513,8 +516,8 @@
visibleWindows.clear();
- magnifiedBounds.op(mHalfBorderWidth, mHalfBorderWidth,
- screenWidth - mHalfBorderWidth, screenHeight - mHalfBorderWidth,
+ magnifiedBounds.op(mDrawBorderInset, mDrawBorderInset,
+ screenWidth - mDrawBorderInset, screenHeight - mDrawBorderInset,
Region.Op.INTERSECT);
if (!mOldMagnifiedBounds.equals(magnifiedBounds)) {
@@ -527,8 +530,8 @@
Rect dirtyRect = mTempRect1;
if (mFullRedrawNeeded) {
mFullRedrawNeeded = false;
- dirtyRect.set(mHalfBorderWidth, mHalfBorderWidth,
- screenWidth - mHalfBorderWidth, screenHeight - mHalfBorderWidth);
+ dirtyRect.set(mDrawBorderInset, mDrawBorderInset,
+ screenWidth - mDrawBorderInset, screenHeight - mDrawBorderInset);
mWindow.invalidate(dirtyRect);
} else {
Region dirtyRegion = mTempRegion3;
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/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/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
index 2b693a3..402f0dd 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
@@ -51,11 +51,11 @@
final JobInfo task = new Builder(taskId, mComponent)
.setRequiresCharging(true)
- .setRequiredNetworkCapabilities(JobInfo.NetworkType.ANY)
- .setBackoffCriteria(initialBackoff, JobInfo.BackoffPolicy.EXPONENTIAL)
+ .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
+ .setBackoffCriteria(initialBackoff, JobInfo.BACKOFF_POLICY_EXPONENTIAL)
.setOverrideDeadline(runByMillis)
.setMinimumLatency(runFromMillis)
- .setIsPersisted(true)
+ .setPersisted(true)
.build();
final JobStatus ts = new JobStatus(task, SOME_UID);
mTaskStoreUnderTest.add(ts);
@@ -80,14 +80,14 @@
.setRequiresDeviceIdle(true)
.setPeriodic(10000L)
.setRequiresCharging(true)
- .setIsPersisted(true)
+ .setPersisted(true)
.build();
final JobInfo task2 = new Builder(12, mComponent)
.setMinimumLatency(5000L)
- .setBackoffCriteria(15000L, JobInfo.BackoffPolicy.LINEAR)
+ .setBackoffCriteria(15000L, JobInfo.BACKOFF_POLICY_LINEAR)
.setOverrideDeadline(30000L)
- .setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED)
- .setIsPersisted(true)
+ .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
+ .setPersisted(true)
.build();
final JobStatus taskStatus1 = new JobStatus(task1, SOME_UID);
final JobStatus taskStatus2 = new JobStatus(task2, SOME_UID);
@@ -121,7 +121,7 @@
.setRequiresDeviceIdle(true)
.setPeriodic(10000L)
.setRequiresCharging(true)
- .setIsPersisted(true);
+ .setPersisted(true);
PersistableBundle extras = new PersistableBundle();
extras.putDouble("hello", 3.2);
@@ -159,11 +159,11 @@
assertEquals("Invalid idle constraint.", first.isRequireDeviceIdle(),
second.isRequireDeviceIdle());
assertEquals("Invalid unmetered constraint.",
- first.getNetworkCapabilities() == JobInfo.NetworkType.UNMETERED,
- second.getNetworkCapabilities() == JobInfo.NetworkType.UNMETERED);
+ first.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED,
+ second.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED);
assertEquals("Invalid connectivity constraint.",
- first.getNetworkCapabilities() == JobInfo.NetworkType.ANY,
- second.getNetworkCapabilities() == JobInfo.NetworkType.ANY);
+ first.getNetworkType() == JobInfo.NETWORK_TYPE_ANY,
+ second.getNetworkType() == JobInfo.NETWORK_TYPE_ANY);
assertEquals("Invalid deadline constraint.",
first.hasLateConstraint(),
second.hasLateConstraint());
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
index 3a64984..376230b 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
@@ -16,6 +16,10 @@
package com.android.server.voiceinteraction;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
import android.hardware.soundtrigger.SoundTrigger;
import android.hardware.soundtrigger.SoundTrigger.Keyphrase;
@@ -27,6 +31,7 @@
import android.hardware.soundtrigger.SoundTrigger.RecognitionEvent;
import android.hardware.soundtrigger.SoundTrigger.SoundModelEvent;
import android.hardware.soundtrigger.SoundTriggerModule;
+import android.os.PowerManager;
import android.os.RemoteException;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
@@ -64,8 +69,10 @@
/** The properties for the DSP module */
private final SoundTriggerModule mModule;
private final Object mLock = new Object();
+ private final Context mContext;
private final TelephonyManager mTelephonyManager;
private final PhoneStateListener mPhoneStateListener;
+ private final PowerManager mPowerManager;
// TODO: Since many layers currently only deal with one recognition
// we simplify things by assuming one listener here too.
@@ -77,15 +84,19 @@
private RecognitionConfig mRecognitionConfig = null;
private boolean mRequested = false;
private boolean mCallActive = false;
+ private boolean mIsPowerSaveMode = false;
// Indicates if the native sound trigger service is disabled or not.
// This is an indirect indication of the microphone being open in some other application.
private boolean mServiceDisabled = false;
private boolean mStarted = false;
+ private PowerSaveModeListener mPowerSaveModeListener;
- SoundTriggerHelper(TelephonyManager telephonyManager) {
+ SoundTriggerHelper(Context context) {
ArrayList <ModuleProperties> modules = new ArrayList<>();
int status = SoundTrigger.listModules(modules);
- mTelephonyManager = telephonyManager;
+ mContext = context;
+ mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mPhoneStateListener = new MyCallStateListener();
if (status != SoundTrigger.STATUS_OK || modules.size() == 0) {
Slog.w(TAG, "listModules status=" + status + ", # of modules=" + modules.size());
@@ -133,6 +144,15 @@
mCallActive = mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE;
// Register for call state changes when the first call to start recognition occurs.
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+
+ // Register for power saver mode changes when the first call to start recognition
+ // occurs.
+ if (mPowerSaveModeListener == null) {
+ mPowerSaveModeListener = new PowerSaveModeListener();
+ mContext.registerReceiver(mPowerSaveModeListener,
+ new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
+ }
+ mIsPowerSaveMode = mPowerManager.isPowerSaveMode();
}
if (moduleProperties == null || mModule == null) {
@@ -338,16 +358,6 @@
}
}
- class MyCallStateListener extends PhoneStateListener {
- @Override
- public void onCallStateChanged(int state, String arg1) {
- if (DBG) Slog.d(TAG, "onCallStateChanged: " + state);
- synchronized (mLock) {
- onCallStateChangedLocked(TelephonyManager.CALL_STATE_IDLE != state);
- }
- }
- }
-
private void onCallStateChangedLocked(boolean callActive) {
if (mCallActive == callActive) {
// We consider multiple call states as being active
@@ -358,6 +368,14 @@
updateRecognitionLocked(true /* notify */);
}
+ private void onPowerSaveModeChangedLocked(boolean isPowerSaveMode) {
+ if (mIsPowerSaveMode == isPowerSaveMode) {
+ return;
+ }
+ mIsPowerSaveMode = isPowerSaveMode;
+ updateRecognitionLocked(true /* notify */);
+ }
+
private void onSoundModelUpdatedLocked(SoundModelEvent event) {
// TODO: Handle sound model update here.
}
@@ -438,7 +456,7 @@
return STATUS_OK;
}
- boolean start = mRequested && !mCallActive && !mServiceDisabled;
+ boolean start = mRequested && !mCallActive && !mServiceDisabled && !mIsPowerSaveMode;
if (start == mStarted) {
// No-op.
return STATUS_OK;
@@ -509,6 +527,36 @@
// Unregister from call state changes.
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+
+ // Unregister from power save mode changes.
+ if (mPowerSaveModeListener != null) {
+ mContext.unregisterReceiver(mPowerSaveModeListener);
+ mPowerSaveModeListener = null;
+ }
+ }
+
+ class MyCallStateListener extends PhoneStateListener {
+ @Override
+ public void onCallStateChanged(int state, String arg1) {
+ if (DBG) Slog.d(TAG, "onCallStateChanged: " + state);
+ synchronized (mLock) {
+ onCallStateChangedLocked(TelephonyManager.CALL_STATE_IDLE != state);
+ }
+ }
+ }
+
+ class PowerSaveModeListener extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (!PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(intent.getAction())) {
+ return;
+ }
+ boolean active = mPowerManager.isPowerSaveMode();
+ if (DBG) Slog.d(TAG, "onPowerSaveModeChanged: " + active);
+ synchronized (mLock) {
+ onPowerSaveModeChangedLocked(active);
+ }
+ }
}
void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -525,6 +573,7 @@
pw.print(" requested="); pw.println(mRequested);
pw.print(" started="); pw.println(mStarted);
pw.print(" call active="); pw.println(mCallActive);
+ pw.print(" power save mode active="); pw.println(mIsPowerSaveMode);
pw.print(" service disabled="); pw.println(mServiceDisabled);
}
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index a173a5c..45fa923 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -46,7 +46,6 @@
import android.service.voice.VoiceInteractionService;
import android.service.voice.VoiceInteractionServiceInfo;
import android.speech.RecognitionService;
-import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Slog;
@@ -78,8 +77,7 @@
mContext = context;
mResolver = context.getContentResolver();
mDbHelper = new DatabaseHelper(context);
- mSoundTriggerHelper = new SoundTriggerHelper(
- (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE));
+ mSoundTriggerHelper = new SoundTriggerHelper(context);
}
@Override
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 c307a25..d8f487f 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -87,6 +87,7 @@
public void onConferenceChanged(Connection c, Conference conference) {}
}
+ /** @hide */
public static abstract class VideoProvider {
/**
@@ -528,6 +529,7 @@
* {@link VideoProfile.VideoState#RX_ENABLED}.
*
* @return The video state of the call.
+ * @hide
*/
public final int getVideoState() {
return mVideoState;
@@ -699,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);
@@ -755,6 +758,7 @@
/**
* Sets the video call provider.
* @param videoProvider The video provider.
+ * @hide
*/
public final void setVideoProvider(VideoProvider videoProvider) {
mVideoProvider = videoProvider;
@@ -763,6 +767,7 @@
}
}
+ /** @hide */
public final VideoProvider getVideoProvider() {
return mVideoProvider;
}
@@ -914,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;
@@ -929,6 +935,7 @@
*/
public final void resetConference() {
if (mConference != null) {
+ Log.d(this, "Conference reset");
mConference = null;
fireConferenceChanged();
}
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 c805978..b77bb18 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -84,6 +84,7 @@
private final ConnectionServiceAdapter mAdapter = new ConnectionServiceAdapter();
private boolean mAreAccountsInitialized = false;
+ private Conference sNullConference;
private final IBinder mBinder = new IConnectionService.Stub() {
@Override
@@ -561,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) {
@@ -616,7 +629,10 @@
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) {
@@ -885,4 +901,19 @@
}
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/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/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index b935d2a..acb97a0 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1825,7 +1825,7 @@
int slotId = SubscriptionManager.getSlotId(subId);
// retrieve the list of emergency numbers
// check read-write ecclist property first
- String ecclist = (slotId == 0) ? "ril.ecclist" : ("ril.ecclist" + slotId);
+ String ecclist = (slotId <= 0) ? "ril.ecclist" : ("ril.ecclist" + slotId);
numbers = SystemProperties.get(ecclist);
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/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/JobSchedulerTestApp/res/layout/activity_main.xml b/tests/JobSchedulerTestApp/res/layout/activity_main.xml
index d3429ff..96e1641 100644
--- a/tests/JobSchedulerTestApp/res/layout/activity_main.xml
+++ b/tests/JobSchedulerTestApp/res/layout/activity_main.xml
@@ -141,6 +141,20 @@
android:id="@+id/checkbox_idle"
android:text="@string/idle_mode_text"/>
</LinearLayout>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/persisted_caption"
+ android:layout_marginRight="15dp"/>
+ <CheckBox
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/checkbox_persisted"
+ android:text="@string/persisted_mode_text"/>
+ </LinearLayout>
</LinearLayout>
<Button
diff --git a/tests/JobSchedulerTestApp/res/values/strings.xml b/tests/JobSchedulerTestApp/res/values/strings.xml
index eebfb19..90dd2b6 100644
--- a/tests/JobSchedulerTestApp/res/values/strings.xml
+++ b/tests/JobSchedulerTestApp/res/values/strings.xml
@@ -27,6 +27,7 @@
<string name="charging_caption">Charging:</string>
<string name="charging_text">Requires device plugged in.</string>
<string name="idle_caption">Idle:</string>
+ <string name="persisted_caption">Persisted:</string>
<string name="constraints">Constraints</string>
<string name="connectivity">Connectivity:</string>
<string name="any">Any</string>
@@ -34,4 +35,5 @@
<string name="timing">Timing:</string>
<string name="delay">Delay:</string>
<string name="deadline">Deadline:</string>
+ <string name="persisted_mode_text">Persisted:</string>
</resources>
diff --git a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java
index e15929d..b9a2a7e 100644
--- a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java
+++ b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java
@@ -65,6 +65,8 @@
mAnyConnectivityRadioButton = (RadioButton) findViewById(R.id.checkbox_any);
mRequiresChargingCheckBox = (CheckBox) findViewById(R.id.checkbox_charging);
mRequiresIdleCheckbox = (CheckBox) findViewById(R.id.checkbox_idle);
+ mIsPersistedCheckbox = (CheckBox) findViewById(R.id.checkbox_persisted);
+
mServiceComponent = new ComponentName(this, TestJobService.class);
// Start service and provide it a way to communicate with us.
Intent startServiceIntent = new Intent(this, TestJobService.class);
@@ -85,6 +87,7 @@
RadioButton mAnyConnectivityRadioButton;
CheckBox mRequiresChargingCheckBox;
CheckBox mRequiresIdleCheckbox;
+ CheckBox mIsPersistedCheckbox;
ComponentName mServiceComponent;
/** Service object to interact scheduled jobs. */
@@ -140,13 +143,13 @@
boolean requiresUnmetered = mWiFiConnectivityRadioButton.isChecked();
boolean requiresAnyConnectivity = mAnyConnectivityRadioButton.isChecked();
if (requiresUnmetered) {
- builder.setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED);
+ builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
} else if (requiresAnyConnectivity) {
- builder.setRequiredNetworkCapabilities(JobInfo.NetworkType.ANY);
+ builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
}
builder.setRequiresDeviceIdle(mRequiresIdleCheckbox.isChecked());
builder.setRequiresCharging(mRequiresChargingCheckBox.isChecked());
-
+ builder.setPersisted(mIsPersistedCheckbox.isChecked());
mTestService.scheduleJob(builder.build());
}
diff --git a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java
index e2c3be0..a68e04e 100644
--- a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java
+++ b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java
@@ -90,31 +90,6 @@
mActivity.onReceivedStartJob(params);
}
- // Spin off a new task on a separate thread for a couple seconds.
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... voids) {
- try {
- Log.d(TAG, "Sleeping for 3 seconds.");
- Thread.sleep(3000L);
- } catch (InterruptedException e) {}
- final JobParameters params = jobParamsMap.get(currId);
- Log.d(TAG, "Pulled :" + currId + " " + params);
- jobFinished(params, false);
-
- Log.d(TAG, "Rescheduling new job: " + params.getJobId());
- scheduleJob(
- new JobInfo.Builder(params.getJobId(),
- new ComponentName(getBaseContext(), TestJobService.class))
- .setMinimumLatency(2000L)
- .setOverrideDeadline(3000L)
- .setRequiresCharging(true)
- .build()
- );
-
- return null;
- }
- }.execute();
return true;
}
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/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
index 77c0c32..1233c0c 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
@@ -25,6 +25,7 @@
import android.util.Log;
import java.util.Arrays;
+import java.util.Locale;
public class MainInteractionService extends VoiceInteractionService {
static final String TAG = "MainInteractionService";
@@ -67,7 +68,8 @@
Log.i(TAG, "Keyphrase enrollment meta-data: "
+ Arrays.toString(getKeyphraseEnrollmentInfo().listKeyphraseMetadata()));
- mHotwordDetector = createAlwaysOnHotwordDetector("Hello There", "en-US", mHotwordCallback);
+ mHotwordDetector = createAlwaysOnHotwordDetector(
+ "Hello There", new Locale("en-US"), mHotwordCallback);
}
@Override
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/Command.cpp b/tools/aapt/Command.cpp
index bdbf47b..b394671 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -438,6 +438,7 @@
LARGE_SCREEN_ATTR = 0x01010286,
XLARGE_SCREEN_ATTR = 0x010102bf,
REQUIRED_ATTR = 0x0101028e,
+ INSTALL_LOCATION_ATTR = 0x010102b7,
SCREEN_SIZE_ATTR = 0x010102ca,
SCREEN_DENSITY_ATTR = 0x010102cb,
REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364,
@@ -1177,6 +1178,33 @@
splitName.string()).string());
}
printf("\n");
+
+ int32_t installLocation = getResolvedIntegerAttribute(&res, tree,
+ INSTALL_LOCATION_ATTR, &error, -1);
+ if (error != "") {
+ fprintf(stderr, "ERROR getting 'android:installLocation' attribute: %s\n",
+ error.string());
+ goto bail;
+ }
+
+ if (installLocation >= 0) {
+ printf("install-location:'");
+ switch (installLocation) {
+ case 0:
+ printf("auto");
+ break;
+ case 1:
+ printf("internalOnly");
+ break;
+ case 2:
+ printf("preferExternal");
+ break;
+ default:
+ fprintf(stderr, "Invalid installLocation %d\n", installLocation);
+ goto bail;
+ }
+ printf("'\n");
+ }
} else if (depth == 2) {
withinApplication = false;
if (tag == "application") {
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/ResourceFilter.cpp b/tools/aapt/ResourceFilter.cpp
index de8b4fc..fc95e14 100644
--- a/tools/aapt/ResourceFilter.cpp
+++ b/tools/aapt/ResourceFilter.cpp
@@ -56,24 +56,34 @@
return true;
}
+ uint32_t matchedAxis = 0x0;
const size_t N = mConfigs.size();
for (size_t i = 0; i < N; i++) {
const std::pair<ConfigDescription, uint32_t>& entry = mConfigs[i];
uint32_t diff = entry.first.diff(config);
if ((diff & entry.second) == 0) {
- return true;
+ // Mark the axis that was matched.
+ matchedAxis |= entry.second;
} else if ((diff & entry.second) == ResTable_config::CONFIG_LOCALE) {
// If the locales differ, but the languages are the same and
// the locale we are matching only has a language specified,
// we match.
- if (config.language[0] && memcmp(config.language, entry.first.language, sizeof(config.language)) == 0) {
+ if (config.language[0] &&
+ memcmp(config.language, entry.first.language, sizeof(config.language)) == 0) {
if (config.country[0] == 0) {
- return true;
+ matchedAxis |= ResTable_config::CONFIG_LOCALE;
}
}
+ } else if ((diff & entry.second) == ResTable_config::CONFIG_SMALLEST_SCREEN_SIZE) {
+ // Special case if the smallest screen width doesn't match. We check that the
+ // config being matched has a smaller screen width than the filter specified.
+ if (config.smallestScreenWidthDp != 0 &&
+ config.smallestScreenWidthDp < entry.first.smallestScreenWidthDp) {
+ matchedAxis |= ResTable_config::CONFIG_SMALLEST_SCREEN_SIZE;
+ }
}
}
- return false;
+ return matchedAxis == (mConfigMask & mask);
}
status_t
diff --git a/tools/aapt/ResourceFilter.h b/tools/aapt/ResourceFilter.h
index f459584..d6430c0 100644
--- a/tools/aapt/ResourceFilter.h
+++ b/tools/aapt/ResourceFilter.h
@@ -24,8 +24,7 @@
};
/**
- * Implements logic for parsing and handling "-c" and "--preferred-configurations"
- * options.
+ * Implements logic for parsing and handling "-c" options.
*/
class WeakResourceFilter : public ResourceFilter {
public:
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..bbc2e02 100644
--- a/tools/aapt/tests/ResourceFilter_test.cpp
+++ b/tools/aapt/tests/ResourceFilter_test.cpp
@@ -75,6 +75,17 @@
EXPECT_TRUE(filter.match(config));
}
+TEST(WeakResourceFilterTest, MatchesConfigWithOneMatchingAxis) {
+ WeakResourceFilter filter;
+ ASSERT_EQ(NO_ERROR, filter.parse(String8("fr_FR,sw360dp,normal,en_US")));
+
+ ConfigDescription config;
+ config.language[0] = 'e';
+ config.language[1] = 'n';
+
+ EXPECT_TRUE(filter.match(config));
+}
+
TEST(WeakResourceFilterTest, DoesNotMatchConfigWithDifferentValueAxis) {
WeakResourceFilter filter;
ASSERT_EQ(NO_ERROR, filter.parse(String8("fr")));
@@ -86,6 +97,32 @@
EXPECT_FALSE(filter.match(config));
}
+TEST(WeakResourceFilterTest, DoesNotMatchWhenOneQualifierIsExplicitlyNotMatched) {
+ WeakResourceFilter filter;
+ ASSERT_EQ(NO_ERROR, filter.parse(String8("fr_FR,en_US,normal,large,xxhdpi,sw320dp")));
+
+ ConfigDescription config;
+ config.language[0] = 'f';
+ config.language[1] = 'r';
+ config.smallestScreenWidthDp = 600;
+ config.version = 13;
+
+ EXPECT_FALSE(filter.match(config));
+}
+
+TEST(WeakResourceFilterTest, MatchesSmallestWidthWhenSmaller) {
+ WeakResourceFilter filter;
+ ASSERT_EQ(NO_ERROR, filter.parse(String8("sw600dp")));
+
+ ConfigDescription config;
+ config.language[0] = 'f';
+ config.language[1] = 'r';
+ config.smallestScreenWidthDp = 320;
+ config.version = 13;
+
+ EXPECT_TRUE(filter.match(config));
+}
+
TEST(WeakResourceFilterTest, MatchesConfigWithSameLanguageButNoRegionSpecified) {
WeakResourceFilter filter;
ASSERT_EQ(NO_ERROR, filter.parse(String8("de-rDE")));
@@ -126,3 +163,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/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();