summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt26
-rw-r--r--api/system-current.txt28
-rw-r--r--api/test-current.txt26
-rw-r--r--cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java95
-rw-r--r--core/java/android/app/IntentService.java14
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java51
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl4
-rw-r--r--core/java/android/app/backup/BackupManager.java23
-rw-r--r--core/java/android/app/backup/BackupTransport.java18
-rw-r--r--core/java/android/app/backup/IBackupManager.aidl10
-rw-r--r--core/java/android/view/inputmethod/EditorInfo.java40
-rw-r--r--core/java/android/view/inputmethod/InputMethodInfo.java2
-rw-r--r--core/java/android/widget/AbsListView.java68
-rw-r--r--core/java/android/widget/Editor.java2
-rw-r--r--core/java/android/widget/Gallery.java46
-rw-r--r--core/java/android/widget/TextView.java34
-rw-r--r--core/java/com/android/internal/backup/IBackupTransport.aidl11
-rw-r--r--core/jni/android/graphics/MinikinUtils.cpp9
-rw-r--r--core/jni/android/graphics/MinikinUtils.h3
-rw-r--r--core/jni/android/graphics/Paint.cpp16
-rw-r--r--core/tests/coretests/src/android/widget/TextViewActivityTest.java40
-rw-r--r--libs/androidfw/DisplayEventDispatcher.cpp2
-rw-r--r--libs/hwui/Texture.cpp4
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java10
-rw-r--r--packages/DocumentsUI/tests/src/com/android/documentsui/services/MoveJobTest.java17
-rw-r--r--packages/SystemUI/res/layout-sw600dp/navigation_bar.xml322
-rw-r--r--packages/SystemUI/res/layout-sw600dp/navigation_layout_rot90.xml90
-rw-r--r--packages/SystemUI/res/layout/back.xml31
-rw-r--r--packages/SystemUI/res/layout/home.xml30
-rw-r--r--packages/SystemUI/res/layout/menu_ime.xml44
-rw-r--r--packages/SystemUI/res/layout/nav_key_space.xml25
-rw-r--r--packages/SystemUI/res/layout/navigation_bar.xml306
-rw-r--r--packages/SystemUI/res/layout/navigation_layout.xml91
-rw-r--r--packages/SystemUI/res/layout/navigation_layout_rot90.xml91
-rw-r--r--packages/SystemUI/res/layout/recent_apps.xml30
-rw-r--r--packages/SystemUI/res/values-sw600dp-land/dimens.xml3
-rw-r--r--packages/SystemUI/res/values-sw600dp/config.xml4
-rw-r--r--packages/SystemUI/res/values-sw600dp/dimens.xml3
-rw-r--r--packages/SystemUI/res/values/config.xml3
-rw-r--r--packages/SystemUI/res/values/dimens.xml5
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java168
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java266
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java162
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java55
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java55
-rw-r--r--services/backup/java/com/android/server/backup/Trampoline.java6
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java56
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java5
53 files changed, 1618 insertions, 893 deletions
diff --git a/api/current.txt b/api/current.txt
index 4f801cb97082..e50eba11393f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5807,6 +5807,7 @@ package android.app.admin {
method public java.lang.String getLongSupportMessage(android.content.ComponentName);
method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
method public long getMaximumTimeToLock(android.content.ComponentName);
+ method public int getOrganizationColor(android.content.ComponentName);
method public boolean getPackageSuspended(android.content.ComponentName, java.lang.String);
method public android.app.admin.DevicePolicyManager getParentProfileInstance(android.content.ComponentName);
method public long getPasswordExpiration(android.content.ComponentName);
@@ -5875,6 +5876,7 @@ package android.app.admin {
method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
method public void setMaximumTimeToLock(android.content.ComponentName, long);
+ method public void setOrganizationColor(android.content.ComponentName, int);
method public boolean setPackageSuspended(android.content.ComponentName, java.lang.String, boolean);
method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
method public void setPasswordHistoryLength(android.content.ComponentName, int);
@@ -43606,6 +43608,7 @@ package android.view.inputmethod {
field public android.os.Bundle extras;
field public int fieldId;
field public java.lang.String fieldName;
+ field public android.util.LocaleList hintLocales;
field public java.lang.CharSequence hintText;
field public int imeOptions;
field public int initialCapsMode;
@@ -43613,7 +43616,6 @@ package android.view.inputmethod {
field public int initialSelStart;
field public int inputType;
field public java.lang.CharSequence label;
- field public android.util.LocaleList locales;
field public java.lang.String packageName;
field public java.lang.String privateImeOptions;
}
@@ -46860,6 +46862,7 @@ package android.widget {
method public int getHyphenationFrequency();
method public int getImeActionId();
method public java.lang.CharSequence getImeActionLabel();
+ method public android.util.LocaleList getImeHintLocales();
method public int getImeOptions();
method public boolean getIncludeFontPadding();
method public android.os.Bundle getInputExtras(boolean);
@@ -46966,6 +46969,7 @@ package android.widget {
method public void setHorizontallyScrolling(boolean);
method public void setHyphenationFrequency(int);
method public void setImeActionLabel(java.lang.CharSequence, int);
+ method public void setImeHintLocales(android.util.LocaleList);
method public void setImeOptions(int);
method public void setIncludeFontPadding(boolean);
method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
@@ -47919,10 +47923,8 @@ package java.io {
}
public final class Console implements java.io.Flushable {
- method public static java.io.Console console();
method public void flush();
method public java.io.Console format(java.lang.String, java.lang.Object...);
- method public static synchronized java.io.Console getConsole();
method public java.io.Console printf(java.lang.String, java.lang.Object...);
method public java.lang.String readLine(java.lang.String, java.lang.Object...);
method public java.lang.String readLine();
@@ -48206,7 +48208,6 @@ package java.io {
public class InterruptedIOException extends java.io.IOException {
ctor public InterruptedIOException();
ctor public InterruptedIOException(java.lang.String);
- ctor public InterruptedIOException(java.lang.Throwable);
field public int bytesTransferred;
}
@@ -48877,7 +48878,6 @@ package java.lang {
method public long longValue();
method public static byte parseByte(java.lang.String, int) throws java.lang.NumberFormatException;
method public static byte parseByte(java.lang.String) throws java.lang.NumberFormatException;
- method public static java.lang.String toHexString(byte, boolean);
method public static java.lang.String toString(byte);
method public static java.lang.Byte valueOf(byte);
method public static java.lang.Byte valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -51029,7 +51029,6 @@ package java.net {
public class BindException extends java.net.SocketException {
ctor public BindException(java.lang.String);
ctor public BindException();
- ctor public BindException(java.lang.String, java.lang.Throwable);
}
public abstract class CacheRequest {
@@ -51047,7 +51046,6 @@ package java.net {
public class ConnectException extends java.net.SocketException {
ctor public ConnectException(java.lang.String);
ctor public ConnectException();
- ctor public ConnectException(java.lang.String, java.lang.Throwable);
}
public abstract class ContentHandler {
@@ -51127,7 +51125,6 @@ package java.net {
method public void disconnect();
method public synchronized boolean getBroadcast() throws java.net.SocketException;
method public java.nio.channels.DatagramChannel getChannel();
- method public final java.io.FileDescriptor getFileDescriptor$();
method public java.net.InetAddress getInetAddress();
method public java.net.InetAddress getLocalAddress();
method public int getLocalPort();
@@ -51204,7 +51201,6 @@ package java.net {
method public boolean hasExpired();
method public boolean isHttpOnly();
method public static java.util.List<java.net.HttpCookie> parse(java.lang.String);
- method public static java.util.List<java.net.HttpCookie> parse(java.lang.String, boolean);
method public void setComment(java.lang.String);
method public void setCommentURL(java.lang.String);
method public void setDiscard(boolean);
@@ -51297,9 +51293,6 @@ package java.net {
}
public final class Inet4Address extends java.net.InetAddress {
- field public static final java.net.InetAddress ALL;
- field public static final java.net.InetAddress ANY;
- field public static final java.net.InetAddress LOOPBACK;
}
public final class Inet6Address extends java.net.InetAddress {
@@ -51308,8 +51301,6 @@ package java.net {
method public int getScopeId();
method public java.net.NetworkInterface getScopedInterface();
method public boolean isIPv4CompatibleAddress();
- field public static final java.net.InetAddress ANY;
- field public static final java.net.InetAddress LOOPBACK;
}
public class InetAddress implements java.io.Serializable {
@@ -51437,13 +51428,11 @@ package java.net {
public class PortUnreachableException extends java.net.SocketException {
ctor public PortUnreachableException(java.lang.String);
ctor public PortUnreachableException();
- ctor public PortUnreachableException(java.lang.String, java.lang.Throwable);
}
public class ProtocolException extends java.io.IOException {
ctor public ProtocolException(java.lang.String);
ctor public ProtocolException();
- ctor public ProtocolException(java.lang.String, java.lang.Throwable);
}
public abstract interface ProtocolFamily {
@@ -51578,8 +51567,6 @@ package java.net {
public class SocketException extends java.io.IOException {
ctor public SocketException(java.lang.String);
ctor public SocketException();
- ctor public SocketException(java.lang.Throwable);
- ctor public SocketException(java.lang.String, java.lang.Throwable);
}
public abstract class SocketImpl implements java.net.SocketOptions {
@@ -51649,8 +51636,6 @@ package java.net {
public class SocketTimeoutException extends java.io.InterruptedIOException {
ctor public SocketTimeoutException(java.lang.String);
ctor public SocketTimeoutException();
- ctor public SocketTimeoutException(java.lang.Throwable);
- ctor public SocketTimeoutException(java.lang.String, java.lang.Throwable);
}
public final class StandardProtocolFamily extends java.lang.Enum implements java.net.ProtocolFamily {
@@ -59595,7 +59580,6 @@ package java.util.jar {
ctor public JarFile(java.io.File, boolean, int) throws java.io.IOException;
method public java.util.jar.JarEntry getJarEntry(java.lang.String);
method public java.util.jar.Manifest getManifest() throws java.io.IOException;
- method public boolean hasClassPathAttribute() throws java.io.IOException;
field public static final java.lang.String MANIFEST_NAME = "META-INF/MANIFEST.MF";
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 47a51d4112ca..2d358bfe0bf8 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5947,6 +5947,7 @@ package android.app.admin {
method public java.lang.String getLongSupportMessage(android.content.ComponentName);
method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
method public long getMaximumTimeToLock(android.content.ComponentName);
+ method public int getOrganizationColor(android.content.ComponentName);
method public boolean getPackageSuspended(android.content.ComponentName, java.lang.String);
method public android.app.admin.DevicePolicyManager getParentProfileInstance(android.content.ComponentName);
method public long getPasswordExpiration(android.content.ComponentName);
@@ -6021,6 +6022,7 @@ package android.app.admin {
method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
method public void setMaximumTimeToLock(android.content.ComponentName, long);
+ method public void setOrganizationColor(android.content.ComponentName, int);
method public boolean setPackageSuspended(android.content.ComponentName, java.lang.String, boolean);
method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
method public void setPasswordHistoryLength(android.content.ComponentName, int);
@@ -6293,6 +6295,7 @@ package android.app.backup {
method public static void dataChanged(java.lang.String);
method public long getAvailableRestoreToken(java.lang.String);
method public java.lang.String getCurrentTransport();
+ method public boolean isAppEligibleForBackup(java.lang.String);
method public boolean isBackupEnabled();
method public java.lang.String[] listAllTransports();
method public int requestBackup(java.lang.String[], android.app.backup.BackupObserver);
@@ -6342,6 +6345,7 @@ package android.app.backup {
method public int getNextFullRestoreDataChunk(android.os.ParcelFileDescriptor);
method public int getRestoreData(android.os.ParcelFileDescriptor);
method public int initializeDevice();
+ method public boolean isAppEligibleForBackup(android.content.pm.PackageInfo, boolean);
method public java.lang.String name();
method public android.app.backup.RestoreDescription nextRestorePackage();
method public int performBackup(android.content.pm.PackageInfo, android.os.ParcelFileDescriptor, int);
@@ -46034,6 +46038,7 @@ package android.view.inputmethod {
field public android.os.Bundle extras;
field public int fieldId;
field public java.lang.String fieldName;
+ field public android.util.LocaleList hintLocales;
field public java.lang.CharSequence hintText;
field public int imeOptions;
field public int initialCapsMode;
@@ -46041,7 +46046,6 @@ package android.view.inputmethod {
field public int initialSelStart;
field public int inputType;
field public java.lang.CharSequence label;
- field public android.util.LocaleList locales;
field public java.lang.String packageName;
field public java.lang.String privateImeOptions;
}
@@ -49614,6 +49618,7 @@ package android.widget {
method public int getHyphenationFrequency();
method public int getImeActionId();
method public java.lang.CharSequence getImeActionLabel();
+ method public android.util.LocaleList getImeHintLocales();
method public int getImeOptions();
method public boolean getIncludeFontPadding();
method public android.os.Bundle getInputExtras(boolean);
@@ -49720,6 +49725,7 @@ package android.widget {
method public void setHorizontallyScrolling(boolean);
method public void setHyphenationFrequency(int);
method public void setImeActionLabel(java.lang.CharSequence, int);
+ method public void setImeHintLocales(android.util.LocaleList);
method public void setImeOptions(int);
method public void setIncludeFontPadding(boolean);
method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
@@ -50673,10 +50679,8 @@ package java.io {
}
public final class Console implements java.io.Flushable {
- method public static java.io.Console console();
method public void flush();
method public java.io.Console format(java.lang.String, java.lang.Object...);
- method public static synchronized java.io.Console getConsole();
method public java.io.Console printf(java.lang.String, java.lang.Object...);
method public java.lang.String readLine(java.lang.String, java.lang.Object...);
method public java.lang.String readLine();
@@ -50960,7 +50964,6 @@ package java.io {
public class InterruptedIOException extends java.io.IOException {
ctor public InterruptedIOException();
ctor public InterruptedIOException(java.lang.String);
- ctor public InterruptedIOException(java.lang.Throwable);
field public int bytesTransferred;
}
@@ -51631,7 +51634,6 @@ package java.lang {
method public long longValue();
method public static byte parseByte(java.lang.String, int) throws java.lang.NumberFormatException;
method public static byte parseByte(java.lang.String) throws java.lang.NumberFormatException;
- method public static java.lang.String toHexString(byte, boolean);
method public static java.lang.String toString(byte);
method public static java.lang.Byte valueOf(byte);
method public static java.lang.Byte valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -53783,7 +53785,6 @@ package java.net {
public class BindException extends java.net.SocketException {
ctor public BindException(java.lang.String);
ctor public BindException();
- ctor public BindException(java.lang.String, java.lang.Throwable);
}
public abstract class CacheRequest {
@@ -53801,7 +53802,6 @@ package java.net {
public class ConnectException extends java.net.SocketException {
ctor public ConnectException(java.lang.String);
ctor public ConnectException();
- ctor public ConnectException(java.lang.String, java.lang.Throwable);
}
public abstract class ContentHandler {
@@ -53881,7 +53881,6 @@ package java.net {
method public void disconnect();
method public synchronized boolean getBroadcast() throws java.net.SocketException;
method public java.nio.channels.DatagramChannel getChannel();
- method public final java.io.FileDescriptor getFileDescriptor$();
method public java.net.InetAddress getInetAddress();
method public java.net.InetAddress getLocalAddress();
method public int getLocalPort();
@@ -53958,7 +53957,6 @@ package java.net {
method public boolean hasExpired();
method public boolean isHttpOnly();
method public static java.util.List<java.net.HttpCookie> parse(java.lang.String);
- method public static java.util.List<java.net.HttpCookie> parse(java.lang.String, boolean);
method public void setComment(java.lang.String);
method public void setCommentURL(java.lang.String);
method public void setDiscard(boolean);
@@ -54051,9 +54049,6 @@ package java.net {
}
public final class Inet4Address extends java.net.InetAddress {
- field public static final java.net.InetAddress ALL;
- field public static final java.net.InetAddress ANY;
- field public static final java.net.InetAddress LOOPBACK;
}
public final class Inet6Address extends java.net.InetAddress {
@@ -54062,8 +54057,6 @@ package java.net {
method public int getScopeId();
method public java.net.NetworkInterface getScopedInterface();
method public boolean isIPv4CompatibleAddress();
- field public static final java.net.InetAddress ANY;
- field public static final java.net.InetAddress LOOPBACK;
}
public class InetAddress implements java.io.Serializable {
@@ -54191,13 +54184,11 @@ package java.net {
public class PortUnreachableException extends java.net.SocketException {
ctor public PortUnreachableException(java.lang.String);
ctor public PortUnreachableException();
- ctor public PortUnreachableException(java.lang.String, java.lang.Throwable);
}
public class ProtocolException extends java.io.IOException {
ctor public ProtocolException(java.lang.String);
ctor public ProtocolException();
- ctor public ProtocolException(java.lang.String, java.lang.Throwable);
}
public abstract interface ProtocolFamily {
@@ -54332,8 +54323,6 @@ package java.net {
public class SocketException extends java.io.IOException {
ctor public SocketException(java.lang.String);
ctor public SocketException();
- ctor public SocketException(java.lang.Throwable);
- ctor public SocketException(java.lang.String, java.lang.Throwable);
}
public abstract class SocketImpl implements java.net.SocketOptions {
@@ -54403,8 +54392,6 @@ package java.net {
public class SocketTimeoutException extends java.io.InterruptedIOException {
ctor public SocketTimeoutException(java.lang.String);
ctor public SocketTimeoutException();
- ctor public SocketTimeoutException(java.lang.Throwable);
- ctor public SocketTimeoutException(java.lang.String, java.lang.Throwable);
}
public final class StandardProtocolFamily extends java.lang.Enum implements java.net.ProtocolFamily {
@@ -62349,7 +62336,6 @@ package java.util.jar {
ctor public JarFile(java.io.File, boolean, int) throws java.io.IOException;
method public java.util.jar.JarEntry getJarEntry(java.lang.String);
method public java.util.jar.Manifest getManifest() throws java.io.IOException;
- method public boolean hasClassPathAttribute() throws java.io.IOException;
field public static final java.lang.String MANIFEST_NAME = "META-INF/MANIFEST.MF";
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 6b5b8b02c36d..bcdf5c1b22d9 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5809,6 +5809,7 @@ package android.app.admin {
method public java.lang.String getLongSupportMessage(android.content.ComponentName);
method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
method public long getMaximumTimeToLock(android.content.ComponentName);
+ method public int getOrganizationColor(android.content.ComponentName);
method public boolean getPackageSuspended(android.content.ComponentName, java.lang.String);
method public android.app.admin.DevicePolicyManager getParentProfileInstance(android.content.ComponentName);
method public long getPasswordExpiration(android.content.ComponentName);
@@ -5877,6 +5878,7 @@ package android.app.admin {
method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
method public void setMaximumTimeToLock(android.content.ComponentName, long);
+ method public void setOrganizationColor(android.content.ComponentName, int);
method public boolean setPackageSuspended(android.content.ComponentName, java.lang.String, boolean);
method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
method public void setPasswordHistoryLength(android.content.ComponentName, int);
@@ -43622,6 +43624,7 @@ package android.view.inputmethod {
field public android.os.Bundle extras;
field public int fieldId;
field public java.lang.String fieldName;
+ field public android.util.LocaleList hintLocales;
field public java.lang.CharSequence hintText;
field public int imeOptions;
field public int initialCapsMode;
@@ -43629,7 +43632,6 @@ package android.view.inputmethod {
field public int initialSelStart;
field public int inputType;
field public java.lang.CharSequence label;
- field public android.util.LocaleList locales;
field public java.lang.String packageName;
field public java.lang.String privateImeOptions;
}
@@ -46876,6 +46878,7 @@ package android.widget {
method public int getHyphenationFrequency();
method public int getImeActionId();
method public java.lang.CharSequence getImeActionLabel();
+ method public android.util.LocaleList getImeHintLocales();
method public int getImeOptions();
method public boolean getIncludeFontPadding();
method public android.os.Bundle getInputExtras(boolean);
@@ -46982,6 +46985,7 @@ package android.widget {
method public void setHorizontallyScrolling(boolean);
method public void setHyphenationFrequency(int);
method public void setImeActionLabel(java.lang.CharSequence, int);
+ method public void setImeHintLocales(android.util.LocaleList);
method public void setImeOptions(int);
method public void setIncludeFontPadding(boolean);
method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
@@ -47935,10 +47939,8 @@ package java.io {
}
public final class Console implements java.io.Flushable {
- method public static java.io.Console console();
method public void flush();
method public java.io.Console format(java.lang.String, java.lang.Object...);
- method public static synchronized java.io.Console getConsole();
method public java.io.Console printf(java.lang.String, java.lang.Object...);
method public java.lang.String readLine(java.lang.String, java.lang.Object...);
method public java.lang.String readLine();
@@ -48222,7 +48224,6 @@ package java.io {
public class InterruptedIOException extends java.io.IOException {
ctor public InterruptedIOException();
ctor public InterruptedIOException(java.lang.String);
- ctor public InterruptedIOException(java.lang.Throwable);
field public int bytesTransferred;
}
@@ -48893,7 +48894,6 @@ package java.lang {
method public long longValue();
method public static byte parseByte(java.lang.String, int) throws java.lang.NumberFormatException;
method public static byte parseByte(java.lang.String) throws java.lang.NumberFormatException;
- method public static java.lang.String toHexString(byte, boolean);
method public static java.lang.String toString(byte);
method public static java.lang.Byte valueOf(byte);
method public static java.lang.Byte valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -51045,7 +51045,6 @@ package java.net {
public class BindException extends java.net.SocketException {
ctor public BindException(java.lang.String);
ctor public BindException();
- ctor public BindException(java.lang.String, java.lang.Throwable);
}
public abstract class CacheRequest {
@@ -51063,7 +51062,6 @@ package java.net {
public class ConnectException extends java.net.SocketException {
ctor public ConnectException(java.lang.String);
ctor public ConnectException();
- ctor public ConnectException(java.lang.String, java.lang.Throwable);
}
public abstract class ContentHandler {
@@ -51143,7 +51141,6 @@ package java.net {
method public void disconnect();
method public synchronized boolean getBroadcast() throws java.net.SocketException;
method public java.nio.channels.DatagramChannel getChannel();
- method public final java.io.FileDescriptor getFileDescriptor$();
method public java.net.InetAddress getInetAddress();
method public java.net.InetAddress getLocalAddress();
method public int getLocalPort();
@@ -51220,7 +51217,6 @@ package java.net {
method public boolean hasExpired();
method public boolean isHttpOnly();
method public static java.util.List<java.net.HttpCookie> parse(java.lang.String);
- method public static java.util.List<java.net.HttpCookie> parse(java.lang.String, boolean);
method public void setComment(java.lang.String);
method public void setCommentURL(java.lang.String);
method public void setDiscard(boolean);
@@ -51313,9 +51309,6 @@ package java.net {
}
public final class Inet4Address extends java.net.InetAddress {
- field public static final java.net.InetAddress ALL;
- field public static final java.net.InetAddress ANY;
- field public static final java.net.InetAddress LOOPBACK;
}
public final class Inet6Address extends java.net.InetAddress {
@@ -51324,8 +51317,6 @@ package java.net {
method public int getScopeId();
method public java.net.NetworkInterface getScopedInterface();
method public boolean isIPv4CompatibleAddress();
- field public static final java.net.InetAddress ANY;
- field public static final java.net.InetAddress LOOPBACK;
}
public class InetAddress implements java.io.Serializable {
@@ -51453,13 +51444,11 @@ package java.net {
public class PortUnreachableException extends java.net.SocketException {
ctor public PortUnreachableException(java.lang.String);
ctor public PortUnreachableException();
- ctor public PortUnreachableException(java.lang.String, java.lang.Throwable);
}
public class ProtocolException extends java.io.IOException {
ctor public ProtocolException(java.lang.String);
ctor public ProtocolException();
- ctor public ProtocolException(java.lang.String, java.lang.Throwable);
}
public abstract interface ProtocolFamily {
@@ -51594,8 +51583,6 @@ package java.net {
public class SocketException extends java.io.IOException {
ctor public SocketException(java.lang.String);
ctor public SocketException();
- ctor public SocketException(java.lang.Throwable);
- ctor public SocketException(java.lang.String, java.lang.Throwable);
}
public abstract class SocketImpl implements java.net.SocketOptions {
@@ -51665,8 +51652,6 @@ package java.net {
public class SocketTimeoutException extends java.io.InterruptedIOException {
ctor public SocketTimeoutException(java.lang.String);
ctor public SocketTimeoutException();
- ctor public SocketTimeoutException(java.lang.Throwable);
- ctor public SocketTimeoutException(java.lang.String, java.lang.Throwable);
}
public final class StandardProtocolFamily extends java.lang.Enum implements java.net.ProtocolFamily {
@@ -59611,7 +59596,6 @@ package java.util.jar {
ctor public JarFile(java.io.File, boolean, int) throws java.io.IOException;
method public java.util.jar.JarEntry getJarEntry(java.lang.String);
method public java.util.jar.Manifest getManifest() throws java.io.IOException;
- method public boolean hasClassPathAttribute() throws java.io.IOException;
field public static final java.lang.String MANIFEST_NAME = "META-INF/MANIFEST.MF";
}
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 9728e384d9a2..67d63a44a908 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -16,8 +16,11 @@
package com.android.commands.bmgr;
+import android.app.backup.BackupManager;
+import android.app.backup.BackupProgress;
import android.app.backup.RestoreSet;
import android.app.backup.IBackupManager;
+import android.app.backup.IBackupObserver;
import android.app.backup.IRestoreObserver;
import android.app.backup.IRestoreSession;
import android.os.RemoteException;
@@ -108,6 +111,11 @@ public final class Bmgr {
return;
}
+ if ("backupnow".equals(op)) {
+ doBackupNow();
+ return;
+ }
+
System.err.println("Unknown command");
showUsage();
}
@@ -189,6 +197,88 @@ public final class Bmgr {
}
}
+ class BackupObserver extends IBackupObserver.Stub {
+ boolean done = false;
+
+ @Override
+ public void onUpdate(String currentPackage, BackupProgress backupProgress) {
+ System.out.println(
+ "onUpdate: " + currentPackage + " with progress: " + backupProgress.bytesTransferred
+ + "/" + backupProgress.bytesExpected);
+ }
+
+ @Override
+ public void onResult(String currentPackage, int status) {
+ System.out.println("onResult: " + currentPackage + " with result: "
+ + convertBackupStatusToString(status));
+ }
+
+ @Override
+ public void backupFinished(int status) {
+ System.out.println("backupFinished: " + convertBackupStatusToString(status));
+ synchronized (this) {
+ done = true;
+ this.notify();
+ }
+ }
+
+ public void waitForCompletion() {
+ // The backupFinished() callback will throw the 'done' flag; we
+ // just sit and wait on that notification.
+ synchronized (this) {
+ while (!this.done) {
+ try {
+ this.wait();
+ } catch (InterruptedException ex) {
+ }
+ }
+ }
+ }
+
+ }
+
+ private static String convertBackupStatusToString(int errorCode) {
+ switch (errorCode) {
+ case BackupManager.SUCCESS:
+ return "Success";
+ case BackupManager.ERROR_BACKUP_NOT_ALLOWED:
+ return "Backup is not allowed";
+ case BackupManager.ERROR_PACKAGE_NOT_FOUND:
+ return "Package not found";
+ case BackupManager.ERROR_TRANSPORT_ABORTED:
+ return "Transport error";
+ case BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED:
+ return "Transport rejected package";
+ case BackupManager.ERROR_AGENT_FAILURE:
+ return "Agent error";
+ default:
+ return "Unknown error";
+ }
+ }
+
+ private void doBackupNow() {
+ String pkg;
+ ArrayList<String> allPkgs = new ArrayList<String>();
+ while ((pkg = nextArg()) != null) {
+ allPkgs.add(pkg);
+ }
+ if (allPkgs.size() > 0) {
+ try {
+ BackupObserver observer = new BackupObserver();
+ int err = mBmgr.requestBackup(allPkgs.toArray(new String[allPkgs.size()]), observer);
+ if (err == 0) {
+ // Off and running -- wait for the backup to complete
+ observer.waitForCompletion();
+ } else {
+ System.err.println("Unable to run backup");
+ }
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(BMGR_NOT_RUNNING_ERR);
+ }
+ }
+ }
+
private void doTransport() {
try {
String which = nextArg();
@@ -528,5 +618,10 @@ public final class Bmgr {
System.err.println("");
System.err.println("The 'fullbackup' command induces a full-data stream backup for one or more");
System.err.println("packages. The data is sent via the currently active transport.");
+ System.err.println("");
+ System.err.println("The 'backupnow' command runs an immediate backup for one or more packages.");
+ System.err.println("For each package it will run key/value or full data backup ");
+ System.err.println("depending on the package's manifest declarations.");
+ System.err.println("The data is sent via the currently active transport.");
}
}
diff --git a/core/java/android/app/IntentService.java b/core/java/android/app/IntentService.java
index 3cda9736e91c..f33af396070e 100644
--- a/core/java/android/app/IntentService.java
+++ b/core/java/android/app/IntentService.java
@@ -17,6 +17,7 @@
package android.app;
import android.annotation.WorkerThread;
+import android.annotation.Nullable;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
@@ -113,7 +114,7 @@ public abstract class IntentService extends Service {
}
@Override
- public void onStart(Intent intent, int startId) {
+ public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
@@ -127,7 +128,7 @@ public abstract class IntentService extends Service {
* @see android.app.Service#onStartCommand
*/
@Override
- public int onStartCommand(Intent intent, int flags, int startId) {
+ public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@@ -139,10 +140,11 @@ public abstract class IntentService extends Service {
/**
* Unless you provide binding for your service, you don't need to implement this
- * method, because the default implementation returns null.
+ * method, because the default implementation returns null.
* @see android.app.Service#onBind
*/
@Override
+ @Nullable
public IBinder onBind(Intent intent) {
return null;
}
@@ -158,7 +160,11 @@ public abstract class IntentService extends Service {
*
* @param intent The value passed to {@link
* android.content.Context#startService(Intent)}.
+ * This may be null if the service is being restarted after
+ * its process has gone away; see
+ * {@link android.app.Service#onStartCommand}
+ * for details.
*/
@WorkerThread
- protected abstract void onHandleIntent(Intent intent);
+ protected abstract void onHandleIntent(@Nullable Intent intent);
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 20cacffaae72..a655bfd823b1 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -5142,4 +5142,55 @@ public class DevicePolicyManager {
return null;
}
}
+
+ /**
+ * Called by a profile owner of a managed profile to set the color used for customization.
+ * This color is used as background color of the confirm credentials screen for that user.
+ * The default color is {@link android.graphics.Color#GRAY}.
+ *
+ * <p>The confirm credentials screen can be created using
+ * {@link android.app.KeyguardManager#createConfirmDeviceCredentialIntent}.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param color The 32bit representation of the color to be used.
+ */
+ public void setOrganizationColor(@NonNull ComponentName admin, int color) {
+ try {
+ mService.setOrganizationColor(admin, color);
+ } catch (RemoteException re) {
+ Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ }
+ }
+
+ /**
+ * Called by a profile owner of a managed profile to retrieve the color used for customization.
+ * This color is used as background color of the confirm credentials screen for that user.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @return The 32bit representation of the color to be used.
+ */
+ public int getOrganizationColor(@NonNull ComponentName admin) {
+ try {
+ return mService.getOrganizationColor(admin);
+ } catch (RemoteException re) {
+ Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ return 0;
+ }
+ }
+
+ /**
+ * @hide
+ * Retrieve the customization color for a given user.
+ *
+ * @param userHandle The user id of the user we're interested in.
+ * @return The 32bit representation of the color to be used.
+ */
+ public int getOrganizationColorForUser(int userHandle) {
+ try {
+ return mService.getOrganizationColorForUser(userHandle);
+ } catch (RemoteException re) {
+ Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ return 0;
+ }
+ }
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 08cab8846290..82115a2880f4 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -263,4 +263,8 @@ interface IDevicePolicyManager {
String getLongSupportMessageForUser(in ComponentName admin, int userHandle);
boolean isSeparateProfileChallengeAllowed(int userHandle);
+
+ void setOrganizationColor(in ComponentName admin, in int color);
+ int getOrganizationColor(in ComponentName admin);
+ int getOrganizationColorForUser(int userHandle);
}
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 193a0b2c768d..c27eaa4f59bf 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -426,6 +426,29 @@ public class BackupManager {
}
/**
+ * Ask the framework whether this app is eligible for backup.
+ *
+ * <p>Callers must hold the android.permission.BACKUP permission to use this method.
+ *
+ * @param packageName The name of the package.
+ * @return Whether this app is eligible for backup.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean isAppEligibleForBackup(String packageName) {
+ checkServiceBinder();
+ if (sService != null) {
+ try {
+ return sService.isAppEligibleForBackup(packageName);
+ } catch (RemoteException e) {
+ Log.e(TAG, "isAppEligibleForBackup(pkg) couldn't connect");
+ }
+ }
+ return false;
+ }
+
+ /**
* Request an immediate backup, providing an observer to which results of the backup operation
* will be published. The Android backup system will decide for each package whether it will
* be full app data backup or key/value-pair-based backup.
diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java
index 4363604cba92..aca115f29e78 100644
--- a/core/java/android/app/backup/BackupTransport.java
+++ b/core/java/android/app/backup/BackupTransport.java
@@ -482,6 +482,18 @@ public class BackupTransport {
"Transport cancelFullBackup() not implemented");
}
+ /**
+ * Ask the transport whether this app is eligible for backup.
+ *
+ * @param targetPackage The identity of the application.
+ * @param isFullBackup If set, transport should check if app is eligible for full data backup,
+ * otherwise to check if eligible for key-value backup.
+ * @return Whether this app is eligible for backup.
+ */
+ public boolean isAppEligibleForBackup(PackageInfo targetPackage, boolean isFullBackup) {
+ return true;
+ }
+
// ------------------------------------------------------------------------------------
// Full restore interfaces
@@ -659,6 +671,12 @@ public class BackupTransport {
}
@Override
+ public boolean isAppEligibleForBackup(PackageInfo targetPackage, boolean isFullBackup)
+ throws RemoteException {
+ return BackupTransport.this.isAppEligibleForBackup(targetPackage, isFullBackup);
+ }
+
+ @Override
public int getNextFullRestoreDataChunk(ParcelFileDescriptor socket) {
return BackupTransport.this.getNextFullRestoreDataChunk(socket);
}
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index 2a1c00f9adc4..5d4cc6fe2dc9 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -329,6 +329,16 @@ interface IBackupManager {
long getAvailableRestoreToken(String packageName);
/**
+ * Ask the framework whether this app is eligible for backup.
+ *
+ * <p>Callers must hold the android.permission.BACKUP permission to use this method.
+ *
+ * @param packageName The name of the package.
+ * @return Whether this app is eligible for backup.
+ */
+ boolean isAppEligibleForBackup(String packageName);
+
+ /**
* Request an immediate backup, providing an observer to which results of the backup operation
* will be published. The Android backup system will decide for each package whether it will
* be full app data backup or key/value-pair-based backup.
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index 3ff95228f15e..85893b0c0b08 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -16,6 +16,7 @@
package android.view.inputmethod;
+import android.annotation.Nullable;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -341,20 +342,26 @@ public class EditorInfo implements InputType, Parcelable {
public Bundle extras;
/**
- * Additional context information that tells what languages are expected by the user.
+ * List of the languages that the user is supposed to switch to no matter what input method
+ * subtype is currently used. This special "hint" can be used mainly for, but not limited to,
+ * multilingual users who want IMEs to switch language context automatically.
*
- * <p><strong>IME authors:</strong> Possible use cases for IME developers would be:</p>
- * <ul>
- * <li>Automatically switching keyboard layout.</li>
- * <li>Changing language model for better typing experience.</li>
- * </ul>
+ * <p>{@code null} means that no special language "hint" is needed.</p>
*
- * <p><strong>Editor authors:</strong> Providing this context information can help IMEs to
- * improve text input experience. For example, chat applications can remember what language is
- * used in the last conversation for each chat session, and put the last used language at the
- * top of {@link #locales}.</p>
+ * <p><strong>Editor authors:</strong> Specify this only when you are confident that the user
+ * will switch to certain languages in this context no matter what input method subtype is
+ * currently selected. Otherwise, keep this {@code null}. Explicit user actions and/or
+ * preferences would be good signals to specify this special "hint", For example, a chat
+ * application may be able to put the last used language at the top of {@link #hintLocales}
+ * based on whom the user is going to talk, by remembering what language is used in the last
+ * conversation. Do not specify {@link android.widget.TextView#getTextLocales()} only because
+ * it is used for text rendering.</p>
+ *
+ * @see android.widget.TextView#setImeHintLocales(LocaleList)
+ * @see android.widget.TextView#getImeHintLocales()
*/
- public LocaleList locales = LocaleList.getEmptyLocaleList();
+ @Nullable
+ public LocaleList hintLocales = null;
/**
* Ensure that the data in this EditorInfo is compatible with an application
@@ -410,7 +417,7 @@ public class EditorInfo implements InputType, Parcelable {
+ " fieldId=" + fieldId
+ " fieldName=" + fieldName);
pw.println(prefix + "extras=" + extras);
- pw.println(prefix + "locales=" + locales);
+ pw.println(prefix + "hintLocales=" + hintLocales);
}
/**
@@ -434,7 +441,11 @@ public class EditorInfo implements InputType, Parcelable {
dest.writeInt(fieldId);
dest.writeString(fieldName);
dest.writeBundle(extras);
- locales.writeToParcel(dest, flags);
+ if (hintLocales != null) {
+ hintLocales.writeToParcel(dest, flags);
+ } else {
+ LocaleList.getEmptyLocaleList().writeToParcel(dest, flags);
+ }
}
/**
@@ -458,7 +469,8 @@ public class EditorInfo implements InputType, Parcelable {
res.fieldId = source.readInt();
res.fieldName = source.readString();
res.extras = source.readBundle();
- res.locales = LocaleList.CREATOR.createFromParcel(source);
+ LocaleList hintLocales = LocaleList.CREATOR.createFromParcel(source);
+ res.hintLocales = hintLocales.isEmpty() ? null : hintLocales;
return res;
}
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 4fc66656f625..43306d094bda 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -191,6 +191,8 @@ public final class InputMethodInfo implements Parcelable {
.InputMethod_Subtype_label, 0))
.setSubtypeIconResId(a.getResourceId(com.android.internal.R.styleable
.InputMethod_Subtype_icon, 0))
+ .setLanguageTag(a.getString(com.android.internal.R.styleable
+ .InputMethod_Subtype_languageTag))
.setSubtypeLocale(a.getString(com.android.internal.R.styleable
.InputMethod_Subtype_imeSubtypeLocale))
.setSubtypeMode(a.getString(com.android.internal.R.styleable
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 6241a4cd3462..6c2c956efa7d 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -3203,42 +3203,74 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
return mContextMenuInfo;
}
- /** @hide */
+ @Override
+ public boolean showContextMenu() {
+ return showContextMenuInternal(0, 0, false);
+ }
+
@Override
public boolean showContextMenu(float x, float y) {
+ return showContextMenuInternal(x, y, true);
+ }
+
+ private boolean showContextMenuInternal(float x, float y, boolean useOffsets) {
final int position = pointToPosition((int)x, (int)y);
if (position != INVALID_POSITION) {
final long id = mAdapter.getItemId(position);
View child = getChildAt(position - mFirstPosition);
if (child != null) {
mContextMenuInfo = createContextMenuInfo(child, position, id);
- return super.showContextMenuForChild(AbsListView.this, x, y);
+ if (useOffsets) {
+ return super.showContextMenuForChild(this, x, y);
+ } else {
+ return super.showContextMenuForChild(this);
+ }
}
}
- return super.showContextMenu(x, y);
+ if (useOffsets) {
+ return super.showContextMenu(x, y);
+ } else {
+ return super.showContextMenu();
+ }
}
@Override
public boolean showContextMenuForChild(View originalView) {
+ return showContextMenuForChildInternal(originalView, 0, 0, false);
+ }
+
+ @Override
+ public boolean showContextMenuForChild(View originalView, float x, float y) {
+ return showContextMenuForChildInternal(originalView,x, y, true);
+ }
+
+ private boolean showContextMenuForChildInternal(View originalView, float x, float y,
+ boolean useOffsets) {
final int longPressPosition = getPositionForView(originalView);
- if (longPressPosition >= 0) {
- final long longPressId = mAdapter.getItemId(longPressPosition);
- boolean handled = false;
-
- if (mOnItemLongClickListener != null) {
- handled = mOnItemLongClickListener.onItemLongClick(AbsListView.this, originalView,
- longPressPosition, longPressId);
- }
- if (!handled) {
- mContextMenuInfo = createContextMenuInfo(
- getChildAt(longPressPosition - mFirstPosition),
- longPressPosition, longPressId);
+ if (longPressPosition < 0) {
+ return false;
+ }
+
+ final long longPressId = mAdapter.getItemId(longPressPosition);
+ boolean handled = false;
+
+ if (mOnItemLongClickListener != null) {
+ handled = mOnItemLongClickListener.onItemLongClick(this, originalView,
+ longPressPosition, longPressId);
+ }
+
+ if (!handled) {
+ final View child = getChildAt(longPressPosition - mFirstPosition);
+ mContextMenuInfo = createContextMenuInfo(child, longPressPosition, longPressId);
+
+ if (useOffsets) {
+ handled = super.showContextMenuForChild(originalView, x, y);
+ } else {
handled = super.showContextMenuForChild(originalView);
}
-
- return handled;
}
- return false;
+
+ return handled;
}
@Override
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index df5af25cb73e..4355eb3bcd69 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -69,6 +69,7 @@ import android.text.style.SuggestionSpan;
import android.text.style.TextAppearanceSpan;
import android.text.style.URLSpan;
import android.util.DisplayMetrics;
+import android.util.LocaleList;
import android.util.Log;
import android.util.SparseArray;
import android.view.ActionMode;
@@ -5299,6 +5300,7 @@ public class Editor {
Bundle extras;
OnEditorActionListener onEditorActionListener;
boolean enterDown;
+ LocaleList imeHintLocales;
}
static class InputMethodState {
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index 9ebbe36da1c5..a6ef572a2e3a 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.annotation.NonNull;
import android.annotation.Widget;
import android.content.Context;
import android.content.res.TypedArray;
@@ -1097,15 +1098,15 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList
}
@Override
- public void onLongPress(MotionEvent e) {
-
+ public void onLongPress(@NonNull MotionEvent e) {
if (mDownTouchPosition < 0) {
return;
}
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- long id = getItemIdAtPosition(mDownTouchPosition);
- dispatchLongPress(mDownTouchView, mDownTouchPosition, id);
+
+ final long id = getItemIdAtPosition(mDownTouchPosition);
+ dispatchLongPress(mDownTouchView, mDownTouchPosition, id, e.getX(), e.getY(), true);
}
// Unused methods from GestureDetector.OnGestureListener below
@@ -1159,29 +1160,47 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList
@Override
public boolean showContextMenuForChild(View originalView) {
+ return showContextMenuForChildInternal(originalView, 0, 0, false);
+ }
+
+ @Override
+ public boolean showContextMenuForChild(View originalView, float x, float y) {
+ return showContextMenuForChildInternal(originalView, x, y, true);
+ }
+ private boolean showContextMenuForChildInternal(View originalView, float x, float y,
+ boolean useOffsets) {
final int longPressPosition = getPositionForView(originalView);
if (longPressPosition < 0) {
return false;
}
final long longPressId = mAdapter.getItemId(longPressPosition);
- return dispatchLongPress(originalView, longPressPosition, longPressId);
+ return dispatchLongPress(originalView, longPressPosition, longPressId, x, y, useOffsets);
}
@Override
public boolean showContextMenu() {
-
+ return showContextMenuInternal(0, 0, false);
+ }
+
+ @Override
+ public boolean showContextMenu(float x, float y) {
+ return showContextMenuInternal(x, y, true);
+ }
+
+ private boolean showContextMenuInternal(float x, float y, boolean useOffsets) {
if (isPressed() && mSelectedPosition >= 0) {
- int index = mSelectedPosition - mFirstPosition;
- View v = getChildAt(index);
- return dispatchLongPress(v, mSelectedPosition, mSelectedRowId);
+ final int index = mSelectedPosition - mFirstPosition;
+ final View v = getChildAt(index);
+ return dispatchLongPress(v, mSelectedPosition, mSelectedRowId, x, y, useOffsets);
}
return false;
}
- private boolean dispatchLongPress(View view, int position, long id) {
+ private boolean dispatchLongPress(View view, int position, long id, float x, float y,
+ boolean useOffsets) {
boolean handled = false;
if (mOnItemLongClickListener != null) {
@@ -1191,7 +1210,12 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList
if (!handled) {
mContextMenuInfo = new AdapterContextMenuInfo(view, position, id);
- handled = super.showContextMenuForChild(this);
+
+ if (useOffsets) {
+ handled = super.showContextMenuForChild(view, x, y);
+ } else {
+ handled = super.showContextMenuForChild(this);
+ }
}
if (handled) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 7535caa8981f..c626af65016c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -5002,6 +5002,35 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
/**
+ * Change "hint" locales associated with the text view, which will be reported to an IME with
+ * {@link EditorInfo#hintLocales} when it has focus.
+ *
+ * <p><strong>Note:</strong> If you want new "hint" to take effect immediately you need to
+ * call {@link InputMethodManager#restartInput(View)}.</p>
+ * @param hintLocales List of the languages that the user is supposed to switch to no matter
+ * what input method subtype is currently used. Set {@code null} to clear the current "hint".
+ * @see #getImeHIntLocales()
+ * @see android.view.inputmethod.EditorInfo#hintLocales
+ */
+ public void setImeHintLocales(@Nullable LocaleList hintLocales) {
+ createEditorIfNeeded();
+ mEditor.createInputContentTypeIfNeeded();
+ mEditor.mInputContentType.imeHintLocales = hintLocales;
+ }
+
+ /**
+ * @return The current languages list "hint". {@code null} when no "hint" is available.
+ * @see #setImeHintLocales(LocaleList)
+ * @see android.view.inputmethod.EditorInfo#hintLocales
+ */
+ @Nullable
+ public LocaleList getImeHintLocales() {
+ if (mEditor == null) { return null; }
+ if (mEditor.mInputContentType == null) { return null; }
+ return mEditor.mInputContentType.imeHintLocales;
+ }
+
+ /**
* Returns the error message that was set to be displayed with
* {@link #setError}, or <code>null</code> if no error was set
* or if it the error was cleared by the widget after user input.
@@ -6421,8 +6450,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
outAttrs.actionLabel = mEditor.mInputContentType.imeActionLabel;
outAttrs.actionId = mEditor.mInputContentType.imeActionId;
outAttrs.extras = mEditor.mInputContentType.extras;
+ outAttrs.hintLocales = mEditor.mInputContentType.imeHintLocales;
} else {
outAttrs.imeOptions = EditorInfo.IME_NULL;
+ outAttrs.hintLocales = null;
}
if (focusSearch(FOCUS_DOWN) != null) {
outAttrs.imeOptions |= EditorInfo.IME_FLAG_NAVIGATE_NEXT;
@@ -6450,9 +6481,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_ENTER_ACTION;
}
outAttrs.hintText = mHint;
- // LocaleList is designed to be immutable. This is theoretically equivalent to copy
- // the snapshot of the current text locales.
- outAttrs.locales = getTextLocales();
if (mText instanceof Editable) {
InputConnection ic = new EditableInputConnection(this);
outAttrs.initialSelStart = getSelectionStart();
diff --git a/core/java/com/android/internal/backup/IBackupTransport.aidl b/core/java/com/android/internal/backup/IBackupTransport.aidl
index b1fc20d18d38..444dbfa71e8c 100644
--- a/core/java/com/android/internal/backup/IBackupTransport.aidl
+++ b/core/java/com/android/internal/backup/IBackupTransport.aidl
@@ -239,6 +239,16 @@ interface IBackupTransport {
int sendBackupData(int numBytes);
void cancelFullBackup();
+ /**
+ * Ask the transport whether this app is eligible for backup.
+ *
+ * @param targetPackage The identity of the application.
+ * @param isFullBackup If set, transport should check if app is eligible for full data backup,
+ * otherwise to check if eligible for key-value backup.
+ * @return Whether this app is eligible for backup.
+ */
+ boolean isAppEligibleForBackup(in PackageInfo targetPackage, boolean isFullBackup);
+
// full restore stuff
/**
@@ -286,5 +296,4 @@ interface IBackupTransport {
* operation will immediately be finished with no further attempts to restore app data.
*/
int abortFullRestore();
-
}
diff --git a/core/jni/android/graphics/MinikinUtils.cpp b/core/jni/android/graphics/MinikinUtils.cpp
index 0597d3f37a71..309d35b90260 100644
--- a/core/jni/android/graphics/MinikinUtils.cpp
+++ b/core/jni/android/graphics/MinikinUtils.cpp
@@ -62,6 +62,15 @@ void MinikinUtils::doLayout(Layout* layout, const Paint* paint, int bidiFlags,
layout->doLayout(buf, start, count, bufSize, bidiFlags, minikinStyle, minikinPaint);
}
+float MinikinUtils::measureText(const Paint* paint, int bidiFlags, TypefaceImpl* typeface,
+ const uint16_t* buf, size_t start, size_t count, size_t bufSize, float *advances) {
+ FontCollection *font;
+ MinikinPaint minikinPaint;
+ FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, &font, paint, typeface);
+ return Layout::measureText(buf, start, count, bufSize, bidiFlags, minikinStyle, minikinPaint,
+ font, advances);
+}
+
bool MinikinUtils::hasVariationSelector(TypefaceImpl* typeface, uint32_t codepoint, uint32_t vs) {
const TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(typeface);
return resolvedFace->fFontCollection->hasVariationSelector(codepoint, vs);
diff --git a/core/jni/android/graphics/MinikinUtils.h b/core/jni/android/graphics/MinikinUtils.h
index 5bf1eec4507d..91525397b2ba 100644
--- a/core/jni/android/graphics/MinikinUtils.h
+++ b/core/jni/android/graphics/MinikinUtils.h
@@ -40,6 +40,9 @@ public:
TypefaceImpl* typeface, const uint16_t* buf, size_t start, size_t count,
size_t bufSize);
+ static float measureText(const Paint* paint, int bidiFlags, TypefaceImpl* typeface,
+ const uint16_t* buf, size_t start, size_t count, size_t bufSize, float *advances);
+
static bool hasVariationSelector(TypefaceImpl* typeface, uint32_t codepoint, uint32_t vs);
static float xOffsetForTextAlign(Paint* paint, const Layout& layout);
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 98f8ce3e93c9..a3214eb2c9e3 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -493,16 +493,16 @@ namespace PaintGlue {
return 0;
}
}
-
- Layout layout;
- MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, start, count,
- contextCount);
- if (advances != NULL) {
- std::unique_ptr<jfloat> advancesArray(new jfloat[count]);
- layout.getAdvances(advancesArray.get());
+ std::unique_ptr<jfloat[]> advancesArray;
+ if (advances) {
+ advancesArray.reset(new jfloat[count]);
+ }
+ const float advance = MinikinUtils::measureText(paint, bidiFlags, typeface, text,
+ start, count, contextCount, advancesArray.get());
+ if (advances) {
env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray.get());
}
- return layout.getAdvance();
+ return advance;
}
static jfloat getTextAdvances___CIIIII_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index e54723ea1b13..edbfef9c82bc 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -48,6 +48,9 @@ import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.KeyEvent;
+import static org.hamcrest.Matchers.anyOf;
+import static org.hamcrest.Matchers.is;
+
/**
* Tests the TextView widget from an Activity
*/
@@ -84,6 +87,43 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV
}
@SmallTest
+ public void testPositionCursorAtTextAtIndex_arabic() throws Exception {
+ // Arabic text. The expected cursorable boundary is
+ // | \u0623 \u064F | \u067A | \u0633 \u0652 |
+ final String text = "\u0623\u064F\u067A\u0633\u0652";
+ onView(withId(R.id.textview)).perform(click());
+ onView(withId(R.id.textview)).perform(replaceText(text));
+
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(0));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(1));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(anyOf(is(0), is(2))));
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(2));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(2));
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(3));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(3));
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(4));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(anyOf(is(3), is(5))));
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(5));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(5));
+ }
+
+ @SmallTest
+ public void testPositionCursorAtTextAtIndex_devanagari() throws Exception {
+ // Devanagari text. The expected cursorable boundary is | \u0915 \u093E |
+ final String text = "\u0915\u093E";
+ onView(withId(R.id.textview)).perform(click());
+ onView(withId(R.id.textview)).perform(replaceText(text));
+
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(0));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(1));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(anyOf(is(0), is(2))));
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(2));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(2));
+ }
+
+ @SmallTest
public void testLongPressToSelect() throws Exception {
final String helloWorld = "Hello Kirk!";
onView(withId(R.id.textview)).perform(click());
diff --git a/libs/androidfw/DisplayEventDispatcher.cpp b/libs/androidfw/DisplayEventDispatcher.cpp
index 99cd1732031c..b8ef9ea49293 100644
--- a/libs/androidfw/DisplayEventDispatcher.cpp
+++ b/libs/androidfw/DisplayEventDispatcher.cpp
@@ -103,7 +103,7 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) {
int32_t vsyncDisplayId;
uint32_t vsyncCount;
if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
- ALOGE("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 ", id=%d, count=%d",
+ ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 ", id=%d, count=%d",
this, ns2ms(vsyncTimestamp), vsyncDisplayId, vsyncCount);
mWaitingForVsync = false;
dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp
index c5000e4cadbc..92de89491127 100644
--- a/libs/hwui/Texture.cpp
+++ b/libs/hwui/Texture.cpp
@@ -180,6 +180,10 @@ static void colorTypeToGlFormatAndType(SkColorType colorType,
*outFormat = GL_RGBA;
*outType = GL_UNSIGNED_BYTE;
break;
+ case kGray_8_SkColorType:
+ *outFormat = GL_LUMINANCE;
+ *outType = GL_UNSIGNED_BYTE;
+ break;
default:
LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", colorType);
break;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
index 7f6b1e1d3abd..7a238bd6ce7d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
@@ -24,6 +24,7 @@ import android.content.Context;
import android.os.RemoteException;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
+import android.util.Log;
import com.android.documentsui.R;
import com.android.documentsui.model.DocumentInfo;
@@ -92,6 +93,15 @@ final class MoveJob extends CopyJob {
}
}
+ // Moving virtual files by bytes is not supported. This is because, it would involve
+ // conversion, and the source file should not be deleted in such case (as it's a different
+ // file).
+ if (src.isVirtualDocument()) {
+ Log.w(TAG, "Cannot move virtual files byte by byte.");
+ onFileFailed(src);
+ return false;
+ }
+
// If we couldn't do an optimized copy...we fall back to vanilla byte copy.
boolean copied = byteCopyDocument(src, dest);
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/services/MoveJobTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/services/MoveJobTest.java
index 7edfcdb8f82f..69d2db778be9 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/services/MoveJobTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/services/MoveJobTest.java
@@ -16,6 +16,9 @@
package com.android.documentsui.services;
+import static com.google.common.collect.Lists.newArrayList;
+
+import android.net.Uri;
import android.test.suitebuilder.annotation.MediumTest;
import com.android.documentsui.model.DocumentInfo;
@@ -33,15 +36,23 @@ public class MoveJobTest extends AbstractCopyJobTest<MoveJob> {
}
public void testMoveVirtualTypedFile() throws Exception {
- runCopyVirtualTypedFileTest();
+ Uri testFile = mDocs.createVirtualFile(
+ mSrcRoot, "/virtual.sth", "virtual/mime-type",
+ FRUITY_BYTES, "application/pdf", "text/html");
+ createJob(newArrayList(testFile)).run();
- mDocs.assertChildCount(mSrcRoot, 0);
+ mJobListener.waitForFinished();
+
+ // Should have failed, source not deleted. Moving by bytes for virtual files
+ // is not supported.
+ mDocs.assertChildCount(mDestRoot, 0);
+ mDocs.assertChildCount(mSrcRoot, 1);
}
public void testMoveVirtualNonTypedFile() throws Exception {
runCopyVirtualNonTypedFileTest();
- // should have failed, source not deleted
+ // Should have failed, source not deleted.
mDocs.assertChildCount(mSrcRoot, 1);
}
diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
deleted file mode 100644
index 1fcb2dfdd6c3..000000000000
--- a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
+++ /dev/null
@@ -1,322 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2012, 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.
--->
-
-<!-- navigation bar for sw600dp (small tablets) -->
-<com.android.systemui.statusbar.phone.NavigationBarView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:background="@drawable/system_bar_background"
- >
-
- <FrameLayout android:id="@+id/rot0"
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- >
-
- <LinearLayout
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:orientation="horizontal"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:id="@+id/nav_buttons"
- android:animateLayoutChanges="true"
- >
-
- <!-- navigation controls -->
- <View
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:layout_weight="0"
- android:layout_marginStart="2dp"
- android:visibility="invisible"
- />
- <Space
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
- android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_back"
- android:scaleType="centerInside"
- systemui:keyCode="4"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_back"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
- android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_home"
- android:scaleType="centerInside"
- systemui:keyCode="3"
- systemui:keyRepeat="true"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_home"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
- android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_recent"
- android:scaleType="centerInside"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_recent"
- />
- <Space
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- />
- <FrameLayout
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:layout_weight="0"
- android:layout_marginEnd="2dp" >
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_menu"
- android:scaleType="centerInside"
- android:layout_marginEnd="2dp"
- systemui:keyCode="82"
- android:visibility="invisible"
- android:contentDescription="@string/accessibility_menu"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView
- android:id="@+id/ime_switcher"
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="2dp"
- android:scaleType="centerInside"
- android:src="@drawable/ic_ime_switcher_default"
- android:visibility="invisible"
- android:contentDescription="@string/accessibility_ime_switch_button" />
- </FrameLayout>
- </LinearLayout>
-
- <!-- lights out layout to match exactly -->
- <LinearLayout
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:orientation="horizontal"
- android:id="@+id/lights_out"
- android:visibility="gone"
- >
- <Space
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- />
- <ImageView
- android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
- android:layout_height="match_parent"
- android:layout_marginStart="40dp"
- android:src="@drawable/ic_sysbar_lights_out_dot_small"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_back"
- />
- <ImageView
- android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_lights_out_dot_large"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_home"
- />
- <ImageView
- android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
- android:layout_marginEnd="40dp"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_lights_out_dot_small"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_recent"
- />
- <Space
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- />
- </LinearLayout>
-
- <com.android.systemui.statusbar.policy.DeadZone
- android:id="@+id/deadzone"
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- systemui:minSize="@dimen/navigation_bar_deadzone_size"
- systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
- systemui:holdTime="@integer/navigation_bar_deadzone_hold"
- systemui:decayTime="@integer/navigation_bar_deadzone_decay"
- systemui:orientation="horizontal"
- android:layout_gravity="top"
- />
- </FrameLayout>
-
- <FrameLayout android:id="@+id/rot90"
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:visibility="gone"
- android:paddingTop="0dp"
- >
-
- <LinearLayout
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:orientation="horizontal"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:id="@+id/nav_buttons"
- android:animateLayoutChanges="true"
- >
-
- <!-- navigation controls -->
- <View
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:layout_weight="0"
- android:layout_marginStart="2dp"
- android:visibility="invisible"
- />
- <Space
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
- android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_back"
- android:scaleType="centerInside"
- systemui:keyCode="4"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_back"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
- android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_home"
- android:scaleType="centerInside"
- systemui:keyCode="3"
- systemui:keyRepeat="true"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_home"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
- android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_recent"
- android:scaleType="centerInside"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_recent"
- />
- <Space
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- />
- <FrameLayout
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="2dp"
- android:layout_weight="0" >
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="2dp"
- android:src="@drawable/ic_sysbar_menu"
- android:scaleType="centerInside"
- systemui:keyCode="82"
- android:visibility="invisible"
- android:contentDescription="@string/accessibility_menu" />
- <com.android.systemui.statusbar.policy.KeyButtonView
- android:id="@+id/ime_switcher"
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="2dp"
- android:src="@drawable/ic_ime_switcher_default"
- android:visibility="invisible"
- android:contentDescription="@string/accessibility_ime_switch_button"
- android:scaleType="centerInside" />
- </FrameLayout>
- </LinearLayout>
-
- <!-- lights out layout to match exactly -->
- <LinearLayout
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:orientation="horizontal"
- android:id="@+id/lights_out"
- android:visibility="gone"
- >
- <Space
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- />
- <ImageView
- android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
- android:layout_height="match_parent"
- android:layout_marginStart="40dp"
- android:src="@drawable/ic_sysbar_lights_out_dot_small"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_back"
- />
- <ImageView
- android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_lights_out_dot_large"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_home"
- />
- <ImageView
- android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
- android:layout_marginEnd="40dp"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_lights_out_dot_small"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_recent"
- />
- <Space
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- />
- </LinearLayout>
-
- <!-- On tablets in landscape the navbar is on the bottom, so use a
- horizontal dead zone. -->
- <com.android.systemui.statusbar.policy.DeadZone
- android:id="@+id/deadzone"
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- systemui:minSize="@dimen/navigation_bar_deadzone_size"
- systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
- systemui:holdTime="@integer/navigation_bar_deadzone_hold"
- systemui:decayTime="@integer/navigation_bar_deadzone_decay"
- systemui:orientation="horizontal"
- android:layout_gravity="top"
- />
- </FrameLayout>
-</com.android.systemui.statusbar.phone.NavigationBarView>
diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_layout_rot90.xml b/packages/SystemUI/res/layout-sw600dp/navigation_layout_rot90.xml
new file mode 100644
index 000000000000..dd559c534351
--- /dev/null
+++ b/packages/SystemUI/res/layout-sw600dp/navigation_layout_rot90.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <FrameLayout
+ android:id="@+id/nav_buttons"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:id="@+id/start_group"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="start"
+ android:orientation="horizontal" />
+
+ <LinearLayout
+ android:id="@+id/center_group"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:orientation="horizontal" />
+
+ <LinearLayout
+ android:id="@+id/end_group"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="end"
+ android:orientation="horizontal" />
+
+ </FrameLayout>
+
+ <FrameLayout
+ android:id="@+id/lights_out"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:id="@+id/start_group_lightsout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="start"
+ android:orientation="horizontal" />
+
+ <LinearLayout
+ android:id="@+id/center_group_lightsout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:orientation="horizontal" />
+
+ <LinearLayout
+ android:id="@+id/end_group_lightsout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="end"
+ android:orientation="horizontal" />
+
+ </FrameLayout>
+
+ <com.android.systemui.statusbar.policy.DeadZone
+ android:id="@+id/deadzone"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:layout_gravity="top"
+ systemui:minSize="@dimen/navigation_bar_deadzone_size"
+ systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
+ systemui:holdTime="@integer/navigation_bar_deadzone_hold"
+ systemui:decayTime="@integer/navigation_bar_deadzone_decay"
+ systemui:orientation="horizontal"
+ />
+
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/back.xml b/packages/SystemUI/res/layout/back.xml
new file mode 100644
index 000000000000..d2566224d02b
--- /dev/null
+++ b/packages/SystemUI/res/layout/back.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<com.android.systemui.statusbar.policy.KeyButtonView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/back"
+ android:layout_width="@dimen/navigation_key_width"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:src="@drawable/ic_sysbar_back"
+ systemui:keyCode="4"
+ android:scaleType="center"
+ android:contentDescription="@string/accessibility_back"
+ android:paddingStart="@dimen/navigation_key_padding"
+ android:paddingEnd="@dimen/navigation_key_padding"
+ />
+
diff --git a/packages/SystemUI/res/layout/home.xml b/packages/SystemUI/res/layout/home.xml
new file mode 100644
index 000000000000..f11592de37ef
--- /dev/null
+++ b/packages/SystemUI/res/layout/home.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<com.android.systemui.statusbar.policy.KeyButtonView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/home"
+ android:layout_width="@dimen/navigation_key_width"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:src="@drawable/ic_sysbar_home"
+ systemui:keyCode="3"
+ android:scaleType="center"
+ android:contentDescription="@string/accessibility_home"
+ android:paddingStart="@dimen/navigation_key_padding"
+ android:paddingEnd="@dimen/navigation_key_padding"
+ />
+
diff --git a/packages/SystemUI/res/layout/menu_ime.xml b/packages/SystemUI/res/layout/menu_ime.xml
new file mode 100644
index 000000000000..90b74d0b57d1
--- /dev/null
+++ b/packages/SystemUI/res/layout/menu_ime.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:layout_width="@dimen/navigation_side_padding"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ >
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/menu"
+ android:layout_width="@dimen/navigation_extra_key_width"
+ android:layout_height="match_parent"
+ android:layout_marginEnd="2dp"
+ android:src="@drawable/ic_sysbar_menu"
+ android:scaleType="centerInside"
+ systemui:keyCode="82"
+ android:visibility="invisible"
+ android:contentDescription="@string/accessibility_menu"
+ />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/ime_switcher"
+ android:layout_width="@dimen/navigation_extra_key_width"
+ android:layout_height="match_parent"
+ android:layout_marginEnd="2dp"
+ android:src="@drawable/ic_ime_switcher_default"
+ android:visibility="invisible"
+ android:contentDescription="@string/accessibility_ime_switch_button"
+ android:scaleType="centerInside"
+ />
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/nav_key_space.xml b/packages/SystemUI/res/layout/nav_key_space.xml
new file mode 100644
index 000000000000..3986841b1838
--- /dev/null
+++ b/packages/SystemUI/res/layout/nav_key_space.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+** Copyright 2016, 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.
+*/
+-->
+
+<Space xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:layout_width="@dimen/navigation_side_padding"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ >
+</Space>
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index 8498a4f08e8f..36e937d4d3ef 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -22,309 +22,17 @@
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
- android:background="@drawable/system_bar_background"
- >
+ android:background="@drawable/system_bar_background">
- <FrameLayout android:id="@+id/rot0"
- android:layout_height="match_parent"
+ <com.android.systemui.statusbar.phone.NavigationBarInflaterView
+ android:id="@+id/navigation_inflater"
android:layout_width="match_parent"
- >
+ android:layout_height="match_parent">
- <LinearLayout
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:orientation="horizontal"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:id="@+id/nav_buttons"
- android:animateLayoutChanges="true"
- >
+ <include android:id="@+id/rot0" layout="@layout/navigation_layout" />
- <!-- navigation controls -->
- <View
- android:layout_width="@dimen/navigation_side_padding"
- android:layout_height="match_parent"
- android:layout_weight="0"
- android:visibility="invisible"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
- android:layout_width="@dimen/navigation_key_width"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_back"
- systemui:keyCode="4"
- android:layout_weight="0"
- android:scaleType="center"
- android:contentDescription="@string/accessibility_back"
- />
- <View
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:visibility="invisible"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
- android:layout_width="@dimen/navigation_key_width"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_home"
- systemui:keyCode="3"
- systemui:keyRepeat="false"
- android:layout_weight="0"
- android:scaleType="center"
- android:contentDescription="@string/accessibility_home"
- />
- <View
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:visibility="invisible"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
- android:layout_width="@dimen/navigation_key_width"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_recent"
- android:layout_weight="0"
- android:scaleType="center"
- android:contentDescription="@string/accessibility_recent"
- />
- <FrameLayout
- android:layout_width="@dimen/navigation_side_padding"
- android:layout_height="match_parent"
- android:layout_weight="0" >
- <com.android.systemui.statusbar.policy.KeyButtonView
- android:id="@+id/menu"
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:contentDescription="@string/accessibility_menu"
- android:src="@drawable/ic_sysbar_menu"
- android:visibility="invisible"
- android:scaleType="centerInside"
- android:layout_gravity="end"
- systemui:keyCode="82" />
+ <include android:id="@+id/rot90" layout="@layout/navigation_layout_rot90" />
- <com.android.systemui.statusbar.policy.KeyButtonView
- android:id="@+id/ime_switcher"
- android:layout_width="@dimen/navigation_extra_key_width"
- android:layout_height="match_parent"
- android:contentDescription="@string/accessibility_ime_switch_button"
- android:scaleType="centerInside"
- android:src="@drawable/ic_ime_switcher_default"
- android:visibility="invisible"
- android:layout_gravity="end" />
- </FrameLayout>
-
- </LinearLayout>
-
- <!-- lights out layout to match exactly -->
- <LinearLayout
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:orientation="horizontal"
- android:id="@+id/lights_out"
- android:visibility="gone"
- >
- <ImageView
- android:layout_width="@dimen/navigation_key_width"
- android:layout_height="match_parent"
- android:layout_marginStart="@dimen/navigation_side_padding"
- android:src="@drawable/ic_sysbar_lights_out_dot_small"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_back"
- />
- <View
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:visibility="invisible"
- />
- <ImageView
- android:layout_width="@dimen/navigation_key_width"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_lights_out_dot_large"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_home"
- />
- <View
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:visibility="invisible"
- />
- <ImageView
- android:layout_width="@dimen/navigation_key_width"
- android:layout_marginEnd="@dimen/navigation_side_padding"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_lights_out_dot_small"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_recent"
- />
- </LinearLayout>
-
- <com.android.systemui.statusbar.policy.DeadZone
- android:id="@+id/deadzone"
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- systemui:minSize="@dimen/navigation_bar_deadzone_size"
- systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
- systemui:holdTime="@integer/navigation_bar_deadzone_hold"
- systemui:decayTime="@integer/navigation_bar_deadzone_decay"
- systemui:orientation="horizontal"
- android:layout_gravity="top"
- />
- </FrameLayout>
-
- <FrameLayout android:id="@+id/rot90"
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:visibility="gone"
- android:paddingTop="0dp"
- >
-
- <LinearLayout
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:orientation="vertical"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:id="@+id/nav_buttons"
- android:animateLayoutChanges="true"
- >
-
- <!-- navigation controls -->
- <FrameLayout
- android:layout_weight="0"
- android:layout_width="match_parent"
- android:layout_height="@dimen/navigation_side_padding" >
- <com.android.systemui.statusbar.policy.KeyButtonView
- android:id="@+id/ime_switcher"
- android:layout_width="match_parent"
- android:layout_height="@dimen/navigation_extra_key_width"
- android:contentDescription="@string/accessibility_ime_switch_button"
- android:scaleType="centerInside"
- android:src="@drawable/ic_ime_switcher_default"
- android:layout_gravity="top"
- android:visibility="invisible" />
-
- <com.android.systemui.statusbar.policy.KeyButtonView
- android:id="@+id/menu"
- android:layout_width="match_parent"
- android:layout_height="40dp"
- android:contentDescription="@string/accessibility_menu"
- android:src="@drawable/ic_sysbar_menu"
- android:scaleType="centerInside"
- android:layout_gravity="top"
- android:visibility="invisible"
- systemui:keyCode="82" />
- </FrameLayout>
-
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
- android:layout_height="@dimen/navigation_key_width"
- android:layout_width="match_parent"
- android:src="@drawable/ic_sysbar_recent"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_recent"
- />
- <View
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:layout_weight="1"
- android:visibility="invisible"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
- android:layout_height="@dimen/navigation_key_width"
- android:layout_width="match_parent"
- android:src="@drawable/ic_sysbar_home"
- android:scaleType="center"
- systemui:keyCode="3"
- systemui:keyRepeat="false"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_home"
- />
- <View
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:layout_weight="1"
- android:visibility="invisible"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
- android:layout_height="@dimen/navigation_key_width"
- android:layout_width="match_parent"
- android:src="@drawable/ic_sysbar_back"
- android:scaleType="center"
- systemui:keyCode="4"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_back"
- />
- <View
- android:layout_height="@dimen/navigation_side_padding"
- android:layout_width="match_parent"
- android:layout_weight="0"
- android:visibility="invisible"
- />
- </LinearLayout>
-
- <!-- lights out layout to match exactly -->
- <LinearLayout
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:orientation="vertical"
- android:id="@+id/lights_out"
- android:visibility="gone"
- >
- <ImageView
- android:layout_height="@dimen/navigation_key_width"
- android:layout_marginTop="@dimen/navigation_side_padding"
- android:layout_width="match_parent"
- android:src="@drawable/ic_sysbar_lights_out_dot_small"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_recent"
- />
- <View
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:layout_weight="1"
- android:visibility="invisible"
- />
- <ImageView
- android:layout_height="@dimen/navigation_key_width"
- android:layout_width="match_parent"
- android:src="@drawable/ic_sysbar_lights_out_dot_large"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_home"
- />
- <View
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:layout_weight="1"
- android:visibility="invisible"
- />
- <ImageView
- android:layout_height="@dimen/navigation_key_width"
- android:layout_marginBottom="@dimen/navigation_side_padding"
- android:layout_width="match_parent"
- android:src="@drawable/ic_sysbar_lights_out_dot_small"
- android:scaleType="center"
- android:layout_weight="0"
- android:contentDescription="@string/accessibility_back"
- />
- </LinearLayout>
-
- <com.android.systemui.statusbar.policy.DeadZone
- android:id="@+id/deadzone"
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- systemui:minSize="@dimen/navigation_bar_deadzone_size"
- systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
- systemui:holdTime="@integer/navigation_bar_deadzone_hold"
- systemui:decayTime="@integer/navigation_bar_deadzone_decay"
- systemui:orientation="vertical"
- android:layout_gravity="top"
- />
- </FrameLayout>
+ </com.android.systemui.statusbar.phone.NavigationBarInflaterView>
</com.android.systemui.statusbar.phone.NavigationBarView>
diff --git a/packages/SystemUI/res/layout/navigation_layout.xml b/packages/SystemUI/res/layout/navigation_layout.xml
new file mode 100644
index 000000000000..7ebf4edfc78b
--- /dev/null
+++ b/packages/SystemUI/res/layout/navigation_layout.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <FrameLayout
+ android:id="@+id/nav_buttons"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:id="@+id/start_group"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="start"
+ android:orientation="horizontal" />
+
+ <LinearLayout
+ android:id="@+id/center_group"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:orientation="horizontal" />
+
+ <LinearLayout
+ android:id="@+id/end_group"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="end"
+ android:orientation="horizontal" />
+
+ </FrameLayout>
+
+ <FrameLayout
+ android:id="@+id/lights_out"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:id="@+id/start_group_lightsout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="start"
+ android:orientation="horizontal" />
+
+ <LinearLayout
+ android:id="@+id/center_group_lightsout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:orientation="horizontal" />
+
+ <LinearLayout
+ android:id="@+id/end_group_lightsout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="end"
+ android:orientation="horizontal" />
+
+ </FrameLayout>
+
+ <com.android.systemui.statusbar.policy.DeadZone
+ android:id="@+id/deadzone"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:layout_gravity="top"
+ systemui:minSize="@dimen/navigation_bar_deadzone_size"
+ systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
+ systemui:holdTime="@integer/navigation_bar_deadzone_hold"
+ systemui:decayTime="@integer/navigation_bar_deadzone_decay"
+ systemui:orientation="horizontal"
+ />
+
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/navigation_layout_rot90.xml b/packages/SystemUI/res/layout/navigation_layout_rot90.xml
new file mode 100644
index 000000000000..46df97347a1c
--- /dev/null
+++ b/packages/SystemUI/res/layout/navigation_layout_rot90.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <FrameLayout
+ android:id="@+id/nav_buttons"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.android.systemui.statusbar.phone.ReverseLinearLayout
+ android:id="@+id/start_group"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="bottom"
+ android:orientation="vertical" />
+
+ <com.android.systemui.statusbar.phone.ReverseLinearLayout
+ android:id="@+id/center_group"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:orientation="vertical" />
+
+ <com.android.systemui.statusbar.phone.ReverseLinearLayout
+ android:id="@+id/end_group"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="top"
+ android:orientation="vertical" />
+
+ </FrameLayout>
+
+ <FrameLayout
+ android:id="@+id/lights_out"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.android.systemui.statusbar.phone.ReverseLinearLayout
+ android:id="@+id/start_group_lightsout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="bottom"
+ android:orientation="vertical" />
+
+ <com.android.systemui.statusbar.phone.ReverseLinearLayout
+ android:id="@+id/center_group_lightsout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:orientation="vertical" />
+
+ <com.android.systemui.statusbar.phone.ReverseLinearLayout
+ android:id="@+id/end_group_lightsout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="top"
+ android:orientation="vertical" />
+
+ </FrameLayout>
+
+ <com.android.systemui.statusbar.policy.DeadZone
+ android:id="@+id/deadzone"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:layout_gravity="top"
+ systemui:minSize="@dimen/navigation_bar_deadzone_size"
+ systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
+ systemui:holdTime="@integer/navigation_bar_deadzone_hold"
+ systemui:decayTime="@integer/navigation_bar_deadzone_decay"
+ systemui:orientation="vertical"
+ />
+
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/recent_apps.xml b/packages/SystemUI/res/layout/recent_apps.xml
new file mode 100644
index 000000000000..eb8ee43c0263
--- /dev/null
+++ b/packages/SystemUI/res/layout/recent_apps.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<com.android.systemui.statusbar.policy.KeyButtonView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/recent_apps"
+ android:layout_width="@dimen/navigation_key_width"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:src="@drawable/ic_sysbar_recent"
+ android:scaleType="center"
+ android:contentDescription="@string/accessibility_recent"
+ android:paddingStart="@dimen/navigation_key_padding"
+ android:paddingEnd="@dimen/navigation_key_padding"
+ />
+
diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
index f084bc2c3ddb..be5b856a65f5 100644
--- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
@@ -34,4 +34,7 @@
In sw600dp we want the buttons centered so this fills the space,
(screen_pinning_request_width - 3 * screen_pinning_request_button_width) / 2 -->
<dimen name="screen_pinning_request_side_width">2dp</dimen>
+
+ <dimen name="navigation_key_width">162dp</dimen>
+ <dimen name="navigation_key_padding">42dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index 17ff19549a0d..db4da10756ed 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -42,4 +42,8 @@
while the stack is not focused. -->
<item name="recents_layout_unfocused_range_min" format="float" type="integer">-2</item>
<item name="recents_layout_unfocused_range_max" format="float" type="integer">2.5</item>
+
+ <!-- Nav bar button default ordering/layout -->
+ <string name="config_navBarLayout" translatable="false">space;back,home,recent;menu_ime</string>
+
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 49dbac2f5f65..71f92fd18587 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -90,4 +90,7 @@
<dimen name="screen_pinning_request_side_width">8dp</dimen>
<dimen name="fab_margin">24dp</dimen>
+
+ <dimen name="navigation_key_width">128dp</dimen>
+ <dimen name="navigation_key_padding">25dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 7a873147fdfb..aedc2c52e05b 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -288,5 +288,8 @@
<!-- SystemUIFactory component -->
<string name="config_systemUIFactoryComponent" translatable="false">com.android.systemui.SystemUIFactory</string>
+ <!-- Nav bar button default ordering/layout -->
+ <string name="config_navBarLayout" translatable="false">space,back;home;recent,menu_ime</string>
+
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index d7bd86ffa887..46a0f2ae2ae7 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -96,6 +96,11 @@
<!-- The width of the view containing navigation buttons -->
<dimen name="navigation_key_width">70dp</dimen>
+ <dimen name="navigation_key_padding">0dp</dimen>
+
+ <dimen name="navigation_key_width_sw600dp_land">162dp</dimen>
+ <dimen name="navigation_key_padding_sw600dp_land">42dp</dimen>
+
<!-- The width of the view containing the menu/ime navigation bar icons -->
<dimen name="navigation_extra_key_width">36dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 3eee08766c73..f8cbf656dfa0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -651,7 +651,7 @@ public class RecentsImpl extends IRecentsNonSystemUserCallbacks.Stub implements
mDummyStackView.updateLayoutForStack(stack);
final Task toTask = new Task();
final TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView,
- topTask.id, toTask);
+ toTask);
ForegroundThread.getHandler().postAtFrontOfQueue(new Runnable() {
@Override
public void run() {
@@ -721,7 +721,7 @@ public class RecentsImpl extends IRecentsNonSystemUserCallbacks.Stub implements
// Update the destination rect
Task toTask = new Task();
TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView,
- topTask.id, toTask);
+ toTask);
RectF toTaskRect = toTransform.rect;
Bitmap thumbnail = getThumbnailBitmap(topTask, toTask, toTransform);
if (thumbnail != null) {
@@ -754,14 +754,14 @@ public class RecentsImpl extends IRecentsNonSystemUserCallbacks.Stub implements
* Returns the transition rect for the given task id.
*/
private TaskViewTransform getThumbnailTransitionTransform(TaskStack stack,
- TaskStackView stackView, int runningTaskId, Task runningTaskOut) {
+ TaskStackView stackView, Task runningTaskOut) {
// Find the running task in the TaskStack
Task launchTask = stack.getLaunchTarget();
if (launchTask != null) {
runningTaskOut.copyFrom(launchTask);
} else {
// If no task is specified or we can not find the task just use the front most one
- launchTask = stack.getStackFrontMostTask();
+ launchTask = stack.getStackFrontMostTask(true /* includeFreeform */);
runningTaskOut.copyFrom(launchTask);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index c73273e6f258..de1daa8ea988 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -527,9 +527,9 @@ public class TaskStack {
*/
public void removeTask(Task t, TaskViewAnimation animation) {
if (mStackTaskList.contains(t)) {
- boolean wasFrontMostTask = (getStackFrontMostTask() == t);
+ boolean wasFrontMostTask = (getStackFrontMostTask(false /* includeFreeform */) == t);
removeTaskImpl(mStackTaskList, t);
- Task newFrontMostTask = getStackFrontMostTask();
+ Task newFrontMostTask = getStackFrontMostTask(false /* includeFreeform */);
if (mCb != null) {
// Notify that a task has been removed
mCb.onStackTaskRemoved(this, t, wasFrontMostTask, newFrontMostTask, animation);
@@ -616,14 +616,14 @@ public class TaskStack {
/**
* Gets the front-most task in the stack.
*/
- public Task getStackFrontMostTask() {
+ public Task getStackFrontMostTask(boolean includeFreeformTasks) {
ArrayList<Task> stackTasks = mStackTaskList.getTasks();
if (stackTasks.isEmpty()) {
return null;
}
for (int i = stackTasks.size() - 1; i >= 0; i--) {
Task task = stackTasks.get(i);
- if (!task.isFreeformTask()) {
+ if (!task.isFreeformTask() || includeFreeformTasks) {
return task;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 809d4eed7a11..de045f46f9f9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -1427,7 +1427,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
// Restore the action button visibility if it is the front most task view
- if (mScreenPinningEnabled && tv.getTask() == mStack.getStackFrontMostTask()) {
+ if (mScreenPinningEnabled && tv.getTask() ==
+ mStack.getStackFrontMostTask(false /* includeFreeform */)) {
tv.showActionButton(false /* fadeIn */, 0 /* fadeInDuration */);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
new file mode 100644
index 000000000000..8e3886bcb2de
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import com.android.systemui.statusbar.policy.KeyButtonView;
+
+import android.graphics.drawable.Drawable;
+import android.view.View;
+import android.widget.ImageView;
+
+import java.util.ArrayList;
+
+/**
+ * Dispatches common view calls to multiple views. This is used to handle
+ * multiples of the same nav bar icon appearing.
+ */
+public class ButtonDispatcher {
+
+ private final ArrayList<View> mViews = new ArrayList<>();
+
+ private final int mId;
+
+ private View.OnClickListener mClickListener;
+ private View.OnTouchListener mTouchListener;
+ private View.OnLongClickListener mLongClickListener;
+ private Boolean mLongClickable;
+ private Integer mAlpha;
+ private Integer mVisibility = -1;
+ private int mImageResource = -1;
+ private Drawable mImageDrawable;
+ private View mCurrentView;
+
+ public ButtonDispatcher(int id) {
+ mId = id;
+ }
+
+ void clear() {
+ mViews.clear();
+ }
+
+ void addView(View view) {
+ mViews.add(view);
+ view.setOnClickListener(mClickListener);
+ view.setOnTouchListener(mTouchListener);
+ view.setOnLongClickListener(mLongClickListener);
+ if (mLongClickable != null) {
+ view.setLongClickable(mLongClickable);
+ }
+ if (mAlpha != null) {
+ view.setAlpha(mAlpha);
+ }
+ if (mVisibility != null) {
+ view.setVisibility(mVisibility);
+ }
+ if (mImageResource > 0) {
+ ((ImageView) view).setImageResource(mImageResource);
+ } else if (mImageDrawable != null) {
+ ((ImageView) view).setImageDrawable(mImageDrawable);
+ }
+ }
+
+ public int getId() {
+ return mId;
+ }
+
+ public int getVisibility() {
+ return mVisibility;
+ }
+
+ public float getAlpha() {
+ return mAlpha;
+ }
+
+ public void setImageDrawable(Drawable drawable) {
+ mImageDrawable = drawable;
+ mImageResource = -1;
+ final int N = mViews.size();
+ for (int i = 0; i < N; i++) {
+ ((ImageView) mViews.get(i)).setImageDrawable(mImageDrawable);
+ }
+ }
+
+ public void setImageResource(int resource) {
+ mImageResource = resource;
+ mImageDrawable = null;
+ final int N = mViews.size();
+ for (int i = 0; i < N; i++) {
+ ((ImageView) mViews.get(i)).setImageResource(mImageResource);
+ }
+ }
+
+ public void setVisibility(int visibility) {
+ if (mVisibility == visibility) return;
+ mVisibility = visibility;
+ final int N = mViews.size();
+ for (int i = 0; i < N; i++) {
+ mViews.get(i).setVisibility(mVisibility);
+ }
+ }
+
+ public void abortCurrentGesture() {
+ // This seems to be an instantaneous thing, so not going to persist it.
+ final int N = mViews.size();
+ for (int i = 0; i < N; i++) {
+ ((KeyButtonView) mViews.get(i)).abortCurrentGesture();
+ }
+ }
+
+ public void setAlpha(int alpha) {
+ mAlpha = alpha;
+ final int N = mViews.size();
+ for (int i = 0; i < N; i++) {
+ mViews.get(i).setAlpha(alpha);
+ }
+ }
+
+ public void setOnClickListener(View.OnClickListener clickListener) {
+ mClickListener = clickListener;
+ final int N = mViews.size();
+ for (int i = 0; i < N; i++) {
+ mViews.get(i).setOnClickListener(mClickListener);
+ }
+ }
+
+ public void setOnTouchListener(View.OnTouchListener touchListener) {
+ mTouchListener = touchListener;
+ final int N = mViews.size();
+ for (int i = 0; i < N; i++) {
+ mViews.get(i).setOnTouchListener(mTouchListener);
+ }
+ }
+
+ public void setLongClickable(boolean isLongClickable) {
+ mLongClickable = isLongClickable;
+ final int N = mViews.size();
+ for (int i = 0; i < N; i++) {
+ mViews.get(i).setLongClickable(mLongClickable);
+ }
+ }
+
+ public void setOnLongClickListener(View.OnLongClickListener longClickListener) {
+ mLongClickListener = longClickListener;
+ final int N = mViews.size();
+ for (int i = 0; i < N; i++) {
+ mViews.get(i).setOnLongClickListener(mLongClickListener);
+ }
+ }
+
+ public View getCurrentView() {
+ return mCurrentView;
+ }
+
+ public void setCurrentView(View currentView) {
+ mCurrentView = currentView.findViewById(mId);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
index ae6a11ffd2ba..abe357ae004c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -164,12 +164,14 @@ public class NavigationBarGestureHelper extends GestureDetector.SimpleOnGestureL
mTouchDownY = (int) event.getY();
if (mNavigationBarView != null) {
- View recentsButton = mNavigationBarView.getRecentsButton();
+ View recentsButton = mNavigationBarView.getRecentsButton().getCurrentView();
if (recentsButton != null) {
mDownOnRecents = mTouchDownX >= recentsButton.getLeft()
&& mTouchDownX <= recentsButton.getRight()
&& mTouchDownY >= recentsButton.getTop()
&& mTouchDownY <= recentsButton.getBottom();
+ } else {
+ mDownOnRecents = false;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
new file mode 100644
index 000000000000..b8ae81f7c3fb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.Space;
+import com.android.systemui.R;
+import com.android.systemui.tuner.TunerService;
+
+import java.util.Objects;
+
+public class NavigationBarInflaterView extends FrameLayout implements TunerService.Tunable {
+
+ private static final String TAG = "NavBarInflater";
+
+ public static final String NAV_BAR_VIEWS = "sysui_nav_bar";
+
+ private static final String MENU_IME = "menu_ime";
+ private static final String BACK = "back";
+ private static final String HOME = "home";
+ private static final String RECENT = "recent";
+ private static final String NAVSPACE = "space";
+
+ public static final String GRAVITY_SEPARATOR = ";";
+ public static final String BUTTON_SEPARATOR = ",";
+
+ private final LayoutInflater mLayoutInflater;
+ private final LayoutInflater mLandscapeInflater;
+
+ private FrameLayout mRot0;
+ private FrameLayout mRot90;
+ private SparseArray<ButtonDispatcher> mButtonDispatchers;
+ private String mCurrentLayout;
+
+ public NavigationBarInflaterView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mLayoutInflater = LayoutInflater.from(context);
+ Configuration landscape = new Configuration();
+ landscape.setTo(context.getResources().getConfiguration());
+ landscape.orientation = Configuration.ORIENTATION_LANDSCAPE;
+ mLandscapeInflater = LayoutInflater.from(context.createConfigurationContext(landscape));
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mRot0 = (FrameLayout) findViewById(R.id.rot0);
+ mRot90 = (FrameLayout) findViewById(R.id.rot90);
+ clearViews();
+ inflateLayout(getDefaultLayout());
+ }
+
+ private String getDefaultLayout() {
+ return mContext.getString(R.string.config_navBarLayout);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ TunerService.get(getContext()).addTunable(this, NAV_BAR_VIEWS);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ TunerService.get(getContext()).removeTunable(this);
+ super.onDetachedFromWindow();
+ }
+
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ if (NAV_BAR_VIEWS.equals(key)) {
+ if (newValue == null) {
+ newValue = getDefaultLayout();
+ }
+ if (!Objects.equals(mCurrentLayout, newValue)) {
+ clearViews();
+ inflateLayout(newValue);
+ }
+ }
+ }
+
+ public void setButtonDispatchers(SparseArray<ButtonDispatcher> buttonDisatchers) {
+ mButtonDispatchers = buttonDisatchers;
+ for (int i = 0; i < buttonDisatchers.size(); i++) {
+ initiallyFill(buttonDisatchers.valueAt(i));
+ }
+ }
+
+ private void initiallyFill(ButtonDispatcher buttonDispatcher) {
+ addAll(buttonDispatcher, (ViewGroup) mRot0.findViewById(R.id.start_group));
+ addAll(buttonDispatcher, (ViewGroup) mRot0.findViewById(R.id.center_group));
+ addAll(buttonDispatcher, (ViewGroup) mRot0.findViewById(R.id.end_group));
+ addAll(buttonDispatcher, (ViewGroup) mRot90.findViewById(R.id.start_group));
+ addAll(buttonDispatcher, (ViewGroup) mRot90.findViewById(R.id.center_group));
+ addAll(buttonDispatcher, (ViewGroup) mRot90.findViewById(R.id.end_group));
+ }
+
+ private void addAll(ButtonDispatcher buttonDispatcher, ViewGroup parent) {
+ for (int i = 0; i < parent.getChildCount(); i++) {
+ // Need to manually search for each id, just in case each group has more than one
+ // of a single id. It probably mostly a waste of time, but shouldn't take long
+ // and will only happen once.
+ if (parent.getChildAt(i).getId() == buttonDispatcher.getId()) {
+ buttonDispatcher.addView(parent.getChildAt(i));
+ } else if (parent.getChildAt(i) instanceof ViewGroup) {
+ addAll(buttonDispatcher, (ViewGroup) parent.getChildAt(i));
+ }
+ }
+ }
+
+ private void inflateLayout(String newLayout) {
+ mCurrentLayout = newLayout;
+ String[] sets = newLayout.split(GRAVITY_SEPARATOR);
+ String[] start = sets[0].split(BUTTON_SEPARATOR);
+ String[] center = sets[1].split(BUTTON_SEPARATOR);
+ String[] end = sets[2].split(BUTTON_SEPARATOR);
+ inflateButtons(start, (ViewGroup) mRot0.findViewById(R.id.start_group),
+ (ViewGroup) mRot0.findViewById(R.id.start_group_lightsout), false);
+ inflateButtons(start, (ViewGroup) mRot90.findViewById(R.id.start_group),
+ (ViewGroup) mRot90.findViewById(R.id.start_group_lightsout), true);
+ inflateButtons(center, (ViewGroup) mRot0.findViewById(R.id.center_group),
+ (ViewGroup) mRot0.findViewById(R.id.start_group_lightsout), false);
+ inflateButtons(center, (ViewGroup) mRot90.findViewById(R.id.center_group),
+ (ViewGroup) mRot90.findViewById(R.id.start_group_lightsout), true);
+ inflateButtons(end, (ViewGroup) mRot0.findViewById(R.id.end_group),
+ (ViewGroup) mRot0.findViewById(R.id.start_group_lightsout), false);
+ inflateButtons(end, (ViewGroup) mRot90.findViewById(R.id.end_group),
+ (ViewGroup) mRot90.findViewById(R.id.start_group_lightsout), true);
+ }
+
+ private void inflateButtons(String[] buttons, ViewGroup parent, ViewGroup lightsOutParent,
+ boolean landscape) {
+ for (int i = 0; i < buttons.length; i++) {
+ copyToLightsout(inflateButton(buttons[i], parent, landscape), lightsOutParent);
+ }
+ }
+
+ private void copyToLightsout(View view, ViewGroup lightsOutParent) {
+ if (view instanceof FrameLayout) {
+ // The only ViewGroup we support in here is a FrameLayout, so copy those manually.
+ FrameLayout original = (FrameLayout) view;
+ FrameLayout layout = new FrameLayout(view.getContext());
+ for (int i = 0; i < original.getChildCount(); i++) {
+ copyToLightsout(original.getChildAt(i), layout);
+ }
+ lightsOutParent.addView(layout, copy(view.getLayoutParams()));
+ } else if (view instanceof Space) {
+ lightsOutParent.addView(new Space(view.getContext()), copy(view.getLayoutParams()));
+ } else {
+ lightsOutParent.addView(generateLightsOutView(view), copy(view.getLayoutParams()));
+ }
+ }
+
+ private View generateLightsOutView(View view) {
+ ImageView imageView = new ImageView(view.getContext());
+ // Copy everything we can about the original view.
+ imageView.setPadding(view.getPaddingLeft(), view.getPaddingTop(), view.getPaddingRight(),
+ view.getPaddingBottom());
+ imageView.setContentDescription(view.getContentDescription());
+ imageView.setId(view.getId());
+ // Only home gets a big dot, everything else will be little.
+ imageView.setImageResource(view.getId() == R.id.home
+ ? R.drawable.ic_sysbar_lights_out_dot_large
+ : R.drawable.ic_sysbar_lights_out_dot_small);
+ return imageView;
+ }
+
+ private ViewGroup.LayoutParams copy(ViewGroup.LayoutParams layoutParams) {
+ return new LayoutParams(layoutParams.width, layoutParams.height);
+ }
+
+ private View inflateButton(String button, ViewGroup parent, boolean landscape) {
+ View v = null;
+ if (HOME.equals(button)) {
+ v = (landscape ? mLandscapeInflater : mLayoutInflater)
+ .inflate(R.layout.home, parent, false);
+ if (landscape && isSw600Dp()) {
+ setupLandButton(v);
+ }
+ } else if (BACK.equals(button)) {
+ v = (landscape ? mLandscapeInflater : mLayoutInflater)
+ .inflate(R.layout.back, parent, false);
+ if (landscape && isSw600Dp()) {
+ setupLandButton(v);
+ }
+ } else if (RECENT.equals(button)) {
+ v = (landscape ? mLandscapeInflater : mLayoutInflater)
+ .inflate(R.layout.recent_apps, parent, false);
+ if (landscape && isSw600Dp()) {
+ setupLandButton(v);
+ }
+ } else if (MENU_IME.equals(button)) {
+ v = (landscape ? mLandscapeInflater : mLayoutInflater)
+ .inflate(R.layout.menu_ime, parent, false);
+ } else if (NAVSPACE.equals(button)) {
+ v = (landscape ? mLandscapeInflater : mLayoutInflater)
+ .inflate(R.layout.nav_key_space, parent, false);
+ } else {
+ throw new IllegalArgumentException("Unknown button " + button);
+ }
+ parent.addView(v);
+ if (mButtonDispatchers != null) {
+ final int indexOfKey = mButtonDispatchers.indexOfKey(v.getId());
+ if (indexOfKey >= 0) {
+ mButtonDispatchers.valueAt(indexOfKey).addView(v);
+ }
+ }
+ return v;
+ }
+
+ private boolean isSw600Dp() {
+ Configuration configuration = mContext.getResources().getConfiguration();
+ return (configuration.smallestScreenWidthDp >= 600);
+ }
+
+ /**
+ * This manually sets the width of sw600dp landscape buttons because despite
+ * overriding the configuration from the overridden resources aren't loaded currently.
+ */
+ private void setupLandButton(View v) {
+ Resources res = mContext.getResources();
+ v.getLayoutParams().width = res.getDimensionPixelOffset(
+ R.dimen.navigation_key_width_sw600dp_land);
+ int padding = res.getDimensionPixelOffset(R.dimen.navigation_key_padding_sw600dp_land);
+ v.setPadding(padding, v.getPaddingTop(), padding, v.getPaddingBottom());
+ }
+
+ private void clearViews() {
+ if (mButtonDispatchers != null) {
+ for (int i = 0; i < mButtonDispatchers.size(); i++) {
+ mButtonDispatchers.valueAt(i).clear();
+ }
+ }
+ clearAllChildren((ViewGroup) mRot0.findViewById(R.id.nav_buttons));
+ clearAllChildren((ViewGroup) mRot0.findViewById(R.id.lights_out));
+ clearAllChildren((ViewGroup) mRot90.findViewById(R.id.nav_buttons));
+ clearAllChildren((ViewGroup) mRot90.findViewById(R.id.lights_out));
+ }
+
+ private void clearAllChildren(ViewGroup group) {
+ for (int i = 0; i < group.getChildCount(); i++) {
+ ((ViewGroup) group.getChildAt(i)).removeAllViews();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 5309903266aa..839b57956f9a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -35,6 +35,7 @@ import android.os.Message;
import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.SparseArray;
import android.view.Display;
import android.view.Gravity;
import android.view.IDockedStackListener.Stub;
@@ -45,15 +46,11 @@ import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.inputmethod.InputMethodManager;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
import android.widget.LinearLayout;
-
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.policy.DeadZone;
-import com.android.systemui.statusbar.policy.KeyButtonView;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -101,6 +98,8 @@ public class NavigationBarView extends LinearLayout {
private boolean mWakeAndUnlocking;
private boolean mCarMode = false;
+ private final SparseArray<ButtonDispatcher> mButtonDisatchers = new SparseArray<>();
+
private class NavTransitionListener implements TransitionListener {
private boolean mBackTransitioning;
private boolean mHomeAppearing;
@@ -132,13 +131,12 @@ public class NavigationBarView extends LinearLayout {
}
public void onBackAltCleared() {
- View backButton = getBackButton();
- View homeButton = getHomeButton();
+ ButtonDispatcher backButton = getBackButton();
// When dismissing ime during unlock, force the back button to run the same appearance
// animation as home (if we catch this condition early enough).
- if (backButton != null && !mBackTransitioning && backButton.getVisibility() == VISIBLE
- && mHomeAppearing && homeButton != null && getHomeButton().getAlpha() == 0) {
+ if (!mBackTransitioning && backButton.getVisibility() == VISIBLE
+ && mHomeAppearing && getHomeButton().getAlpha() == 0) {
getBackButton().setAlpha(0);
ValueAnimator a = ObjectAnimator.ofFloat(backButton, "alpha", 0, 1);
a.setStartDelay(mStartDelay);
@@ -194,6 +192,12 @@ public class NavigationBarView extends LinearLayout {
getIcons(context);
mBarTransitions = new NavigationBarTransitions(this);
+
+ mButtonDisatchers.put(R.id.back, new ButtonDispatcher(R.id.back));
+ mButtonDisatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
+ mButtonDisatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
+ mButtonDisatchers.put(R.id.menu, new ButtonDispatcher(R.id.menu));
+ mButtonDisatchers.put(R.id.ime_switcher, new ButtonDispatcher(R.id.ime_switcher));
}
public BarTransitions getBarTransitions() {
@@ -226,10 +230,7 @@ public class NavigationBarView extends LinearLayout {
}
public void abortCurrentGesture() {
- View homeButton = getHomeButton();
- if (homeButton != null) {
- getHomeButton().abortCurrentGesture();
- }
+ getHomeButton().abortCurrentGesture();
}
private H mHandler = new H();
@@ -242,31 +243,24 @@ public class NavigationBarView extends LinearLayout {
return mRotatedViews;
}
- // The following Buttons can possibly return null if NavigationBarView is extended to provide
- // a different layout and the buttons do not exist in that new layout.
- @Nullable
- public KeyButtonView getRecentsButton() {
- return (KeyButtonView) getCurrentView().findViewById(R.id.recent_apps);
+ public ButtonDispatcher getRecentsButton() {
+ return mButtonDisatchers.get(R.id.recent_apps);
}
- @Nullable
- public View getMenuButton() {
- return getCurrentView().findViewById(R.id.menu);
+ public ButtonDispatcher getMenuButton() {
+ return mButtonDisatchers.get(R.id.menu);
}
- @Nullable
- public View getBackButton() {
- return getCurrentView().findViewById(R.id.back);
+ public ButtonDispatcher getBackButton() {
+ return mButtonDisatchers.get(R.id.back);
}
- @Nullable
- public KeyButtonView getHomeButton() {
- return (KeyButtonView) getCurrentView().findViewById(R.id.home);
+ public ButtonDispatcher getHomeButton() {
+ return mButtonDisatchers.get(R.id.home);
}
- @Nullable
- public View getImeSwitchButton() {
- return getCurrentView().findViewById(R.id.ime_switcher);
+ public ButtonDispatcher getImeSwitchButton() {
+ return mButtonDisatchers.get(R.id.ime_switcher);
}
@Nullable
@@ -344,26 +338,19 @@ public class NavigationBarView extends LinearLayout {
? getBackIconWithAlt(mCarMode, mVertical)
: getBackIcon(mCarMode, mVertical);
- View backButton = getBackButton();
- if (backButton != null && backButton instanceof ImageView) {
- ((ImageView) backButton).setImageDrawable(backIcon);
- }
+ getBackButton().setImageDrawable(backIcon);
- ImageView recentsButton = getRecentsButton();
- if (recentsButton != null) {
- recentsButton.setImageDrawable(mVertical ? mRecentLandIcon : mRecentIcon);
- }
+ getRecentsButton().setImageDrawable(
+ mVertical ? mRecentLandIcon : mRecentIcon);
- ImageView homeButton = getHomeButton();
- if (homeButton != null) {
- homeButton.setImageDrawable(mCarMode ? mHomeCarModeIcon : mHomeDefaultIcon);
+ if (mCarMode) {
+ getHomeButton().setImageDrawable(mHomeCarModeIcon);
+ } else {
+ getHomeButton().setImageDrawable(mHomeDefaultIcon);
}
final boolean showImeButton = ((hints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0);
- View imeSwitchButton = getImeSwitchButton();
- if (imeSwitchButton != null) {
- imeSwitchButton.setVisibility(showImeButton ? View.VISIBLE : View.INVISIBLE);
- }
+ getImeSwitchButton().setVisibility(showImeButton ? View.VISIBLE : View.INVISIBLE);
// Update menu button in case the IME state has changed.
setMenuVisibility(mShowMenu, true);
@@ -405,20 +392,9 @@ public class NavigationBarView extends LinearLayout {
disableRecent = false;
}
- View backButton = getBackButton();
- if (backButton != null) {
- backButton.setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
- }
-
- View homeButton = getHomeButton();
- if (homeButton != null) {
- homeButton.setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
- }
-
- View recentsButton = getRecentsButton();
- if (recentsButton != null) {
- recentsButton.setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
- }
+ getBackButton().setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
+ getHomeButton().setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
+ getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
// The app shelf, if it exists, follows the visibility of the home button.
View appShelf = getAppShelf();
@@ -510,10 +486,7 @@ public class NavigationBarView extends LinearLayout {
final boolean shouldShow = mShowMenu &&
((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) == 0);
- View menuButton = getMenuButton();
- if (menuButton != null) {
- menuButton.setVisibility(shouldShow ? View.VISIBLE : View.INVISIBLE);
- }
+ getMenuButton().setVisibility(shouldShow ? View.VISIBLE : View.INVISIBLE);
}
@Override
@@ -526,11 +499,13 @@ public class NavigationBarView extends LinearLayout {
mRotatedViews[Surface.ROTATION_270] = mRotatedViews[Surface.ROTATION_90];
mCurrentView = mRotatedViews[Surface.ROTATION_0];
-
- View imeSwitchButton = getImeSwitchButton();
- if (imeSwitchButton != null) {
- imeSwitchButton.setOnClickListener(mImeSwitcherClickListener);
+ for (int i = 0; i < mButtonDisatchers.size(); i++) {
+ mButtonDisatchers.valueAt(i).setCurrentView(mCurrentView);
}
+ ((NavigationBarInflaterView) findViewById(R.id.navigation_inflater)).setButtonDispatchers(
+ mButtonDisatchers);
+
+ getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
updateRTLOrder();
@@ -556,13 +531,9 @@ public class NavigationBarView extends LinearLayout {
}
private void updateRecentsIcon(boolean dockedStackExists) {
- ImageView recentsButton = getRecentsButton();
-
- if (recentsButton != null) {
- recentsButton.setImageResource(dockedStackExists
- ? R.drawable.ic_sysbar_docked
- : R.drawable.ic_sysbar_recent);
- }
+ getRecentsButton().setImageResource(dockedStackExists
+ ? R.drawable.ic_sysbar_docked
+ : R.drawable.ic_sysbar_recent);
}
public boolean isVertical() {
@@ -576,12 +547,12 @@ public class NavigationBarView extends LinearLayout {
}
mCurrentView = mRotatedViews[rot];
mCurrentView.setVisibility(View.VISIBLE);
+ for (int i = 0; i < mButtonDisatchers.size(); i++) {
+ mButtonDisatchers.valueAt(i).setCurrentView(mCurrentView);
+ }
updateLayoutTransitionsEnabled();
- View imeSwitchButton = getImeSwitchButton();
- if (imeSwitchButton != null) {
- imeSwitchButton.setOnClickListener(mImeSwitcherClickListener);
- }
+ getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);
@@ -669,33 +640,16 @@ public class NavigationBarView extends LinearLayout {
// We swap all children of the 90 and 270 degree layouts, since they are vertical
View rotation90 = mRotatedViews[Surface.ROTATION_90];
- swapChildrenOrderIfVertical(rotation90.findViewById(R.id.nav_buttons));
- adjustExtraKeyGravity(rotation90, isLayoutRtl);
+ swapChildrenOrderIfVertical(rotation90);
View rotation270 = mRotatedViews[Surface.ROTATION_270];
if (rotation90 != rotation270) {
- swapChildrenOrderIfVertical(rotation270.findViewById(R.id.nav_buttons));
- adjustExtraKeyGravity(rotation270, isLayoutRtl);
+ swapChildrenOrderIfVertical(rotation270);
}
mIsLayoutRtl = isLayoutRtl;
}
}
- private void adjustExtraKeyGravity(View navBar, boolean isLayoutRtl) {
- View menu = navBar.findViewById(R.id.menu);
- View imeSwitcher = navBar.findViewById(R.id.ime_switcher);
- if (menu != null) {
- FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) menu.getLayoutParams();
- lp.gravity = isLayoutRtl ? Gravity.BOTTOM : Gravity.TOP;
- menu.setLayoutParams(lp);
- }
- if (imeSwitcher != null) {
- FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) imeSwitcher.getLayoutParams();
- lp.gravity = isLayoutRtl ? Gravity.BOTTOM : Gravity.TOP;
- imeSwitcher.setLayoutParams(lp);
- }
- }
-
/**
* Swaps the children order of a LinearLayout if it's orientation is Vertical
*
@@ -705,6 +659,11 @@ public class NavigationBarView extends LinearLayout {
if (group instanceof LinearLayout) {
LinearLayout linearLayout = (LinearLayout) group;
if (linearLayout.getOrientation() == VERTICAL) {
+ if ((linearLayout.getGravity() & Gravity.TOP) != 0) {
+ linearLayout.setGravity(Gravity.BOTTOM);
+ } else if ((linearLayout.getGravity() & Gravity.BOTTOM) != 0) {
+ linearLayout.setGravity(Gravity.TOP);
+ }
int childCount = linearLayout.getChildCount();
ArrayList<View> childList = new ArrayList<>(childCount);
for (int i = 0; i < childCount; i++) {
@@ -715,6 +674,11 @@ public class NavigationBarView extends LinearLayout {
linearLayout.addView(childList.get(i));
}
}
+ } else if (group instanceof ViewGroup) {
+ ViewGroup viewGroup = (ViewGroup) group;
+ for (int i = 0; i < viewGroup.getChildCount(); i++) {
+ swapChildrenOrderIfVertical(viewGroup.getChildAt(i));
+ }
}
}
@@ -802,13 +766,12 @@ public class NavigationBarView extends LinearLayout {
pw.println(" }");
}
- private static void dumpButton(PrintWriter pw, String caption, View button) {
+ private static void dumpButton(PrintWriter pw, String caption, ButtonDispatcher button) {
pw.print(" " + caption + ": ");
if (button == null) {
pw.print("null");
} else {
- pw.print(PhoneStatusBar.viewInfo(button)
- + " " + visibilityToString(button.getVisibility())
+ pw.print(visibilityToString(button.getVisibility())
+ " alpha=" + button.getAlpha()
);
}
@@ -818,4 +781,5 @@ public class NavigationBarView extends LinearLayout {
public interface OnVerticalChangedListener {
void onVerticalChanged(boolean isVertical);
}
+
}
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 71b6713aaba5..ffc836c7bbf8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -293,7 +293,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
Display mDisplay;
Point mCurrentDisplaySize = new Point();
- StatusBarWindowView mStatusBarWindow;
+ protected StatusBarWindowView mStatusBarWindow;
PhoneStatusBarView mStatusBarView;
private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
protected StatusBarWindowManager mStatusBarWindowManager;
@@ -673,8 +673,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
updateDisplaySize(); // populates mDisplayMetrics
updateResources();
- mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
- R.layout.super_status_bar, null);
+ inflateStatusBarWindow(context);
mStatusBarWindow.setService(this);
mStatusBarWindow.setOnTouchListener(new View.OnTouchListener() {
@Override
@@ -935,6 +934,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
return mStatusBarView;
}
+ protected void inflateStatusBarWindow(Context context) {
+ mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
+ R.layout.super_status_bar, null);
+ }
+
protected void createNavigationBarView(Context context) {
inflateNavigationBarView(context);
mNavigationBarView.setDisabledFlags(mDisabled1);
@@ -1185,25 +1189,19 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private void prepareNavigationBarView() {
mNavigationBarView.reorient();
- View recentsButton = mNavigationBarView.getRecentsButton();
- if (recentsButton != null) {
- recentsButton.setOnClickListener(mRecentsClickListener);
- recentsButton.setOnTouchListener(mRecentsPreloadOnTouchListener);
- recentsButton.setLongClickable(true);
- recentsButton.setOnLongClickListener(mRecentsLongClickListener);
- }
+ ButtonDispatcher recentsButton = mNavigationBarView.getRecentsButton();
+ recentsButton.setOnClickListener(mRecentsClickListener);
+ recentsButton.setOnTouchListener(mRecentsPreloadOnTouchListener);
+ recentsButton.setLongClickable(true);
+ recentsButton.setOnLongClickListener(mRecentsLongClickListener);
- View backButton = mNavigationBarView.getBackButton();
- if (backButton != null) {
- backButton.setLongClickable(true);
- backButton.setOnLongClickListener(mLongPressBackListener);
- }
+ ButtonDispatcher backButton = mNavigationBarView.getBackButton();
+ backButton.setLongClickable(true);
+ backButton.setOnLongClickListener(mLongPressBackListener);
- View homeButton = mNavigationBarView.getHomeButton();
- if (homeButton != null) {
- homeButton.setOnTouchListener(mHomeActionListener);
- homeButton.setOnLongClickListener(mLongPressHomeListener);
- }
+ ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
+ homeButton.setOnTouchListener(mHomeActionListener);
+ homeButton.setOnLongClickListener(mLongPressHomeListener);
mAssistManager.onConfigurationChanged();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java
new file mode 100644
index 000000000000..da16954d0d46
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+/**
+ * Automatically reverses the order of children as they are added.
+ * Also reverse the width and height values of layout params
+ */
+public class ReverseLinearLayout extends LinearLayout {
+
+ public ReverseLinearLayout(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public void addView(View child) {
+ reversParams(child.getLayoutParams());
+ super.addView(child, 0);
+ }
+
+ @Override
+ public void addView(View child, ViewGroup.LayoutParams params) {
+ reversParams(params);
+ super.addView(child, 0, params);
+ }
+
+ private void reversParams(ViewGroup.LayoutParams params) {
+ if (params == null) {
+ return;
+ }
+ int width = params.width;
+ params.width = params.height;
+ params.height = width;
+ }
+
+}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 234c94e6faa7..d63dd0c8d03a 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -676,8 +676,13 @@ public class BackupManagerService {
return true;
}
+ // Checks if the app is in a stopped state, that means it won't receive broadcasts.
+ private static boolean appIsStopped(ApplicationInfo app) {
+ return ((app.flags & ApplicationInfo.FLAG_STOPPED) != 0);
+ }
+
/* does *not* check overall backup eligibility policy! */
- public static boolean appGetsFullBackup(PackageInfo pkg) {
+ private static boolean appGetsFullBackup(PackageInfo pkg) {
if (pkg.applicationInfo.backupAgentName != null) {
// If it has an agent, it gets full backups only if it says so
return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FULL_BACKUP_ONLY) != 0;
@@ -2758,7 +2763,7 @@ public class BackupManagerService {
return;
}
- if ((mCurrentPackage.applicationInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0) {
+ if (appIsStopped(mCurrentPackage.applicationInfo)) {
// The app has been force-stopped or cleared or just installed,
// and not yet launched out of that state, so just as it won't
// receive broadcasts, we won't run it for backup.
@@ -4179,28 +4184,18 @@ public class BackupManagerService {
try {
PackageInfo info = mPackageManager.getPackageInfo(pkg,
PackageManager.GET_SIGNATURES);
- if ((info.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) == 0
- || pkg.equals(SHARED_BACKUP_AGENT_PACKAGE)) {
+ if (!appIsEligibleForBackup(info.applicationInfo)) {
// Cull any packages that have indicated that backups are not permitted,
+ // that run as system-domain uids but do not define their own backup agents,
// as well as any explicit mention of the 'special' shared-storage agent
// package (we handle that one at the end).
if (MORE_DEBUG) {
- Slog.d(TAG, "Ignoring opted-out package " + pkg);
- }
- sendBackupOnResult(mBackupObserver, pkg,
- BackupManager.ERROR_BACKUP_NOT_ALLOWED);
- continue;
- } else if ((info.applicationInfo.uid < Process.FIRST_APPLICATION_UID)
- && (info.applicationInfo.backupAgentName == null)) {
- // Cull any packages that run as system-domain uids but do not define their
- // own backup agents
- if (MORE_DEBUG) {
- Slog.d(TAG, "Ignoring non-agent system package " + pkg);
+ Slog.d(TAG, "Ignoring not eligible package " + pkg);
}
sendBackupOnResult(mBackupObserver, pkg,
- BackupManager.ERROR_BACKUP_NOT_ALLOWED);
+ BackupManager.ERROR_BACKUP_NOT_ALLOWED);
continue;
- } else if ((info.applicationInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0) {
+ } else if (appIsStopped(info.applicationInfo)) {
// Cull any packages in the 'stopped' state: they've either just been
// installed or have explicitly been force-stopped by the user. In both
// cases we do not want to launch them for backup.
@@ -9538,6 +9533,32 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
}
}
+ public boolean isAppEligibleForBackup(String packageName) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
+ "isAppEligibleForBackup");
+ try {
+ PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName,
+ PackageManager.GET_SIGNATURES);
+ if (!appIsEligibleForBackup(packageInfo.applicationInfo) ||
+ appIsStopped(packageInfo.applicationInfo)) {
+ return false;
+ }
+ IBackupTransport transport = getTransport(mCurrentTransport);
+ if (transport != null) {
+ try {
+ return transport.isAppEligibleForBackup(packageInfo,
+ appGetsFullBackup(packageInfo));
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to contact transport");
+ }
+ }
+ // If transport is not present we couldn't tell that the package is not eligible.
+ return true;
+ } catch (NameNotFoundException e) {
+ return false;
+ }
+ }
+
// ----- Restore session -----
class ActiveRestoreSession extends IRestoreSession.Stub {
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index 505a1a53d25f..bbf881be102f 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -326,6 +326,12 @@ public class Trampoline extends IBackupManager.Stub {
}
@Override
+ public boolean isAppEligibleForBackup(String packageName) {
+ BackupManagerService svc = mService;
+ return (svc != null) ? svc.isAppEligibleForBackup(packageName) : false;
+ }
+
+ @Override
public int requestBackup(String[] packages, IBackupObserver observer) throws RemoteException {
BackupManagerService svc = mService;
return (svc != null) ? svc.requestBackup(packages, observer) : null;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index eb759140bbf6..f68a2996541d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -67,6 +67,7 @@ import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.graphics.Bitmap;
+import android.graphics.Color;
import android.media.AudioManager;
import android.media.IAudioService;
import android.net.ConnectivityManager;
@@ -487,6 +488,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private static final String TAG_SHORT_SUPPORT_MESSAGE = "short-support-message";
private static final String TAG_LONG_SUPPORT_MESSAGE = "long-support-message";
private static final String TAG_PARENT_ADMIN = "parent-admin";
+ private static final String TAG_ORGANIZATION_COLOR = "organization-color";
final DeviceAdminInfo info;
@@ -580,6 +582,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
String shortSupportMessage = null;
String longSupportMessage = null;
+ // Background color of confirm credentials screen. Default: gray.
+ static final int DEF_ORGANIZATION_COLOR = Color.GRAY;
+ int organizationColor = DEF_ORGANIZATION_COLOR;
+
ActiveAdmin(DeviceAdminInfo _info, boolean parent) {
info = _info;
isParent = parent;
@@ -787,6 +793,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
parentAdmin.writeToXml(out);
out.endTag(null, TAG_PARENT_ADMIN);
}
+ if (organizationColor != DEF_ORGANIZATION_COLOR) {
+ out.startTag(null, TAG_ORGANIZATION_COLOR);
+ out.attribute(null, ATTR_VALUE, Integer.toString(organizationColor));
+ out.endTag(null, TAG_ORGANIZATION_COLOR);
+ }
}
void writePackageListToXml(XmlSerializer out, String outerTag,
@@ -920,6 +931,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} else if (TAG_PARENT_ADMIN.equals(tag)) {
parentAdmin = new ActiveAdmin(info, /* parent */ true);
parentAdmin.readFromXml(parser);
+ } else if (TAG_ORGANIZATION_COLOR.equals(tag)) {
+ organizationColor = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
} else {
Slog.w(LOG_TAG, "Unknown admin tag: " + tag);
XmlUtils.skipCurrentTag(parser);
@@ -7685,4 +7699,46 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
return null;
}
+
+ @Override
+ public void setOrganizationColor(@NonNull ComponentName who, int color) {
+ final int userHandle = mInjector.userHandleGetCallingUserId();
+ if (!mHasFeature || !isManagedProfile(userHandle)) {
+ return;
+ }
+ Preconditions.checkNotNull(who, "ComponentName is null");
+ synchronized (this) {
+ ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ admin.organizationColor = color;
+ saveSettingsLocked(userHandle);
+ }
+ }
+
+ @Override
+ public int getOrganizationColor(@NonNull ComponentName who) {
+ final int userHandle = mInjector.userHandleGetCallingUserId();
+ if (!mHasFeature || !isManagedProfile(userHandle)) {
+ return ActiveAdmin.DEF_ORGANIZATION_COLOR;
+ }
+ synchronized (this) {
+ ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ return admin.organizationColor;
+ }
+ }
+
+ @Override
+ public int getOrganizationColorForUser(int userHandle) {
+ if (!mHasFeature || !isManagedProfile(userHandle)) {
+ return ActiveAdmin.DEF_ORGANIZATION_COLOR;
+ }
+ enforceCrossUsersPermission(userHandle);
+ synchronized (this) {
+ ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userHandle);
+ return (profileOwner != null)
+ ? profileOwner.organizationColor
+ : ActiveAdmin.DEF_ORGANIZATION_COLOR;
+ }
+ }
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index 08258c99c25e..037ce57ced1b 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -492,6 +492,11 @@ public class BridgePackageManager extends PackageManager {
}
@Override
+ public Drawable getUserBadgeForDensityNoBackground(UserHandle user, int density) {
+ return null;
+ }
+
+ @Override
public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) {
return null;
}